news 2026/9/23 7:17:47

线程层次结构:Thread, Block, Grid

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
线程层次结构:Thread, Block, Grid

CUDA 编程模型采用了一个三层的线程层次结构,旨在映射到 GPU 硬件的多级架构,实现最大的并行性和数据局部性。

1. 线程 (Thread)

线程是 CUDA 并行计算的基本执行单元

  • 定义:在 Kernel 函数中,每个并行计算的实例就是一个线程。例如,在向量加法中,一个线程负责计算C[i]=A[i]+B[i]C[i] = A[i] + B[i]C[i]=A[i]+B[i]

  • 标识:每个线程都有一个内置的唯一标识符threadIdx

    • threadIdx.xthreadIdx.ythreadIdx.z:线程在当前线程块内的坐标。
  • 执行:线程执行 Kernel 代码中定义的指令,访问私有寄存器(Registers)和线程块共享内存(Shared Memory)。

  • 独立性:理想情况下,每个线程应独立执行其任务,减少相互依赖,以实现最大并行效率。

2. 线程块 (Block)

线程块是线程的分组容器,是线程间协作的基本单位。

  • 定义:一组协作的线程集合,它们共同执行 Kernel 的一个子任务。

  • 标识:每个线程块都有一个内置的唯一标识符blockIdx

    • blockIdx.xblockIdx.yblockIdx.z:线程块在网格内的坐标。
  • 维度:线程块可以定义为一维、二维或三维结构(dim3 blockDim;)。

    • blockDim.xblockDim.yblockDim.z:定义了线程块中线程的数量和排列方式。
  • 协作与通信:

    • 共享内存:块内的线程可以通过共享内存(Shared Memory)进行高速数据交换。

    • 同步屏障:块内的线程可以通过__syncthreads()函数进行同步,确保所有线程都到达某个执行点后才能继续,这对于数据依赖的算法至关重要。

  • 硬件映射:一个线程块内的所有线程保证会被调度到同一个SM(流多处理器)上执行。这保证了块内线程对共享内存的访问非常快。

3. 网格 (Grid)

网格是线程块的最高级容器,代表一次完整的 Kernel 启动。

  • 定义:由所有线程块组成的集合,是整个并行计算任务的总和。

  • 标识:网格没有内置的索引变量,它的维度由主机在 Kernel 启动时通过gridDim参数指定。

    • gridDim.xgridDim.ygridDim.z:定义了网格中线程块的数量和排列方式。
  • 协作与通信:网格中的不同线程块原则上是相互独立的

    • 无法直接同步:不同线程块之间不能使用__syncthreads()进行同步。

    • 全局内存通信:线程块之间只能通过访问速度较慢的全局内存(Global Memory)进行通信。如果需要全局同步,必须终止当前 Kernel,在主机端同步后,再次启动一个新的 Kernel。

  • 硬件映射:网格中的线程块由 GPU 调度器分发到不同的 SM 上并行执行。


4. 如何计算全局唯一索引

理解线程层次结构的关键在于知道如何将线程的局部坐标 (blockIdxthreadIdx) 转换为它在整个网格中的全局唯一索引,即它应该处理的数据元素的索引iii

4.1 一维索引计算

对于大多数简单的一维数据结构(如向量),全局索引iii的计算公式如下:

i=blockIdx.x×blockDim.x+threadIdx.xi = \text{blockIdx.x} \times \text{blockDim.x} + \text{threadIdx.x}i=blockIdx.x×blockDim.x+threadIdx.x

变量含义
blockIdx.x\text{blockIdx.x}blockIdx.x当前块的索引
blockDim.x\text{blockDim.x}blockDim.x每个块的线程数
threadIdx.x\text{threadIdx.x}threadIdx.x线程在块内的索引

4.2 二维索引计算(例如矩阵)

对于二维数据结构(如矩阵),我们通常需要计算两个索引rrr(行)和ccc(列):

