CUDA:我应该如何处理线程数无法表示为dimGrid * dimBlock的情况?

时间:2014-02-17 20:18:32

标签: cuda

假设我的输入由七个数据点组成,在这些数据点上执行一些计算并将结果写回到大小为7的输出数组。将块尺寸声明为4会导致网格大小为2,从而导致尝试使用无效的线程id(使用pt_id = blockIdx.x * blockDim.x + threadID.x)运行内核7并因内存访问无效而失败(因为我根据线程ID访问了一些我的数组) 。 我可以在我的内核中添加代码,专门将线程id与max_thread_id参数进行比较,如果thread_id> max_thread_id则不做任何事情,但我想知道是否有更好的方法来处理不规则的输入数组。

1 个答案:

答案 0 :(得分:2)

具有不是块尺寸的多倍的任务是非常常见的事情。我最常用的解决方案就是这个。假设您的输入数据的大小为N,并且您希望将块大小等于BLOCK_SIZE来配置启动。在这种情况下,您的启动配置可能如下所示:

kernel_function<<<(N + BLOCK_SIZE - 1) / BLOCK_SIZE, BLOCK_SIZE>>>(...);

在内核代码中,每个线程确定是否应该做一些工作,如下所示:

int id = blockIdx.x*blockDim.x + threadIdx.x;
if (id < N) { /* do the stuff */ }
else { return; }

如果任务(N)的大小取决于输入,则必须将此值作为参数传递给内核函数。此外,将NBLOCK_SIZE的值定义为宏或模板参数是很常见的。

最后,如果你的输入数组尺寸很小,就像在你的例子中一样,GPU仍未得到充分利用,并行性不会给你带来任何影响,甚至会降低算法的性能。