我只需要澄清一些非常基本的东西 - 大多数计算实例都使用类似的东西:
ID = blockIdx.x * blockDim.x + threadIdx.x;
// ...然后对数组[ID]进行计算
我的问题是,如果我想在一个块(1024)中使用最大线程数,那么我是否真的需要'考虑所有(threadIdx.x
,{{''构造'我的'threadID' 1}},threadIdx.y
)?
如果是这样,建议将其散列为单个值的方法是什么?
如果不是这样,为什么有人会以类似的方式在图像处理相关的操作中使用它,例如在这篇文章中:
https://stackoverflow.com/questions/11503406/cuda-addressing-a-matrix
threadIdx.z
和blockidx.x
如何与blockidx.y
在这方面相同?
答案 0 :(得分:8)
创建2D或3D线程块通常是因为问题适用于数据的2D或3D解释,并且使用2D或3D线程块处理它可能使代码更具可读性。但是没有具体的理由说明为什么不能使用具有适当索引的1D线程块。
创建2D或3D网格(块)通常是出于上述原因和/或绕过网格任意一维中块数量的前CC 3.0设备的限制(65535最大块)在任何方面)。
对于threadblock情况,您可以在一个维度中的单个块中使用1024个线程,因此如果不这样做,则无需使用threadIdx.y
或threadIdx.z
构建ID变量想要。
如果你有一个预CC 3.0设备,并且你的问题在块方面足够大,你可能仍然想要构建一个2D网格。您仍然可以在该网格中使用1D线程块。在这种情况下,可以创建一个唯一的ID变量,如:
int idx = threadIdx.x + (((gridDim.x * blockIdx.y) + blockIdx.x)*blockDim.x);
上述构造应该处理带有任何2D网格的1D线程块。
除了构建2D网格以处理大问题大小之外,还有其他方法,例如让您的块在某种循环中处理多个数据块。
答案 1 :(得分:0)
threadID
是一个误导性术语。计算的值实际上是当前线程将读取或写入的数组的索引。如果使用多个块调用内核,则需要以这种方式计算索引以处理每个数组元素一次。
答案 2 :(得分:0)
请记住,将threadIdx.x
,threadIdx.y
,blockIdx.x
和blockIdx.y
散列为单个值的方式会影响您正在执行的全局内存访问的合并,请参阅哈里斯在这个帖子中的回答
答案 3 :(得分:0)
这是罗伯特克罗维拉的回答:
创建2D / 3D网格不仅仅是为了便于阅读,而且还用于利用片上共享内存中的2D / 3D位置,从而提供更快的访问速度。如果您的问题适用于2D网格,则无法使用1D网格有效利用此类位置。