r=blockIdx.y×blockDim.y+threadIdx.yc=blockIdx.x×blockDim.x+threadIdx.xr = \text{blockIdx.y} \times \text{blockDim.y} + \text{threadIdx.y} \\ c = \text{blockIdx.x} \times \text{blockDim.x} + \text{threadIdx.x}r=blockIdx.y×blockDim.y+threadIdx.yc=blockIdx.x×blockDim.x+threadIdx.x

变量含义
blockIdx.y\text{blockIdx.y}blockIdx.y块的行索引
threadIdx.y\text{threadIdx.y}threadIdx.y线程在块内的行索引
blockDim.y\text{blockDim.y}blockDim.y每个块的线程行数

5. 层次结构与硬件的映射关系

CUDA 层次结构的设计直接反映了 NVIDIA GPU 的硬件结构,这是高效性能的关键:

  1. Grid→\toGPU:整个网格映射到整个 GPU。

  2. Block→\toSM:每个线程块被调度到一个 SM 上执行。多个块可以按时间片轮转的方式在同一个 SM 上执行,或者同时在多个 SM 上执行。

  3. Thread→\toCore:块内的线程最终映射到 SM 内部的 CUDA 核心。

    • Warp:SM 实际上是以Warp(32 个连续线程)为单位进行指令调度和执行的。一个线程块会被分解成一个或多个 Warp。

性能考虑:分块大小

选择合适的线程块大小 (blockDim) 至关重要:

  • 太小:无法充分利用 SM 的资源(如寄存器、共享内存),浪费硬件并行潜力。

  • 太大:可能超出 SM 能够提供的资源限制(如最大线程数、共享内存大小),导致 Kernel 启动失败或运行效率降低。

通常,blockDim选择 128、256 或 512,并且应为 32(Warp 大小)的倍数,以避免线程分化带来的性能损失。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/22 18:59:50

Wan2.2-T2V-5B可用于自然灾害演变过程模拟

Wan2.2-T2V-5B:用AI秒级生成灾害演变视频,让应急推演“动”起来 🌪️🔥 你有没有想过—— 一场山火如何在强风下蔓延?洪水会怎样顺着山谷吞噬村庄?地震后的次生滑坡可能影响哪些区域? 过去&…

作者头像 李华
网站建设 2026/9/22 19:01:07

鸿蒙技术干货7:通知发送与跳转服务

今天开始咱们的系统服务调用系列分享。系统服务是鸿蒙应用与底层系统交互的核心通道,而通知服务(NotificationCenter)更是高频刚需 —— 无论是消息推送、事件提醒还是功能跳转,都离不开它。这篇咱们聚焦 NotificationCenter 的核…

作者头像 李华
网站建设 2026/9/22 6:47:04

Wan2.2-T2V-A14B生成视频的音频同步问题怎么解决

Wan2.2-T2V-A14B生成视频的音频同步问题怎么解决 你有没有遇到过这种情况:AI生成的画面流畅自然,主角缓缓站起、眼神坚定地说出那句“我不会放弃”——画面堪称电影级,可一开口,声音却慢了半拍?嘴一张,音还…

作者头像 李华
网站建设 2026/9/22 5:01:02

Steamless:DRM管理工具完全使用指南

在数字游戏时代,DRM保护机制虽然保护了开发者的权益,但也给合法用户带来了诸多不便。Steamless作为专业的DRM管理工具,专门针对SteamStub保护进行优化,让您能够更自由地使用自己购买的游戏。 【免费下载链接】Steamless Steamless…

作者头像 李华
网站建设 2026/9/23 5:42:22

解码器详解(训练过程)

前文介绍:前面我们以及介绍了自然语言序列输入到模型中进行的词嵌入和位置编码的数据变化过程,编码器的结构和数据流动过程,本文在前文的基础上继续接着介绍解码器中的数据流动过程和解码器结构,阅读本文前最好参考前文&#xff1…

作者头像 李华
网站建设 2026/9/23 15:06:27

FanControl多语言界面配置:从乱码到完美显示的实用指南

FanControl多语言界面配置:从乱码到完美显示的实用指南 【免费下载链接】FanControl.Releases This is the release repository for Fan Control, a highly customizable fan controlling software for Windows. 项目地址: https://gitcode.com/GitHub_Trending/f…

作者头像 李华