Cuda gridDim和blockDim

eha*_*hah 40 cuda

我得到的是什么blockDim,但我有问题gridDim. Blockdim给出块的大小,但是什么gridDim?在互联网上它说明gridDim.x了x坐标中的块数.

我怎么知道是什么blockDim.x * gridDim.x给出的?

我怎么知道gridDim.xx行中有多少个值?

例如,请考虑以下代码:

int tid = threadIdx.x + blockIdx.x * blockDim.x;
double temp = a[tid];
tid += blockDim.x * gridDim.x;

while (tid < count)
{
    if (a[tid] > temp)
    {
       temp = a[tid];
    }
    tid += blockDim.x * gridDim.x;
}
Run Code Online (Sandbox Code Playgroud)

我知道tid从0开始.代码然后有tid+=blockDim.x * gridDim.x.什么是tid现在这个手术后?

Rob*_*lla 84

  • blockDim.x,y,z 给出特定方向上块中的线程数
  • gridDim.x,y,z 给出特定方向上网格中的块数
  • blockDim.x * gridDim.x 给出网格中的线程数(在x方向,在这种情况下)

块和网格变量可以是1,2或3维.处理1-D数据时,通常只创建1-D块和网格.

在CUDA文档中,这些变量在此处定义

特别是,当x维度中的总线程数(gridDim.x*blockDim.x)小于我希望处理的数组的大小时,通常的做法是创建一个循环并使线程网格移动通过整个阵列.在这种情况下,在处理一个循环迭代之后,每个线程必须移动到下一个未处理的位置,这是由gridDim.x*blockDim.x 有效的,整个网格线程跳过一维数据数组,一个网格宽度在时间.本博客文章进一步讨论了这个主题,有时称为"网格跨越循环" .

您可能需要考虑在NVIDIA网络研讨会页面上提供一些介绍性的CUDA网络研讨会.例如,这2:

  • 使用CUDA C进行GPU计算 - 简介(2010)使用CUDA C介绍GPU计算的基础知识.将通过代码示例的演练来说明概念.无需先前的GPU计算经验
  • 使用CUDA C进行GPU计算 - 高级1(2010)第一级优化技术,如全局内存优化和处理器利用率.将使用实际代码示例来说明概念

如果你想更好地理解这些概念,那将花费2个小时.

这里详细介绍了网格跨越循环的一般主题.


alr*_*kai 46

CUDA编程指南转述:

gridDim:此变量包含网格的尺寸.

blockIdx:此变量包含网格中的块索引.

blockDim:此变量包含块的尺寸.

threadIdx:此变量包含块内的线程索引.

你似乎对CUDA所具有的线程层次感到困惑; 简而言之,对于内核,将有1个网格(我总是可视化为3维立方体).它的每个元素都是一个块,这样声明的网格dim3 grid(10, 10, 2);总块数为10*10*2.反过来,每个块都是一个三维立方体线程.

话虽如此,通常只使用块和网格的x维度,这就像你的问题中的代码所做的那样.如果您正在使用1D阵列,这尤其重要.在这种情况下,您的tid+=blockDim.x * gridDim.x行实际上是网格中每个线程的唯一索引.这是因为你blockDim.x将是每个块的大小,你gridDim.x将是块的总数.

因此,如果您启动带参数的内核

dim3 block_dim(128,1,1);
dim3 grid_dim(10,1,1);
kernel<<<grid_dim,block_dim>>>(...);
Run Code Online (Sandbox Code Playgroud)

然后在你的内核中threadIdx.x + blockIdx.x*blockDim.x你有效地拥有:

threadIdx.x range from [0 ~ 128)

blockIdx.x range from [0 ~ 10)

blockDim.x equal to 128

gridDim.x equal to 10

因此,在计算中threadIdx.x + blockIdx.x*blockDim.x,您将拥有在以下定义的范围内的值:[0, 128) + 128 * [1, 10)这意味着您的tid值的范围为{0,1,2,...,1279}.当您想要将线程映射到任务时,这非常有用,因为这为您内核中的所有线程提供了唯一的标识符.

但是,如果你有

int tid = threadIdx.x + blockIdx.x * blockDim.x;
tid += blockDim.x * gridDim.x;
Run Code Online (Sandbox Code Playgroud)

然后你基本上有:tid = [0, 128) + 128 * [1, 10) + (128 * 10),你的tid值范围从{1280,1281,...,2559}我不确定那里的相关性,但这一切都取决于你的应用程序以及你如何映射你的线程你的数据.这种映射对于任何内核启动都是非常重要的,您就是决定如何完成它的人.当您启动内核时,您需要指定网格和块尺寸,并且您必须在内核中强制执行映射到数据.只要您不超过硬件限制(对于现代卡,每个块最多可以有2 ^ 10个线程,每个网格最多可以有2 ^ 16 - 1个块)

  • 具体的例子非常有用,谢谢.很多人只是重复`gridDim`,`blockIdx`等的定义,但这个例子至关重要. (2认同)