cutlass入门: 调用cutlass做通用矩阵乘法Gemm(附代码)

这篇具有很好参考价值的文章主要介绍了cutlass入门: 调用cutlass做通用矩阵乘法Gemm(附代码)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

cutlass是CUDA C++模板抽象的集合,用于实现CUDA中所有级别和规模的高性能矩阵乘法(GEMM)和相关计算。相较于cuBLAS和cuDNN,cutlass中包含了更多可重用的模块化软件组件,这使得cutlass相较于前两者更为灵活。

cutlass项目官方网站:GitHub - NVIDIA/cutlass: CUDA Templates for Linear Algebra Subroutines

本文将展示如何用cutlass实现最基本的矩阵计算。

cutlass的使用流程与普通kernel大致相同:先在host端分配空间生成数据,再将host端的数据传入device端的buffer中,输入参数调用cutlass模块进行运算,最后将device端的数据传回Host端。

本代码实现的矩阵计算为D = α * A * B + β * C。其中,标量α = β = 1,矩阵A的大小为3840*4096,矩阵B的大小为4096*4096,矩阵C的大小为3840*4096。这三个矩阵均被初始化为全部元素为1的矩阵。那么经过简单计算我们可以知道矩阵D所包含的全部元素应该为4097。

代码及注释如下:

#include <iostream>                                           // 标准输入输出流
#include "cutlass/gemm/device/gemm.h"                         // 引入cutlass头文件

using ColumnMajor = cutlass::layout::ColumnMajor;             // 列主序存储方式
using RowMajor    = cutlass::layout::RowMajor;                // 行主序存储方式

using CutlassGemm = cutlass::gemm::device::Gemm<float,        // A矩阵数据类型
                                                RowMajor,     // A矩阵存储方式
                                                float,        // B矩阵数据类型
                                                RowMajor,     // B矩阵存储方式
                                                float,        // C矩阵数据类型
                                                RowMajor>;    // C矩阵存储方式

void generate_tensor_2D(float *ptr, int i_M, int i_N){        // 二维矩阵填充函数(此处全部填充1)
    for(int i = 0; i < i_M; i++){
        for(int j = 0; j < i_N; j++){
            *(ptr + i*i_N + j ) = 1.0;
        }
    }
}

int main(int argc, const char *arg[]) {

    int M = 3840;           //M
    int N = 4096;           //N
    int K = 4096;           //K

    int lda = K;
    int ldb = K;
    int ldc = N;
    int ldd = N;

    float alpha = 1.0;      //alpha
    float beta = 1.0;       //beta

    float *A;               //申明A矩阵host端指针
    float *B;               //申明B矩阵host端指针
    float *C;               //申明C矩阵host端指针
    float *D;               //申明D矩阵host端指针

    size_t A_mem_size = sizeof(float) * M * K; //memory size of matrix A = M * K * sizeof(float)
    size_t B_mem_size = sizeof(float) * K * N; //memory size of matrix B = K * N * sizeof(float)
    size_t C_mem_size = sizeof(float) * M * N; //memory size of matrix C = M * N * sizeof(float)
    size_t D_mem_size = sizeof(float) * M * N; //memory size of matrix C = M * N * sizeof(float)

    A = (float*)malloc(A_mem_size);  // host端A矩阵分配内存
    B = (float*)malloc(B_mem_size);  // host端B矩阵分配内存
    C = (float*)malloc(C_mem_size);  // host端C矩阵分配内存
    D = (float*)malloc(D_mem_size);  // host端D矩阵分配内存

    generate_tensor_2D(A, M, K);     // 填充A矩阵
    generate_tensor_2D(B, K, N);     // 填充B矩阵  
    generate_tensor_2D(C, M, N);     // 填充C矩阵  

    float *d_A;            // 申明device端A矩阵的指针
    float *d_B;            // 申明device端B矩阵的指针
    float *d_C;            // 申明device端C矩阵的指针
    float *d_D;            // 申明device端D矩阵的指针

    cudaMalloc((void**)&d_A, A_mem_size);  // device端为A矩阵分配内存
    cudaMalloc((void**)&d_B, B_mem_size);  // device端为B矩阵分配内存
    cudaMalloc((void**)&d_C, C_mem_size);  // device端为C矩阵分配内存
    cudaMalloc((void**)&d_D, D_mem_size);  // device端为D矩阵分配内存

    cudaMemcpy(d_A, A, A_mem_size, cudaMemcpyHostToDevice); // 将矩阵A的数据传递到device端
    cudaMemcpy(d_B, B, B_mem_size, cudaMemcpyHostToDevice); // 将矩阵B的数据传递到device端
    cudaMemcpy(d_C, C, C_mem_size, cudaMemcpyHostToDevice); // 将矩阵C的数据传递到device端

    CutlassGemm gemm_operator;                  // 申明cutlassgemm类
    CutlassGemm::Arguments args({M, N, K},      // Gemm Problem dimensions
                                {d_A, lda},     // source matrix A
                                {d_B, ldb},     // source matrix B
                                {d_C, ldc},     // source matrix C
                                {d_D, ldd},     // destination matrix D
                                {alpha, beta}); // alpha & beta
    gemm_operator(args); //运行Gemm

    cudaMemcpy(D, d_D, D_mem_size, cudaMemcpyDeviceToHost);  //将运行结果D矩阵传回host端
    std::cout << D[0] << std::endl;                          //打印D中第一行第一个数据
    std::cout << D[M * N - 1] << std::endl;                  //打印D中最后一行最后一个数据

    return 0;
}   

