首页 > 解决方案 > CUDA 数据数不能被 CUDA 线程平均分配

问题描述

比如有两个4线程,但是我有5个数据,第一个0-3可以映射到前4个线程,剩下的呢,它只说可能有运行时错误,但是如何修复它? 在此处输入图像描述

我想我问这个问题的方向是错误的,现在假设我有

perfromwork<<<2,2>>>;

现在我这个伪代码计算出来的dataIndex小于数据元素个数(N=5),那么最后一个(5-2x2=1)怎么办?如果我使用另一个块,它会遇到同样的问题,<<<2, 2>>> 块将创建一个更大的数据索引。

标签: cuda

解决方案


这里有两种规范的方法。

  1. 将网格大小设置为大于或等于数据集大小,并确保使用“线程检查”来防止不需要的额外线程进行任何工作。

  2. 使用grid-stride loop,它允许独立于数据集大小(如果您愿意)确定网格大小,同时仍然提供正确的结果。

vector 为每个添加示例内核:

__global__ void vectorAdd(float *x, float *y, float *z, int size){

  int idx = threadIdx.x+blockDim.x*blockIdx.x;
  if (idx < size) // thread check
    z[idx] = x[idx] + y[idx];
}

上面的内核不使用网格步长循环。它将要求您将网格的大小设置为大于或等于数据集大小,以便处理所有元素。该大小调整代码可能如下所示:

  int size = MY_DATA_SET_SIZE;
  dim3 block(256); // this is threads per block, the choice here is not critical for correctness, but must be 1 or larger and less than or equal to 1024;
  dim3 grid((size+block.x-1)/block.x);
  vectorAdd<<<grid,block>>>(...);

实现网格步长循环以执行相同操作的内核可能如下所示:

__global__ void vectorAdd(float *x, float *y, float *z, int size){

  for (int idx = threadIdx.x+blockDim.x*blockIdx.x; idx < size; idx += blockDim.x*gridDim.x)
    z[idx] = x[idx] + y[idx];
}

在这种情况下,网格大小可以是任意的(1 或更大)并且仍然会产生正确的结果。


推荐阅读