2013-06-25 25 views
2

當我們在分配網格大小時,我在cuda示例中看到了一種常見習慣。以下是一個例子:cuda的每個網格分配習慣中的塊

int 
main(){ 

    ... 
    int numElements = 50000; 
    int threadsPerBlock = 1024; 
    int blocksPerGrid =(numElements + threadsPerBlock - 1)/threadsPerBlock; 

    vectorAdd<<<blocksPerGrid, threadsPerBlock>>>(d_A, d_B, d_C, numElements); 
    ... 
} 

__global__ void 
vectorAdd(const float *A, const float *B, float *C, int numElements) 
{ 
    int i = blockDim.x * blockIdx.x + threadIdx.x; 

    if (i < numElements) 
    { 
     C[i] = A[i] + B[i]; 
    } 
} 

我很好奇的是blocksPerGrid的初始化。我不明白爲什麼它的

int blocksPerGrid = (numElements + threadsPerBlock - 1)/threadsPerBlock; 

,而不是簡單的

int blocksPerGrid = numElements/threadsPerblock; 

看來這是一個相當普遍的習慣。我在各種項目中看到。他們都是這樣做的。 我是新來的cuda。歡迎任何背後的解釋或知識。

回答

8

以您看到的方式完成計算,以允許numElements不是threadsPerblock的整數倍的情況。

例如,使用threadsPerblock = 256numElements = 500

(numElements + threadsPerBlock - 1)/threadsPerBlock = (500 + 255)/256 = 2 

numElements/threadsPerblock = 500/256 = 1 

在第一種情況下,512個線程運行,覆蓋在輸入數據中的500個元素,但是在第二種情況下,僅運行256個線程,未處理244個輸入項目。

還要注意這種內核「保鏢」的代碼:

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

if (i < numElements) 
{ 
    ... Access input here 
} 

是必不可少的,以防止任何額外的線程執行從越界內存操作。