5

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

ID = blockIdx.x*blockDim.x+threadIdx.x;

// ... 然后对数组 [ID] 进行计算

我的问题是,如果我想在一个块中使用最大线程数(1024),那么我真的需要考虑所有(、、、)来“构造”我的“threadID threadIdx.xthreadIdx.ythreadIdx.z

如果是这样,将其散列为单个值的推荐方法是什么?

如果不是这样,为什么有人可以在图像处理相关操作中以类似的方式使用它,例如这篇文章:

https://stackoverflow.com/questions/11503406/cuda-addressing-a-matrix

和怎么样,在这方面他们blockidx.xblockidx.y是一样的吗?threaIdx

4

4 回答 4

9

通常会创建 2D 或 3D 线程块,因为该问题有助于对数据进行 2D 或 3D 解释,并且使用 2D 或 3D 线程块处理它可能会使代码更具可读性。但是没有具体的原因为什么不能使用具有适当索引的一维线程块来完成。

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

对于 threadblock 情况,您可以在单个维度中的单个块中使用 1024 个线程,因此您不需要使用threadIdx.ythreadIdx.z如果您不想构造您的 ID 变量。

如果您有 CC 3.0 之前的设备,并且您的问题在块方面足够大,您可能仍需要构建 2D 网格。您仍然可以在该网格中使用一维线程块。在这种情况下,可以创建一个唯一的 ID 变量,如下所示:

 int idx = threadIdx.x + (((gridDim.x * blockIdx.y) + blockIdx.x)*blockDim.x);  

上述构造应处理具有任何 2D 网格的 1D 线程块。

除了构建 2D 网格来处理大型问题之外,还有其他方法,例如让您的块在某种循环中处理多个数据块。

于 2013-05-06T17:46:45.673 回答
1

这是罗伯特·克罗维拉(Robert Crovella)的回答之上:

创建 2D/3D 网格不仅是为了可读性,而且是为了利用片上共享内存中的 2D/3D 局部性,从而提供更快的访问速度。如果您的问题适用于 2D 网格,则您无法使用 1D 网格有效地利用这种局部性。

于 2014-12-16T16:10:44.590 回答
0

threadID在您的示例中是一个误导性术语。计算的值实际上是当前线程将读取或写入的数组的索引。如果您的内核被多个块调用,您需要以这种方式计算索引以处理每个数组元素一次。

于 2013-05-06T17:47:09.333 回答
0

请记住,您将、threadIdx.x和散列为单个值的方式会影响您正在执行的全局内存访问的合并,请参阅 harrism 在此线程中的回答threadIdx.yblockIdx.xblockIdx.y

CUDA 合并访问全局内存

于 2013-05-06T20:36:26.090 回答