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