阻止cuda的每网格分配习惯

时间:2013-06-25 16:58:15

标签: cuda gpgpu nvidia

我在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的新手。欢迎任何解释或背后的知识。

1 个答案:

答案 0 :(得分: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
}

对于防止任何额外线程执行越界内存操作至关重要。