2014-02-21 196 views
0

使用cuda進行矩陣乘法時存在問題。我必須做A * A * A * A並將其保存在hB中。 Cublas可以,但我無法使用CUDA。尺寸可以是高價值就像2000年這是我的代碼:Cuda進行矩陣乘法

__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); 

} 

我最後安裝CUDA 6,它不需要cudaMemCpy,因爲內存是共享的。

+0

您是否[爲您的CUDA程序進行錯誤檢查](http://stackoverflow.com/q/14038589/2386951)? – Farzad

回答

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,但這對於讓代碼正常工作並不重要。

+0

謝謝。我有個問題。爲什麼Cublas Multiplication比CUDA更快? – user3331951

+0

CUBLAS使用CUDA,但它是高度優化的代碼,由專家編寫。你的問題類似於問爲什麼MKL在矩陣乘法時比在我自己寫的矩陣乘法例程中更快。您的矩陣乘法CUDA代碼是相當天真的,並且有基本的優化,您可以利用它來加快速度。如果您在本頁面右上角的搜索框中搜索cuda矩陣乘法,您會發現很多不同優化的例子。最直接的是在平鋪安排中使用共享內存。 –