CUDA线程寻址((threadadix).x, threadIdx.y, threadaddx .z)和块寻址(blo



我只需要澄清一些非常基本的东西-使用大多数计算示例,如:

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.xblockidx.y在这方面和threaIdx是一样的吗?

创建2D或3D线程块通常是这样做的,因为问题本身适合2D或3D数据解释,使用2D或3D线程块处理它可能会使代码更具可读性。但是没有特别的理由说明为什么不能使用具有适当索引的1D线程块。

创建2D或3D网格(块)通常出于上述原因和/或绕过CC 3.0之前设备对网格任何一个维度的块数量的限制(任何维度的最大65535块)。

对于threadblock的情况,你可以在一个维度的单个块中使用1024个线程,所以如果你不想,你不需要用threadIdx.ythreadIdx.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.xblockIdx.y散列成一个值的方式会影响您正在执行的全局内存访问的合并,请参阅此线程中的harrism的答案

CUDA联合访问全局内存

最新更新