【问题标题】:Cuda to make Matrix MultiplicationCuda 做矩阵乘法
【发布时间】:2014-02-21 16:13:48
【问题描述】:

使用 cuda 进行矩阵乘法时遇到问题。我必须做 A*A*A*A 并将其保存在 hB 中。使用 Cublas 没问题,但我无法使用 CUDA。维度可以是像 2000 这样的高值。这是我的代码:

__global__ void CudaMM(float *A, float *B, int N)
{

    int row = blockIdx.y*blockDim.y + threadIdx.y;
    int col = blockIdx.x*blockDim.x + threadIdx.x;

    float sum = 0.f;
    for (int n = 0; n < N; ++n)
        sum += A[row*N+n]*A[n*N+col];

    B[row*N+col] = sum;
}

void CudaMult(int dimension,float *hMatrice,float *hB,float *d_A,float *d_B){
    int N,K;
    K = 100;            
    N = K*BLOCK_SIZE;

    dim3 threadBlock(BLOCK_SIZE,BLOCK_SIZE);
    dim3 grid(K,K);

    cudaMemcpy(d_A,hMatrice,dimension*dimension*sizeof(float),cudaMemcpyHostToDevice);

CudaMM<<<grid,threadBlock>>>(d_A,d_B,N);

cudaMemcpy(hB,d_B,dimension*dimension*sizeof(float),cudaMemcpyDeviceToHost);


}

void CublasFindConnect(int dimension,float* mat,float* B){


    float *d_A,*d_B;
    cudaMalloc(&d_A,dimension*dimension*sizeof(float));
    cudaMalloc(&d_B,dimension*dimension*sizeof(float));

    int w=0;
    while(w<5){

        CudaMult(dimension,mat,B,d_A,d_B);

          // Copy Matrix computed B to previous M

            for (m=0; m<dimension; m++) {

                for (n=0; n<dimension; n++) {
                    mat[m*dimension+n]=B[m*dimension+n];
                    B[m*dimension+n]=0;
                }
            }

     w++;
    }

cudaFree(d_A);
cudaFree(d_B);

}

我安装了最后一个不需要 cudaMemCpy 的 CUDA 6,因为内存是共享的。

【问题讨论】:

标签: c++ c cuda parallel-processing


【解决方案1】:
  • 我建议您首先对您显示的代码执行正确的cuda error checking,然后看看您会得到什么结果。
  • 如果您也显示一个完整代码会更好。例如BLOCK_SIZE 是什么?这个想法不是告诉我BLOCK_SIZE 是什么,而是显示一个完整代码。
  • 顺便说一句,您在 CUDA 6 中引用的功能有您不满足的特定要求(例如使用 cudaMallocManaged()),但您的代码不依赖于统一内存,因此无关紧要.

我在您的代码中看到的一个问题是您的dimension 变量是任意的(您说它可以达到一个很大的数字,例如 2000),但您的计算大小固定为N=K*BLOCK_SIZE;。大概如果您的 BLOCK_SIZE 是某个值,例如 16 或 32,那么它将满足您的近似最大 dimension 大小 ~2000。

出现问题是因为您的网格大小可能大于您的有效数组大小。您正在启动NxN 网格,但N 可以大于dimension。这意味着一些已启动的线程可以尝试访问超出其有效维度的矩阵(AB)。

您可以通过内核中的“线程检查”来解决此问题,如下所示:

__global__ void CudaMM(float *A, float *B, int N)
{

    int row = blockIdx.y*blockDim.y + threadIdx.y;
    int col = blockIdx.x*blockDim.x + threadIdx.x;

    if ((row < N) && (col < N)) {

      float sum = 0.f;
      for (int n = 0; n < N; ++n)
        sum += A[row*N+n]*A[n*N+col];

      B[row*N+col] = sum;
    }
}

您需要将内核调用修改为:

CudaMM<<<grid,threadBlock>>>(d_A,d_B,dimension);

您可能还需要考虑根据您的实际dimension 选择网格大小,而不是固定为100*BLOCK_SIZE,但这并不是让代码正常工作所必需的。

【讨论】:

  • 谢谢。我有个问题。为什么 Cublas 乘法比 CUDA 快?
  • CUBLAS 使用 CUDA,但它是高度优化的代码,由专家编写。您的问题类似于询问为什么 MKL 在进行矩阵乘法时比我自己编写的矩阵乘法例程更快。您的矩阵乘法 CUDA 代码非常幼稚,您可以利用一些基本的优化来使其更快。如果您在本页右上角的搜索框中搜索 cuda 矩阵乘法,您会发现许多各种优化的示例。最直接的就是以平铺的方式使用共享内存。
猜你喜欢
  • 2012-05-06
  • 2011-09-07
  • 2012-12-09
  • 2012-02-07
  • 2011-04-21
  • 2012-12-13
  • 1970-01-01
  • 2015-02-03
  • 2013-09-02
相关资源
最近更新 更多