Matrix 使用cuBLAS访问子矩阵

Matrix 使用cuBLAS访问子矩阵,matrix,cuda,fortran,partitioning,cublas,Matrix,Cuda,Fortran,Partitioning,Cublas,我读了下面的帖子 我想做一些类似的事情,从Fortran调用cuBLAS例程 基本上,我将一个大矩阵划分为3x3块,在循环的每个步骤中,分区都会发生变化。目前,我为每个单独的子块分配/释放指针,并在每个步骤向设备复制矩阵的相关部分。这会产生很多开销,我希望能够消除这些开销。这可行吗 您可以在主机代码中使用与主机指针相同的方法执行设备指针算法。例如,如果您在GPU上存储了MxN矩阵: float *A_d; cudaMalloc((void **)&A_d, size_t(M*N)*

我读了下面的帖子

我想做一些类似的事情,从Fortran调用cuBLAS例程


基本上,我将一个大矩阵划分为
3x3
块,在循环的每个步骤中,分区都会发生变化。目前,我为每个单独的子块分配/释放指针,并在每个步骤向设备复制矩阵的相关部分。这会产生很多开销,我希望能够消除这些开销。这可行吗

您可以在主机代码中使用与主机指针相同的方法执行设备指针算法。例如,如果您在GPU上存储了MxN矩阵:

 float *A_d;
 cudaMalloc((void **)&A_d, size_t(M*N)*sizeof(float));

如果你想对从(x1,y1)开始的子矩阵进行运算,那么你可以将
a+x1+M*y1
传递给任何需要一个矩阵作为参数的CUBLAS函数。

你可以在主机代码中用与主机指针相同的方法进行设备指针运算。例如,如果您在GPU上存储了MxN矩阵:

 float *A_d;
 cudaMalloc((void **)&A_d, size_t(M*N)*sizeof(float));

如果你想从(x1,y1)开始对一个子矩阵进行运算,那么你将把
a+x1+M*y1
传递给任何需要矩阵作为参数的CUBLAS函数。

Talonmes已经满意地回答了这个问题。为了支持他的答案并可能对其他用户有用,我在这里提供了一个完整的示例,说明如何使用
cublasgemm
在完整矩阵
a
B
的子矩阵之间执行乘法,以及如何将结果分配给完整矩阵
C
的子矩阵

尽管这个问题与Fortran有关,但下面的代码是用C/C++给出的,因为我没有将Fortran与CUDA结合使用,而且许多用户将CUDA与C/C++结合使用

代码利用了

  • 访问子矩阵的指针算法
  • 前导维和子矩阵维的概念
  • 以下代码考虑三个矩阵:

  • A
    -
    10x9
  • B
    -
    15x13
  • C
    -
    10x12
  • 矩阵
    C
    初始化为所有
    10
    s。代码使用Matlab语言执行以下子矩阵乘法:

    C(1+x3:5+x3,1+y3:3+y3) = A(1+x1:5+x1,1+y1:4+y1) * B(1+x2:4+x2,1+y2:3+x2);
    
    Utilities.cu
    Utilities.cuh
    文件在这里被标记和省略

    #include <thrust/device_vector.h>
    #include <thrust/random.h>
    
    #include <cublas_v2.h>
    
    #include "Utilities.cuh"
    
    /********/
    /* MAIN */
    /********/
    int main()
    {
        /**************************/
        /* SETTING UP THE PROBLEM */
        /**************************/
    
        //const int Nrows1 = 10;            // --- Number of rows of matrix 1
        //const int Ncols1 = 10;            // --- Number of columns of matrix 1
    
        //const int Nrows2 = 15;            // --- Number of rows of matrix 2
        //const int Ncols2 = 15;            // --- Number of columns of matrix 2
    
        //const int Nrows3 = 12;            // --- Number of rows of matrix 3
        //const int Ncols3 = 12;            // --- Number of columns of matrix 3
    
        const int Nrows1 = 10;          // --- Number of rows of matrix 1
        const int Ncols1 = 9;           // --- Number of columns of matrix 1
    
        const int Nrows2 = 15;          // --- Number of rows of matrix 2
        const int Ncols2 = 13;          // --- Number of columns of matrix 2
    
        const int Nrows3 = 10;          // --- Number of rows of matrix 3
        const int Ncols3 = 12;          // --- Number of columns of matrix 3
    
        const int Nrows = 5;            // --- Number of rows of submatrix matrix 3 = Number of rows of submatrix 1
        const int Ncols = 3;            // --- Number of columns of submatrix matrix 3 = Number of columns of submatrix 2
    
        const int Nrowscols = 4;        // --- Number of columns of submatrix 1 and of rows of submatrix 2
    
        const int x1 = 3;               // --- Offset for submatrix multiplication along the rows
        const int y1 = 2;               // --- Offset for submatrix multiplication along the columns
    
        const int x2 = 6;               // --- Offset for submatrix multiplication along the rows
        const int y2 = 4;               // --- Offset for submatrix multiplication along the columns
    
        const int x3 = 3;               // --- Offset for submatrix multiplication along the rows
        const int y3 = 5;               // --- Offset for submatrix multiplication along the columns
    
        // --- Random uniform integer distribution between 0 and 100
        thrust::default_random_engine rng;
        thrust::uniform_int_distribution<int> dist(0, 20);
    
        // --- Matrix allocation and initialization
        thrust::device_vector<float> d_matrix1(Nrows1 * Ncols1);
        thrust::device_vector<float> d_matrix2(Nrows2 * Ncols2);
        for (size_t i = 0; i < d_matrix1.size(); i++) d_matrix1[i] = (float)dist(rng);
        for (size_t i = 0; i < d_matrix2.size(); i++) d_matrix2[i] = (float)dist(rng);
    
        printf("\n\nOriginal full size matrix A\n");
        for(int i = 0; i < Nrows1; i++) {
            std::cout << "[ ";
            for(int j = 0; j < Ncols1; j++) 
                std::cout << d_matrix1[j * Nrows1 + i] << " ";
            std::cout << "]\n";
        }
    
        printf("\n\nOriginal full size matrix B\n");
        for(int i = 0; i < Nrows2; i++) {
            std::cout << "[ ";
            for(int j = 0; j < Ncols2; j++) 
                std::cout << d_matrix2[j * Nrows2 + i] << " ";
            std::cout << "]\n";
        }
    
        /*************************/
        /* MATRIX MULTIPLICATION */
        /*************************/
        cublasHandle_t handle;
    
        cublasSafeCall(cublasCreate(&handle));
    
        thrust::device_vector<float> d_matrix3(Nrows3 * Ncols3, 10.f);
    
        float alpha = 1.f;
        float beta  = 0.f;
        cublasSafeCall(cublasSgemm(handle, CUBLAS_OP_N, CUBLAS_OP_N, Nrows, Ncols, Nrowscols, &alpha,
                       thrust::raw_pointer_cast(d_matrix1.data())+x1+Nrows1*y1, Nrows1, thrust::raw_pointer_cast(d_matrix2.data())+x2+Nrows2*y2, Nrows2,
                       &beta, thrust::raw_pointer_cast(d_matrix3.data())+x3+Nrows3*y3, Nrows3));
    
        printf("\n\nResult full size matrix C\n");
        for(int i = 0; i < Nrows3; i++) {
            std::cout << "[ ";
            for(int j = 0; j < Ncols3; j++) 
                std::cout << d_matrix3[j * Nrows3 + i] << " ";
            std::cout << "]\n";
        }
    
        return 0; 
    }
    
    #包括
    #包括
    #包括
    #包括“Utilities.cuh”
    /********/
    /*主要*/
    /********/
    int main()
    {
    /**************************/
    /*设置问题*/
    /**************************/
    //常数int Nrows1=10;//--矩阵1的行数
    //const int Ncols1=10;//--矩阵1的列数
    //常数int Nrows2=15;/——矩阵2的行数
    //const int Ncols2=15;//--矩阵2的列数
    //常数int Nrows3=12;/——矩阵3的行数
    //const int Ncols3=12;//--矩阵3的列数
    常数int Nrows1=10;//--矩阵1的行数
    const int Ncols1=9;//--矩阵1的列数
    常数int Nrows2=15;/——矩阵2的行数
    const int Ncols2=13;/——矩阵2的列数
    常数int Nrows3=10;//--矩阵3的行数
    const int Ncols3=12;//--矩阵3的列数
    常数int Nrows=5;//---子矩阵行数矩阵3=子矩阵行数1
    const int Ncols=3;//---子矩阵的列数矩阵3=子矩阵的列数2
    const int Nrowscols=4;//--子矩阵1的列数和子矩阵2的行数
    const int x1=3;//---子矩阵沿行相乘的偏移量
    const int y1=2;//---子矩阵沿列相乘的偏移量
    const int x2=6;//---子矩阵沿行相乘的偏移量
    const int y2=4;//--子矩阵沿列相乘的偏移量
    const int x3=3;//---子矩阵沿行相乘的偏移量
    const int y3=5;//--子矩阵沿列相乘的偏移量
    //---0到100之间的随机均匀整数分布
    推力:默认随机发动机转速;
    推力:均匀分布距离(0,20);
    //---矩阵分配和初始化
    推力:器件矢量d矩阵1(Nrows1*Ncols1);
    推力:装置矢量d矩阵2(Nrows2*Ncols2);
    对于(size_t i=0;istd::couttalonmies已经满意地回答了这个问题。为了支持他的答案并可能对其他用户有用,我在这里提供了一个完整的示例,说明如何使用
    cublasgemm
    在完整矩阵
    a
    B
    的子矩阵之间执行乘法,以及如何将结果分配给子矩阵完整矩阵的x
    C

    尽管这个问题与Fortran有关,但下面的代码是用C/C++给出的,因为我没有将Fortran与CUDA结合使用,而且许多用户将CUDA与C/C++结合使用

    代码利用了

  • 访问子矩阵的指针算法
  • 前导维和子矩阵维的概念
  • 以下代码考虑三个矩阵:

  • A
    -
    10x9
  • B
    -
    15x13
  • C
    -
    10x12
  • 矩阵
    C
    初始化为所有
    10
    s。该代码执行以下子矩阵乘法