【问题标题】:CUDA Thread Addressing ((threadIdx.x, threadIdx.y, threadIdx.z) and block addressing (blockidx.x, blockidx.y)CUDA 线程寻址 ((threadIdx.x, threadIdx.y, threadIdx.z) 和块寻址 (blockidx.x, blockidx.y)
【发布时间】:2017-05-19 17:05:34
【问题描述】:

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

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

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

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

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

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

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

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

【问题讨论】:

    标签: cuda


    【解决方案1】:

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

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

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

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

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

    上面的构造应该处理任何二维网格的一维线程块。

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

    【讨论】:

      【解决方案2】:

      这是在 Robert Crovella 的回答之上:

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

      【讨论】:

        【解决方案3】:

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

        【讨论】:

          【解决方案4】:

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

          CUDA coalesced access to global memory

          【讨论】:

            猜你喜欢
            • 2017-12-25
            • 2016-07-10
            • 1970-01-01
            • 2012-07-01
            • 1970-01-01
            • 2019-02-27
            • 2013-02-22
            • 2011-10-06
            • 2011-02-13
            相关资源
            最近更新 更多