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



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

拥有大小不是块维度倍数的任务是很常见的事情。我最常用的解决方案是这个。假设您的输入数据具有大小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 仍然未得到充分利用,并行性不会给您带来任何影响,甚至会降低算法的性能。

最新更新