2011-05-16 43 views
0

我對cuda非常陌生。我在設備模擬模式下在我的ubuntu 10.04上使用cuda。 我寫代碼來計算陣列的平方這是繼:cuda編程問題

#include <stdio.h> 
#include <cuda.h> 
__global__ void square_array(float *a, int N) 
    { 
     int idx = blockIdx.x + threadIdx.x; 
     if (idx<=N) 
     a[idx] = a[idx] * a[idx]; 
    } 
int main(void) 
    { 
     float *a_h, *a_d; 
     const int N = 10; 
     size_t size = N * sizeof(float); 
     a_h = (float *)malloc(size);   
     cudaMalloc((void **) &a_d, size); 
      for (int i=0; i<N; i++) a_h[i] = (float)i; 
     cudaMemcpy(a_d, a_h, size, cudaMemcpyHostToDevice); 
      square_array <<< 1,10>>> (a_d, N); 

cudaMemcpy(a_h, a_d, sizeof(float)*N, cudaMemcpyDeviceToHost); 
     // Print results 
     for (int i=0; i<N; i++) printf(" %f\n", a_h[i]); 

     free(a_h); 
cudaFree(a_d); 
    return 0; 
    } 

當我運行這段代碼顯示它沒有問題它給我正確的輸出。

現在我的問題是,當我使用< < < 2,5 >>>或< < < 5,2 >>>結果是一樣的。 gpu上發生了什麼? 我的理解是我只用5個包含2個線程的塊啓動cuda內核。 任何人都可以解釋我如何處理這個或執行啓動(內核調用)?

現在我真正的問題是,當我打電話給內核< < < 1,10 >>>沒關係。它顯示了完美的結果。 但是當我打電話與< < < 1,5 >>內核結果如下:

0.000000 
1.000000 
4.000000 
9.000000 
16.000000 
5.000000 
6.000000 
7.000000 
8.000000 
9.000000 

類似地,當我減少或增加所述第二參數在內核調用它示出了用於例如不同的結果時,我改變它到< < 1,4 >>它顯示了以下結果:

0.000000 
1.000000 
4.000000 
9.000000 
4.000000 
5.000000 
6.000000 
7.000000 
8.000000 
9.000000 

爲什麼這個結果會來嗎? 任何機構可以解釋內核啓動調用的工作嗎?

什麼是blockdim類型變量包含? 請幫我理解內核調用啓動和工作的概念嗎? 我搜索了編程指南,但他們沒有很好地解釋它。

+0

您正在更改N(10,4,5)的值。那麼顯然只有前N個元素應該被更新。你覺得這是什麼讓人困惑?! – 2011-05-16 17:31:50

回答

5

內核代碼中idx的計算不正確。如果將其更改爲:

int idx = blockDim.x * blockIdx.x + threadIdx.x; 

您可能會發現結果有點容易理解。

編輯:對於任何給定內核啓動

square_array<<<gridDim,blockDim>>>(...) 

在GPU中,自動可變blockDim將包含X,Y,並且在主機側內核啓動通過blockDim參數的z分量。同樣,gridDim將包含啓動時傳遞的gridDim參數的x和y分量。

+0

原來的代碼是這樣的,但它並沒有改變場景,或者在上次我仔細檢查了我的問題,我問了關於blockdim,你可以解釋內核調用的工作請 – user513164 2011-05-16 07:28:55

+1

我盡我所能 - 因爲它最初是張貼你的問題是一個沒有格式化,無法理解的垃圾堆。看看我的貼子的編輯。 – talonmies 2011-05-16 07:34:58

0

除了talonmies的說法,您可能需要執行以下操作以在現實應用程序中獲得更好的性能。

if (idx < N) { 
tmp = a[idx]; 
a[idx] = tmp * tmp; 
} 
0

內核在CUDA調用的方法是像這樣:

kernel<<<numBlocks,numThreads>>>(Kernel arguments); 

這意味着會有numBlocks塊,在每個塊上運行numThreads線程。例如,如果您致電

kernel<<<1,5>>>(Kernel args); 

然後1塊將運行並行運行的5個線程。如果你打電話

kernel<<<2,5>>>(Kernel args); 

那麼就有2塊,每個運行5個線程。除非您更改設備代碼,否則「平方」數組的最大維數爲產品numBlocks * numThreads。這解釋了爲什麼不是原始數組中的所有值都被平方。

我建議您閱讀CUDA工具包附帶的CUDA_C_Programming_Guide.pdf。