假设我的输入由七个数据点组成,在这些数据点上执行一些计算并将结果写回到大小为7的输出数组。将块尺寸声明为4会导致网格大小为2,从而导致尝试使用无效的线程id(使用pt_id = blockIdx.x * blockDim.x + threadID.x)运行内核7并因内存访问无效而失败(因为我根据线程ID访问了一些我的数组) 。 我可以在我的内核中添加代码,专门将线程id与max_thread_id参数进行比较,如果thread_id> max_thread_id则不做任何事情,但我想知道是否有更好的方法来处理不规则的输入数组。
答案 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
)的大小取决于输入,则必须将此值作为参数传递给内核函数。此外,将N
和BLOCK_SIZE
的值定义为宏或模板参数是很常见的。
最后,如果你的输入数组尺寸很小,就像在你的例子中一样,GPU仍未得到充分利用,并行性不会给你带来任何影响,甚至会降低算法的性能。