2013-06-25 4 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]; 
    } 
} 

Что мне интересно, это инициализация блоковPerGrid. Я не понимаю, почему это

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

, а не просто

int blocksPerGrid = numElements/threadsPerblock; 

Кажется, это довольно распространенная привычка. Я видел в разных проектах. Все это делают так. Я новичок в cuda. Любые объяснения или знания по этому поводу приветствуются.

ответ

8

Расчет производится так, как вы видите, чтобы разрешить случаи, когда numElements не является круглым кратным threadsPerblock.

Например, при использовании threadsPerblock = 256 и numElements = 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 
} 

имеет важное значение для предотвращения любой из дополнительных потоков от выполнения из операций оценки памяти.

Смежные вопросы