极智开发 | CUDA线程模型与全局索引计算方式

欢迎关注我的公众号 极智视界,获取我的更多经验分享

大家好,我是极智视界,本文分享一下 CUDA线程全局索引计算方式。

邀您加入我的知识星球「极智视界」,星球内有超多好玩的项目实战源码和资源下载,链接:t.zsxq.com/0aiNxERDq

CUDA 线程全局索引的计算,是很容易混淆的概念,因为 CUDA 线程模型的矩阵排布和咱们通常理解的数学矩阵排布秩序不太一样。在谈论这个话题前,还是要先看下下面这张 CUDA 线程层次模型图,关键先要对 Grid、Block、Thread 有个清晰的概念,如下,(需要注意的是,下面是 CUDA12 中的线程模型,新引入了一个 Thread Block Cluster 结构),

基本关系是 Thread 在一起组成了 Block,Block 在一起组成了 Grid,所以是 Grid 包含 Block 再包含 Thread 的关系。为了便于讲解以及回归最经典的 CUDA 线程模型,下面还有张更加清晰的图可以表达,

可以看到在上面的图中,一个 Grid 中是包含了 6 个线程块,而每个线程块又包含了 9 个线程,这其中有两个重要的概念,

  • grid ==> 网格 ==> grid 中包含若干 block ==> 最大允许网格大小为 2^31 -1 (针对一维网格情况);
  • block ==> 线程块 ==> block 中包含若干 thread ==> 最大允许线程块大小为 1024;

线程是 CUDA 编程中的最小单位,实际上线程分块是逻辑上的划分,在物理上线程不分块。在调用 GPU 的时候,核函数中是允许开很多线程的,开的线程个数可以远高于 GPU 计算核心的数量。在设计总的线程数时,至少需要等于硬件的计算核心数,这样才可能充分发挥硬件的计算能力。

在实际 CUDA 编程中,代码中是使用 <<<grid_size, block_size>>> 来进行配置线程的,意思是说线程都是在这个 <<<grid_size, block_size>>> 的规模中,其中 grid_size 是用来配置 block 的规模,而 block_size 是用来配置 thread 的规模,这点比较绕不要弄错了。

  • grid_size ==> 通过 gridDim.x 来配置;==> 可以是 int 或 dim3 的结构;
  • block_size ==> 通过 blockDim.x 来配置;==> 可以是 int 或 dim3 的结构;

然后又来一个概念叫 线程索引,如下,它们是 built-in 的内建变量,意思是代码中可以直接拿来用而不用提前声明,

  • blockIdx.x ==> 用于指定线程在网格中的线程块索引值,取值范围 0 ~ gridDim.x-1;==> 展平开来;
  • threadIdx.x ==> 用于指定线程在线程块中的线程索引值,取值范围 0 ~ blockDim.x-1;==> 展平开来;

来举个例子,来定义一个 kernel_ful<<<2, 4>>>() 的线程模型,示意如下,

其中 gridDim.x 值为 2,blockDim.x 值为 4,blockIdx.x 的取值范围为 0 ~ 1,threadIdx.x 的取值范围为 0 ~ 3,计算标红色 Star 线程的唯一标识为:Idx = threadIdx.x + blockIdx.x * blockDim.x = 2 + 1 * 4 = 6,所以标红色 Star 的全局索引为 thread6,这是符合预期的。 当然,这是一维网格一维线程块的情况,也是最简单的情况,接着来推广到多维。

CUDA 最多其实可以组织三维的网格和线程块,可以用 dim3 的数据结构来表达,其实一维的情况也可以用 dim3 来表达,只是其他维度为 1 而已。这样来看,其实 blockIdx 和 threadIdx 是一个 uint3 的结构体,都包括 x、y、z 三个维度。再回过头来看上面的例子,对于一维的情况只用到了 x 维度,其他维度默认为 1,这个 1 若是展示出来就是 dim3,若是隐藏起来就是 int,所以 <<< _ , _ >>> 中的传参可以是 dim3 也可以为 int,奏是这么简单。

对于多维的情况,可以采用下面的定义方式:

scss 复制代码
dim3 grid_size(Gx, Gy, Gz);
dim3 block_size(Bx, By, Bz);

kernel_ful<<<grid_size, block_size>>>();

具体来说,比如定义一个 2 x 3 x 1 的网格、6 x 2 x 2 的线程块,可以这么写,

scss 复制代码
dim3 grid_size(2, 3);  // or dim3 grid_size(2, 3, 1);
dim3 block_size(6, 2, 2);

kernel_ful<<<grid_size, block_size>>>();

然后继续来看这张图,

