Cuda制作矩阵乘法

时间:2014-02-21 16:13:48

标签: c++ c cuda parallel-processing

使用cuda制作矩阵乘法时遇到问题。我必须做A * A * A * A并将其保存在hB中。有了Cublas,没关系,但我无法用CUDA制作它。 Dimension可以是像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,因为内存是共享的。

1 个答案:

答案 0 :(得分:1)

  • 我建议您先对所显示的代码执行cuda error checking,然后查看结果。
  • 如果您同时显示完整的代码会更好。例如什么是BLOCK_SIZE?我的想法不是要告诉我BLOCK_SIZE是什么,而是要显示完整的代码。
  • 另外,您在CUDA 6中引用的功能具有您未满足的特定要求(例如使用cudaMallocManaged()),但您的代码不依赖于统一内存,因此这是无关紧要的。

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

问题出现是因为您的网格大小可能大于有效的数组大小。您正在发布N x N网格,但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,但这并不是让代码生效所必需的。