代码编译:

$nvcc -I <PATH TO CUTLASS>/include <YOUR SOURCE FILE>

运行结果如下:

nvidia cutlass,深度学习,人工智能,c++

 可见,本程序运行成功利用cutlass实现了D = α * A * B + β * C的矩阵计算。

*本文章及程序仅供交流学习,请勿用作商业用途。转载请告知作者。文章来源地址https://www.toymoban.com/news/detail-532793.html

到了这里,关于cutlass入门: 调用cutlass做通用矩阵乘法Gemm(附代码)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • VS2015+cublas实操记录(cuda加速GEMM矩阵乘加算子)

    cuda安装后一般的安装位置在: C:Program FilesNVIDIA GPU Computing ToolkitCUDAv11.8 把这个目录下的include和lib分别配置在vs中,安装cuda教程可参考: https://zhuanlan.zhihu.com/p/520995962 (笔者实操ok版本:win11+cuda11.8+cdunn8.2.1.32+trt8.5.3.1)。 另外还要记得添加 附加依赖项 : 不然会报错: err

    2024年02月13日
    浏览(41)
  • 【GEMM预备工作】行主序和列主序矩阵的内存中的连续性,解决理解问题

    在内存存储中,默认矩阵是按照行优先储存的,即矩阵的每一列在内存中是连续的。行优先矩阵储存中行数据是不连续的。 而对于列主序的矩阵,是按照列优先储存的,即矩阵的每一行在内存中是连续的。列优先矩阵储存中列数据是不连续的:  

    2024年02月14日
    浏览(34)
  • 【矩阵乘法】C++实现外部矩阵乘法

    ​ 使用文件和内存模拟系统缓存,并利用矩阵乘法验证实际和理论情况。 设计一个 Matrix 类,其中 Matrix 是存在磁盘中的一个二进制文件,类通过保存的矩阵属性来读取磁盘。前八个字节为两个 int32 ,保存矩阵的行列数。 Matrix中有一个 buffer 成员为读取到的数据缓存,通过

    2024年02月11日
    浏览(39)
  • 矩阵乘法(矩阵乘矩阵)

    首先理了解矩阵是什么: 矩阵是一个按照长方阵列排列的复数或实数集合。(相信大家都懂) 关于矩阵的基本概念: 1.方阵:n 阶方阵 (正方形嘛) 2.同型矩阵:两个矩阵,行数与列数对应相同,称为同型矩阵 矩阵加减法: 在了解矩阵乘法前先看看矩阵加减法: 1.两个矩阵

    2024年02月08日
    浏览(58)
  • 矩阵算法之矩阵乘法

    矩阵算法在图像处理、神经网络、模式识别等领域有着广泛的用途。 在矩阵乘法中,A矩阵和B矩阵可以做乘法运算必须满足A矩阵的列的数量等于B矩阵的行的数量。 运算规则:A的每一行中的数字对应乘以B的每一列的数字把结果相加起来。 1、当矩阵A的列数(column)等于矩阵

    2024年02月11日
    浏览(39)
  • Python调用最小二乘法

    所谓线性最小二乘法,可以理解为是解方程的延续,区别在于,当未知量远小于方程数的时候,将得到一个无解的问题。最小二乘法的实质,是保证误差最小的情况下对未知数进行赋值。 最小二乘法是非常经典的算法,而且这个名字我们在高中的时候就已经接触了,属于极其

    2024年02月01日
    浏览(49)
  • 【线性代数】从矩阵分块的角度理解矩阵乘法

    概念: 例: 1. 分块矩阵计算的数学步骤 使用Numpy计算例1 按列分块 按行分块 分块后的计算公式 矩阵分块法提供了行数和列数较多的矩阵相乘的一种计算方法,以此来简化矩阵相乘的运算次数; 按行列分块将矩阵A分为n个列向量和m个行向量,利用矩阵乘法的定义,殊途同归

    2024年02月13日
    浏览(68)
  • 矩阵乘法优化:4x4矩阵块优化方法

    MMult_4x4_3.h 一次计算C中的4x4小块 0.24gflops 2.1% 1 MMult_4x4_4.h 一次计算C中的4x4小块 0.24gflops 2.1% 1 MMult_4x4_5.h 一次计算C中的4x4小块,将16个循环合并一个 0.25gflops 2.2% 1 MMult_4x4_6.h 一次计算C中的4x4小块(我们在寄存器中累加C的元素,并对a的元素使用寄存器) 1.75gflops 16.0% 1 MMult_4x4_7.h 在

    2024年02月15日
    浏览(50)
  • 使用cublas实现矩阵乘法

    使用CUDA写一个矩阵乘法 C = A X B (矩阵维度: A: M X K, B: K X N, C: M X N ),当然可以自己写核函数,但效率不如CUDA自带的 cublas 算法效率高。使用 cublas 唯一值得注意的地方是, 在CPU中的矩阵数据存储是行优先存储,而在GPU中是列优先存储 ,这相当于对原矩阵做了一次转置,我

    2024年02月16日
    浏览(43)
  • 矩阵乘法,python简易实现

    1.首先,先了解下矩阵乘法最基本的工作原理,可简易得理解成 C矩阵(i, j)的值是 由A矩阵 i 行依次与B矩阵 j 列相乘的求和,即:  2.demo实现 3、基于矩阵结果是行和列的对应相乘的累和迭代,所以选择依次增加,核心算法:      其中,选取 i、j、k进行循环与迭代,k作为中

    2024年02月11日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包