前面说到 CUDA 线程模型的矩阵排布和咱们通常理解的数学矩阵排布秩序不太一样,看上图中 Block(1, 1) 中的矩阵排布,第一排是 (0, 0)、(1, 0)、(2, 0)、(3, 0),是最先变化 x;第一列是 (0, 0)、(0, 1)、(0, 2),再变化 y,原点是在左上。整体的排序组织顺序是下面这样的,

下面介绍 CUDA 线程全局索引的计算方式,全部列举出来其实是有下面九种情况,

  • 一维网格一维线程块;
  • 一维网格两维线程块;
  • 一维网格三维线程块;
  • 两维网格一维线程块;
  • 两维网格两维线程块;
  • 两维网格三维线程块;
  • 三维网格一维线程块;
  • 三维网格两维线程块;
  • 三维网格三维线程块;

前面已经介绍过一维网格一维线程块的线程全局索引的计算方式,接着来介绍二维网格二维线程块的计算方式,如下,

要计算上图中红色块的线程索引,调用核函数的线程配置代码如下,

scss 复制代码
dim3 grid_size(3, 2);
dim3 block_size(4, 4);

kernel_ful<<<grid_size, block_size>>>();

然后开始计算,

ini 复制代码
int blockId = blockIdx.x + blockId.y * gridDim.x;
int threadId = threadIdx.y * blockDim.x + threadIdx.x;
int id = blockId * (blockDim.x * blockDim.y) + threadId;

// 带入计算
int blockId = 1 + 1 * 3 = 4;
int threadId = 2 * 4 + 2 = 10;
int id = 4 * (4 * 4) + 10 = 74;

所以计算出来,红色块线程的全局索引就为 thread74,这也是符合预期的。

三维的图画画起来稍显复杂,我这里就不画画了。

其实仔细想想,上面的九种组织情况都可以视为是 三维网格三维线程块 的情况,只是比如一维或者二维的时候,其他维度为 1 而已。若是都把它们都看成三维格式,这样不管哪种线程组织方式,都可以套用 三维网格三维线程块 的计算方式,整理如下,

ini 复制代码
// 线程块索引
int blockId = blockIdx.x + blockIdx.y * gridDim.x + gridDim.x * gridDim.y * blockIdx.z;
// 局部线程索引
int threadId = threadIdx.z * blockDim.x * blockDim.y + threadIdx.y * blockDim.x + threadIdx.x;
// 全局线程索引
int id = blockId * (blockDim.x * blockDim.y * blockDim.z) + threadId;

好了,以上分享了 CUDA线程全局索引计算方式,希望我的分享能对你的学习有一点帮助。


 【公众号传送】

《极智开发 | CUDA线程模型与全局索引计算方式》

畅享人工智能的科技魅力,让好玩的AI项目不难玩。邀请您加入我的知识星球, 星球内我精心整备了大量好玩的AI项目,皆以工程源码形式开放使用,涵盖人脸、检测、分割、多模态、AIGC、自动驾驶、工业等。一定会对你学习有所帮助,也一定非常好玩,并持续更新更加有趣的项目。 t.zsxq.com/0aiNxERDq

相关推荐
Rain的Java大神之路4 分钟前
[特殊字符]8年Java老兵转型AI Agent:90%的人挂在同一个坑,根本不用学Python!(万字实战复盘,建议收藏)
java·数据库·人工智能·后端·python·spring·ai编程
云和数据.ChenGuang7 分钟前
Codex 下载与本地部署实战:从零搭建你的 AI 编程助手
人工智能·深度学习·机器学习·语言模型·fastapi
禹凕13 分钟前
深度学习之反向传播与全流程(Deep Learning about Backpropagation and Entire Process)
人工智能·深度学习
康实训15 分钟前
CGA老年综合评估是什么?评估体系、核心维度与行业应用标准解析
大数据·人工智能·实训室·实训室建设
xsd2024111829 分钟前
手机一扫自动读牌:摄像头识别发牌次序、牌面信息与各家牌型
人工智能
符号看象限_Wangerer35 分钟前
端到端模型的主流方案
人工智能
码云之上36 分钟前
Prompt 拦不住 Chatbot 的安全问题:九大风险与分层防护
人工智能·架构·全栈
具身AGI40 分钟前
一个纹理球,让 VLA 操作大面积失败
人工智能
AI 极客1 小时前
Google AI模式开始主动“盯”价格和库存:当AI搜索从“问一次”变成“持续监控”,企业的GEO打法要跟着调整
人工智能·搜索引擎·geo
项目治理之道1 小时前
金融科技部主导的“科技一体化管理“革命维普 Visual ALM 如何以 AI Agent 重塑项目管理全链路
人工智能·项目管理工具·项目管理软件·项目管理系统·全生命周期管理