【问题标题】:How to use 3D matrices with CULA on a GPU?如何在 GPU 上通过 CULA 使用 3D 矩阵?
【发布时间】:2019-08-06 21:57:39
【问题描述】:

在某些代码的 CPU 版本中,我有很多如下所示的内容:

for(int i =0;i<N;i++){

    dgemm(A[i], B[i],C[i], Size[i][0], Size[i][1], Size[i][2], Size[i][3], 'N','T');

}

A[i] 将是某个大小的二维矩阵。

我希望能够使用 CULA 在 GPU 上执行此操作(我不只是做乘法,所以我需要 CULA 中的线性代数运算),例如:

 for(int i =0;i<N;i++){
        status = culaDeviceDgemm('T', 'N', Size[i][0], Size[i][0], Size[i][0], alpha, GlobalMat_d[i], Size[i][0], NG_d[i], Size[i][0], beta, GG_d[i], Size[i][0]);
}

但是,我想在程序开始时将我的 B 提前存储在 GPU 上,因为它们不会改变,但我不知道如何去做。或者我一般如何存储我的数组以便这成为可能。

我在网上看到了各种关于在 CUDA 中使用 3D 矩阵的内容,但它们似乎不太适用于随后能够对 CULA 函数进行函数调用。

从下面答案中的示例中,我有这个:

extern "C" void copyFNFVecs_(double **FNFVecs, int numpulsars, int numcoeff){


  cudaError_t err;
 err = cudaMalloc( (void ***)&GlobalFVecs_d, numpulsars*sizeof(double*) );
 checkCudaError(err);

    for(int i =0; i < numpulsars;i++){
         err = cudaMalloc( (void **) &(GlobalFVecs_d[i]), numcoeff*numcoeff*sizeof(double) );
         checkCudaError(err);    
       //  err = cudaMemcpy( GlobalFVecs_d[i], FNFVecs[i], sizeof(double)*numcoeff*numcoeff, cudaMemcpyHostToDevice );
        // checkCudaError(err); 
        }

}

我已将 double **GlobalFVecs_d 声明为全局变量。但是当它上线时我得到一个段错误

 err = cudaMalloc( (void **) &(GlobalFVecs_d[i]), numcoeff*numcoeff*sizeof(double) );

但它似乎正是另一个示例中的内容?

我意识到它不一样,所以我现在有了可以编译的代码:

double **GlobalFVecs_d;
double **GlobalFPVecs_d;

extern "C" void copyFNFVecs_(double **FNFVecs, int numpulsars, int numcoeff){


  cudaError_t err;
  GlobalFPVecs_d = (double **)malloc(numpulsars * sizeof(double*));
 err = cudaMalloc( (void ***)&GlobalFVecs_d, numpulsars*sizeof(double*) );
 checkCudaError(err);

    for(int i =0; i < numpulsars;i++){
         err = cudaMalloc( (void **) &(GlobalFPVecs_d[i]), numcoeff*numcoeff*sizeof(double) );
         checkCudaError(err);    
         err = cudaMemcpy( GlobalFPVecs_d[i], FNFVecs[i], sizeof(double)*numcoeff*numcoeff, cudaMemcpyHostToDevice );
         checkCudaError(err);   
        }

         err = cudaMemcpy( GlobalFVecs_d, GlobalFPVecs_d, sizeof(double*)*numpulsars, cudaMemcpyHostToDevice );
         checkCudaError(err);

}

但是,如果我现在尝试通过以下方式访问它:

 dim3 dimBlock(BLOCK_SIZE, BLOCK_SIZE);
 dim3 dimGrid;//((G + dimBlock.x - 1) / dimBlock.x,(N + dimBlock.y - 1) / dimBlock.y);
 dimGrid.x=(numcoeff + dimBlock.x - 1)/dimBlock.x;
 dimGrid.y = (numcoeff + dimBlock.y - 1)/dimBlock.y;

 for(int i =0; i < numpulsars; i++){
    CopyPPFNF<<<dimGrid, dimBlock>>>(PPFMVec_d, GlobalFVecs_d[i], numpulsars, numcoeff, i);
 }

这里是seg faults,这不是获取数据的方法吗?

【问题讨论】:

    标签: cuda gpu linear-algebra algebra cula


    【解决方案1】:
    1. 使用cudaMalloc()B 分配内存
    2. 使用cudaMemcpy()将其从主机复制到设备
    3. 在内核参数列表中传递设备指针

    最后你在内核中使用你传递的参数! 示例:

      1     //  Kernel definition, see also section 4.2.3 of Nvidia Cuda Programming Guide 
      2     __global__  void vecAdd(float* A, float* B, float* C) 
      3     { 
      4        // threadIdx.x is a built-in variable  provided by CUDA at runtime 
      5        int i = threadIdx.x; 
      6        A[i]=0; 
      7        B[i]=i; 
      8        C[i] = A[i] + B[i]; 
      9     } 
      10     
      11     #include  <stdio.h> 
      12     #define  SIZE 10 
      13     int  main() 
      14     { 
      15         int N=SIZE; 
      16         float A[SIZE], B[SIZE], C[SIZE]; 
      17         float *devPtrA; 
      18         float *devPtrB; 
      19         float *devPtrC; 
      20         int memsize= SIZE * sizeof(float); 
      21     
      22         **cudaMalloc((void**)&devPtrA, memsize);** 
      23         cudaMalloc((void**)&devPtrB, memsize); 
      24         cudaMalloc((void**)&devPtrC, memsize); 
      25         **cudaMemcpy(devPtrA, A, memsize,  cudaMemcpyHostToDevice);** 
      26         cudaMemcpy(devPtrB, B, memsize,  cudaMemcpyHostToDevice); 
      27         // __global__ functions are called:  Func<<< Dg, Db, Ns  >>>(parameter); 
      28         **vecAdd<<<1, N>>>(devPtrA,  devPtrB, devPtrC);** 
      29         cudaMemcpy(C, devPtrC, memsize,  cudaMemcpyDeviceToHost); 
      30     
      31         for (int i=0; i<SIZE; i++) 
      32          printf("C[%d]=%f\n",i,C[i]); 
      33     
      34          cudaFree(devPtrA); 
      35         cudaFree(devPtrA); 
      36         cudaFree(devPtrA); 
      37     } 
    

    ** 区域对您来说很重要。示例取自 here。你可能想看看this的问题。

    编辑#1: 首先要声明一个内核函数,您需要在返回类型之前放置关键字__global__,例如

    __global__ void copyFNFVecs_(double **FNFVecs, int numpulsars, int numcoeff).

    此外,我将只使用一个指向您拥有的矩阵的第一个元素的指针。

    double *devPtr.

    分配它

    cudaMalloc((void*)&amp;devPtr, size)

    然后复制

    cudaMemcpy(devPtr, hostPtr, size, hostToDevice).

    请注意,要计算结构的大小,您需要维度(例如 X 和 Y)和基础元素类型的大小(例如 double)。

    size_t size = X*Y*sizeof(double).

    sizeof(double *) 表示指向双精度的指针的大小不正确(在 32 位机器中,指针的大小是 4 字节,而双精度的大小是 8 字节)。

    【讨论】:

    • 您好,感谢您的回复,稍后我将不得不在后续答案中发布代码
    猜你喜欢
    • 2019-01-26
    • 2019-09-10
    • 1970-01-01
    • 1970-01-01
    • 2021-07-26
    • 2021-01-19
    • 1970-01-01
    • 2022-07-05
    • 2012-10-11
    相关资源
    最近更新 更多