【问题标题】:block per grid allocation habit in cudacuda中每个网格分配习惯的块
【发布时间】:2013-06-25 16:58:14
【问题描述】:

当他们分配网格大小时,我在 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 的新手。欢迎对此背后的任何解释或知识。

【问题讨论】:

    标签: cuda gpgpu nvidia


    【解决方案1】:

    计算按照您看到的方式完成,以允许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
    }
    

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

    【讨论】:

      猜你喜欢
      • 2011-08-28
      • 2011-05-22
      • 2012-08-02
      • 2019-02-26
      • 2016-01-19
      • 2012-12-24
      • 2023-03-23
      • 2013-11-07
      相关资源
      最近更新 更多