线程组织:内置变量
在上一篇文章中,我们已经了解了 CUDA 执行配置的三大组成:线程、线程块 block 和 网格 grid。
1. threadIdx
threadIdx 是一个内置的变量,用来表示当前线程在其线程块中的索引。
具体的索引规则,举个例子就能很清楚的了解。如图 1 所示,有两个 block,threadIdx 都是独立于所在的 block 进行依次“编码”的。
如图 2 所示,再举一个二维 block 的例子,“编码”规则也不难理解。比如其中的 X,在第 0 行,第 1 列,所以 threadIdx.x=1,threadIdx.y=0;再比如 Q,在第 1 行,第 2 列,所以 threadIdx.x=2,threadIdx.y=1。
我们写一段代码来了解如何使用。如代码清单 1 所示,grid 的布局是 2x2,即 4 组 block,每组 block 里有 8x8 个线程。在核函数 print_threadIds 中,我们打印每个执行线程的 threadIdx 信息。
我们通过打印信息“验证”我们的理解:总共打印 256 次。threadIdx.x 的范围在 0 到 7;threadIdx.y 的范围也在 0 到 7;threadIdx.z 都是 0。而且 (threadIdx.x,threadIdx.y) 的相同组合,会出现 4 次。
2. blockIdx
blockIdx 也是一个内置的变量,用于表示当前执行线程块的索引。
我们看到图 3 的示例,blockIdx 已经和其内部的 thread 排布无关了,我们只关系整体的 block 排布。比如 X 和 Y 一样,blockIdx.x=0,blockIdx.y=0;T 和 U 一样,blockIdx.x=1,blockIdx.y=1。
3. blockDim 和 gridDim
我们再来看两个内置变量。如图 4 所示,blockDim 提供了当前执行的线程块的维度信息。如图 5 所示,gridDim 提供整个网格的维度信息。
最后我们写程序“验证”一下 blockIdx 和 blockDim/gridDim 的概念。如代码清单 2 所示,执行配置和代码清单 1 是一样的,不过每个执行线程里打印 blockIdx、blockDim、gridDim。
从打印信息来看,blockIdx.x 的范围在 0 到 1;blockIdx.y 的范围也在 0 到 1。blockDim 都为 8x8,gridDim 都为 2x2。
blockDim 和 gridDim 在核函数启动时被设定,在整个核函数执行期间保持不变。有一丝“常量”的意思。