一、CUDA执行模型概述
CUDA(Compute Unified Device Architecture)是NVIDIA推出的通用并行计算平台和编程模型,其核心设计哲学是单指令多线程(Single-Instruction Multiple-Thread, SIMT),通过将计算任务分解为大量轻量级线程,利用GPU的大规模并行计算能力加速应用程序。
CUDA执行模型定义了主机-设备(Host-Device) 异构计算架构:
- 主机(Host):运行在CPU上的串行或并行代码,负责初始化GPU、分配内存、启动核函数(Kernel)
- 设备(Device):运行在GPU上的并行代码,以核函数为单位执行,每个核函数由数千到数百万个线程组成
核函数启动时,用户指定线程层次结构(Grid-Block-Thread),CUDA运行时将这些线程映射到GPU的物理计算单元(SM)上执行。
二、线程层次结构:从逻辑到物理
2.1 三维线程层次
CUDA采用三维层次结构组织线程,这是为了方便映射不同维度的问题空间(如图像、矩阵、体数据):
Grid(1D/2D/3D)
└── Block(1D/2D/3D)
└── Thread(1D/2D/3D)
#mermaid-svg-E9JPvndDTwvZkVNL{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-E9JPvndDTwvZkVNL .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-E9JPvndDTwvZkVNL .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-E9JPvndDTwvZkVNL .error-icon{fill:#552222;}#mermaid-svg-E9JPvndDTwvZkVNL .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-E9JPvndDTwvZkVNL .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-E9JPvndDTwvZkVNL .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-E9JPvndDTwvZkVNL .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-E9JPvndDTwvZkVNL .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-E9JPvndDTwvZkVNL .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-E9JPvndDTwvZkVNL .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-E9JPvndDTwvZkVNL .marker{fill:#333333;stroke:#333333;}#mermaid-svg-E9JPvndDTwvZkVNL .marker.cross{stroke:#333333;}#mermaid-svg-E9JPvndDTwvZkVNL svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-E9JPvndDTwvZkVNL p{margin:0;}#mermaid-svg-E9JPvndDTwvZkVNL .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-E9JPvndDTwvZkVNL .cluster-label text{fill:#333;}#mermaid-svg-E9JPvndDTwvZkVNL .cluster-label span{color:#333;}#mermaid-svg-E9JPvndDTwvZkVNL .cluster-label span p{background-color:transparent;}#mermaid-svg-E9JPvndDTwvZkVNL .label text,#mermaid-svg-E9JPvndDTwvZkVNL span{fill:#333;color:#333;}#mermaid-svg-E9JPvndDTwvZkVNL .node rect,#mermaid-svg-E9JPvndDTwvZkVNL .node circle,#mermaid-svg-E9JPvndDTwvZkVNL .node ellipse,#mermaid-svg-E9JPvndDTwvZkVNL .node polygon,#mermaid-svg-E9JPvndDTwvZkVNL .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-E9JPvndDTwvZkVNL .rough-node .label text,#mermaid-svg-E9JPvndDTwvZkVNL .node .label text,#mermaid-svg-E9JPvndDTwvZkVNL .image-shape .label,#mermaid-svg-E9JPvndDTwvZkVNL .icon-shape .label{text-anchor:middle;}#mermaid-svg-E9JPvndDTwvZkVNL .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-E9JPvndDTwvZkVNL .rough-node .label,#mermaid-svg-E9JPvndDTwvZkVNL .node .label,#mermaid-svg-E9JPvndDTwvZkVNL .image-shape .label,#mermaid-svg-E9JPvndDTwvZkVNL .icon-shape .label{text-align:center;}#mermaid-svg-E9JPvndDTwvZkVNL .node.clickable{cursor:pointer;}#mermaid-svg-E9JPvndDTwvZkVNL .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-E9JPvndDTwvZkVNL .arrowheadPath{fill:#333333;}#mermaid-svg-E9JPvndDTwvZkVNL .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-E9JPvndDTwvZkVNL .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-E9JPvndDTwvZkVNL .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-E9JPvndDTwvZkVNL .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-E9JPvndDTwvZkVNL .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-E9JPvndDTwvZkVNL .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-E9JPvndDTwvZkVNL .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-E9JPvndDTwvZkVNL .cluster text{fill:#333;}#mermaid-svg-E9JPvndDTwvZkVNL .cluster span{color:#333;}#mermaid-svg-E9JPvndDTwvZkVNL div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-E9JPvndDTwvZkVNL .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-E9JPvndDTwvZkVNL rect.text{fill:none;stroke-width:0;}#mermaid-svg-E9JPvndDTwvZkVNL .icon-shape,#mermaid-svg-E9JPvndDTwvZkVNL .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-E9JPvndDTwvZkVNL .icon-shape p,#mermaid-svg-E9JPvndDTwvZkVNL .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-E9JPvndDTwvZkVNL .icon-shape .label rect,#mermaid-svg-E9JPvndDTwvZkVNL .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-E9JPvndDTwvZkVNL .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-E9JPvndDTwvZkVNL .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-E9JPvndDTwvZkVNL :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}#mermaid-svg-E9JPvndDTwvZkVNL .root>*{fill:#f3e8ff!important;stroke:#9333ea!important;stroke-width:2px!important;color:#3b076b!important;}#mermaid-svg-E9JPvndDTwvZkVNL .root span{fill:#f3e8ff!important;stroke:#9333ea!important;stroke-width:2px!important;color:#3b076b!important;}#mermaid-svg-E9JPvndDTwvZkVNL .root tspan{fill:#3b076b!important;}#mermaid-svg-E9JPvndDTwvZkVNL .grid>*{fill:#dbeafe!important;stroke:#2563eb!important;stroke-width:2px!important;color:#1e3a8a!important;}#mermaid-svg-E9JPvndDTwvZkVNL .grid span{fill:#dbeafe!important;stroke:#2563eb!important;stroke-width:2px!important;color:#1e3a8a!important;}#mermaid-svg-E9JPvndDTwvZkVNL .grid tspan{fill:#1e3a8a!important;}#mermaid-svg-E9JPvndDTwvZkVNL .block>*{fill:#fce7f3!important;stroke:#db2777!important;stroke-width:2px!important;color:#831843!important;}#mermaid-svg-E9JPvndDTwvZkVNL .block span{fill:#fce7f3!important;stroke:#db2777!important;stroke-width:2px!important;color:#831843!important;}#mermaid-svg-E9JPvndDTwvZkVNL .block tspan{fill:#831843!important;}#mermaid-svg-E9JPvndDTwvZkVNL .warp>*{fill:#d1fae5!important;stroke:#059669!important;stroke-width:2px!important;color:#064e3b!important;}#mermaid-svg-E9JPvndDTwvZkVNL .warp span{fill:#d1fae5!important;stroke:#059669!important;stroke-width:2px!important;color:#064e3b!important;}#mermaid-svg-E9JPvndDTwvZkVNL .warp tspan{fill:#064e3b!important;} 🚀 Kernel Launch
🌐 Grid
Block 0
Block 1
Block N
Warp 0
32 threads
Warp 1
32 threads
...
Warp 0
32 threads
Warp 1
32 threads
...
...
- Grid:一个核函数的所有线程组成一个Grid,是最大的逻辑执行单元
- Block :Grid被划分为多个Block,Block是资源分配和调度的基本单位
- Thread:Block被划分为多个Thread,是最小的执行单元
2.2 内置变量与索引计算
CUDA提供了一组内置变量,用于线程在层次结构中定位自己:
| 变量名 | 类型 | 含义 | 范围 |
|---|---|---|---|
threadIdx |
dim3 |
线程在Block内的三维索引 | (0,0,0) 到 (blockDim.x-1, blockDim.y-1, blockDim.z-1) |
blockIdx |
dim3 |
Block在Grid内的三维索引 | (0,0,0) 到 (gridDim.x-1, gridDim.y-1, gridDim.z-1) |
blockDim |
dim3 |
每个Block的三维大小(线程数) | 由用户在核函数启动时指定 |
gridDim |
dim3 |
Grid的三维大小(Block数) | 由用户在核函数启动时指定 |
warpSize |
int |
每个Warp包含的线程数 | 所有NVIDIA GPU均为32(架构无关) |
全局唯一索引计算(最常用的一维索引):
cpp
// 一维Grid + 一维Block
int global_idx = blockIdx.x * blockDim.x + threadIdx.x;
// 二维Grid + 二维Block(图像处理常用)
int global_idx = (blockIdx.y * gridDim.x + blockIdx.x) * (blockDim.x * blockDim.y)
+ threadIdx.y * blockDim.x + threadIdx.x;
2.3 线程层次的约束条件
不同架构的GPU对线程层次有不同的硬件限制(以Hopper H100为例):
- 每个Block的最大线程数:1024(自Fermi架构以来保持不变)
- 每个Block的最大维度:
(1024, 1024, 64) - 每个Grid的最大维度:
(2^31-1, 65535, 65535) - 每个SM最多可同时驻留的Block数:32(Hopper)
- 每个SM最多可同时驻留的线程数:2048(Hopper)
三、流式多处理器(SM):GPU的核心计算单元
3.1 SM的基本架构
SM(Streaming Multiprocessor)是GPU的独立计算单元,一个GPU由多个SM组成(如H100有144个SM,B100有132个SM)。每个SM拥有自己的:
- 计算核心(CUDA Core、Tensor Core、RT Core等)
- 寄存器文件(Register File)
- 共享内存(Shared Memory)
- L1缓存
- 线程调度器(Warp Scheduler)
- 指令缓存
Hopper H100 SM架构图 :

3.2 SM的工作原理
SM采用超标量SIMT架构,每个时钟周期可以执行多个Warp的指令。其核心工作流程如下:
- Block分配 :当核函数启动时,CUDA运行时将Block分配到空闲的SM上。一个Block一旦被分配到某个SM,就会在该SM上执行完毕,不会迁移到其他SM。
- Warp生成:SM将Block内的线程按顺序划分为多个Warp,每个Warp包含32个连续的线程。
- Warp调度:Warp调度器从就绪队列中选择一个Warp,将其指令发射到计算核心执行。
- 指令执行:计算核心并行执行Warp内所有线程的同一条指令。
- 上下文切换:当某个Warp因等待内存访问或同步操作而阻塞时,Warp调度器会立即切换到另一个就绪Warp,隐藏延迟。
3.3 SM资源限制与占用率
SM的资源(寄存器、共享内存)是有限的,这些资源决定了每个SM最多可以同时驻留多少个Block和Warp,即占用率(Occupancy)。
占用率计算公式 :
Occupancy=(ActiveWarpsperSM)/(MaxWarpsperSM)Occupancy = (Active Warps per SM) / (Max Warps per SM)Occupancy=(ActiveWarpsperSM)/(MaxWarpsperSM)
影响占用率的三个主要因素:
- 每个Block使用的寄存器数:每个线程使用的寄存器数 × Block大小
- 每个Block使用的共享内存数
- 每个Block的线程数
Hopper H100 SM资源限制:
- 寄存器文件总大小:256KB = 65536 × 32-bit寄存器
- 共享内存总大小:256KB
- 最大驻留Warp数:64(2048线程 ÷ 32线程/Warp)
示例:如果一个核函数每个线程使用32个寄存器,Block大小为256线程,则每个Block需要:
- 寄存器:32 × 256 = 8192个
- 每个SM最多可驻留Block数:65536 ÷ 8192 = 8个
- 每个SM驻留线程数:8 × 256 = 2048个(达到最大值)
- 占用率:2048 ÷ 2048 = 100%
四、Warp:SIMT执行的基本单位
4.1 Warp的基本概念
Warp是SM执行指令的基本单位,每个Warp包含32个线程。SM以Warp为单位调度和执行指令,这是SIMT架构的核心特征。
Warp的生成规则:
- Block内的线程按行优先顺序连续划分为Warp
- 第一个Warp包含线程0 ~ 31,第二个包含32 ~ 63,依此类推
- 如果Block的线程数不是32的整数倍,最后一个Warp会包含不足32个线程(称为"Partial Warp"),这些线程仍然会被执行,但会浪费计算资源
4.2 SIMT执行模型
SIMT(Single-Instruction Multiple-Thread)是CUDA区别于传统SIMD(Single-Instruction Multiple-Data)的核心架构。
SIMT与SIMD的本质区别:
- SIMD:一条指令对多个数据元素执行相同操作,数据元素是连续的,程序员显式管理向量
- SIMT:一条指令对多个线程执行相同操作,每个线程有自己的程序计数器(PC)和寄存器状态,可以独立执行不同的代码路径
SIMT执行的四个关键特征:
- 锁步执行(Lockstep Execution):Warp内的所有线程在同一时刻执行同一条指令
- 线程独立状态:每个线程有自己的PC、寄存器和栈,可以独立分支
- 分支分化(Branch Divergence):当Warp内的线程执行不同的代码路径时,会发生分支分化,导致性能下降
- 延迟隐藏:通过快速切换Warp来隐藏内存访问和计算延迟
4.3 分支分化(Branch Divergence)
分支分化是SIMT架构最主要的性能瓶颈之一。当Warp内的线程遇到条件分支时:
- SM会依次执行所有分支路径
- 对于每个分支路径,只有属于该路径的线程会被激活
- 不属于该路径的线程会被禁用(Masked)
- 当所有分支路径执行完毕后,线程重新汇合
分支分化的性能损失:
- 如果Warp内的线程分为N个分支路径,则执行时间大约是无分支时的N倍
- 最坏情况:每个线程执行不同的路径,性能下降32倍
分支分化的优化原则:
- 尽量让Warp内的线程执行相同的代码路径
- 基于
threadIdx的分支通常不会导致分化(如if (threadIdx.x < 16)) - 使用
__syncwarp()显式同步Warp内的线程 - 对于Hopper及以上架构,使用线程束内原语(Warp Intrinsics) 如
__shfl_sync()、__any_sync()等
4.4 Warp调度策略
SM的Warp调度器采用零开销上下文切换策略,当一个Warp阻塞时,调度器可以在一个时钟周期内切换到另一个就绪Warp。
主要的Warp调度策略:
- Round-Robin(轮询):按顺序循环调度所有就绪Warp(默认策略)
- GTO(Greedy Then Oldest):优先调度最近就绪的Warp,然后调度最老的Warp(Volta及以上架构)
- 优先级调度:支持不同优先级的Warp调度(Hopper及以上架构)
延迟隐藏的原理:
- 内存访问延迟:约400~800个时钟周期
- 每个SM最多可驻留64个Warp(Hopper)
- 只要有足够多的就绪Warp,SM就可以一直保持忙碌,隐藏延迟
五、线程同步与通信
5.1 Block内同步:__syncthreads()
__syncthreads()是CUDA中最常用的同步原语,用于同步同一个Block内的所有线程。
工作原理:
- 当一个线程调用
__syncthreads()时,它会阻塞直到Block内的所有线程都到达该同步点 - 所有线程到达后,同步点释放,线程继续执行
注意事项:
__syncthreads()必须被Block内的所有线程执行,否则会导致死锁__syncthreads()不能放在条件分支中,除非该分支被Block内的所有线程执行__syncthreads()只同步线程的执行,不同步内存操作,需要配合内存屏障使用
5.2 Warp内同步:__syncwarp()
__syncwarp()用于同步同一个Warp内的所有线程 ,比__syncthreads()更轻量级。
工作原理:
- 当一个线程调用
__syncwarp()时,它会阻塞直到Warp内的所有线程都到达该同步点 - 所有线程到达后,同步点释放,线程继续执行
使用场景:
- Warp内的线程通信(如使用
__shfl_sync()进行数据交换) - 优化Block内同步的性能(只同步需要的Warp)
5.3 Grid内同步
CUDA提供了多种Grid内同步的方法:
- 全局内存标志位:使用原子操作设置和检查全局内存中的标志位(适用于所有架构)
- 协作组(Cooperative Groups):CUDA 9.0引入的特性,支持灵活的线程组同步,包括Grid级同步
- 动态并行(Dynamic Parallelism):CUDA 5.0引入的特性,允许核函数在GPU上启动其他核函数,实现嵌套并行和同步
六、内存层次结构与执行模型的关系
CUDA的内存层次结构与执行模型紧密结合,不同层次的内存对应不同的线程访问范围:
| 内存类型 | 位置 | 访问范围 | 大小 | 延迟 | 带宽 | 用途 |
|---|---|---|---|---|---|---|
| 寄存器 | SM内 | 单个线程 | 每个线程最多255个 | ~1周期 | 最高 | 临时变量 |
| 共享内存 | SM内 | 同一个Block内的线程 | 256KB/SM(Hopper) | ~10周期 | ~19TB/s | Block内线程通信 |
| L1缓存 | SM内 | 同一个SM内的线程 | 256KB/SM(Hopper) | ~20周期 | ~19TB/s | 缓存全局内存访问 |
| L2缓存 | GPU内 | 所有SM | 50MB(H100) | ~50周期 | ~6TB/s | 缓存全局内存访问 |
| 全局内存 | GPU外 | 所有线程 | 80GB(H100 SXM) | 400800周期 | ~3.35TB/s | 大规模数据存储 |
| 常量内存 | GPU外 | 所有线程 | 64KB | ~5周期(缓存命中) | 高 | 只读常量数据 |
| 纹理内存 | GPU外 | 所有线程 | 无限制 | ~5周期(缓存命中) | 高 | 二维/三维数据访问 |
内存访问的性能优化原则:
- 合并访问(Coalesced Access):Warp内的线程访问连续的全局内存地址,这样可以合并为一个内存事务
- 优先使用寄存器和共享内存:尽量将频繁访问的数据放在寄存器和共享内存中
- 利用缓存:合理利用L1和L2缓存,减少全局内存访问次数
- 避免共享内存体冲突(Bank Conflict):合理组织共享内存的访问模式,避免多个线程同时访问同一个存储体
七、最新架构的演进
7.1 Volta架构:独立线程调度(Independent Thread Scheduling)
Volta架构引入了独立线程调度,彻底改变了SIMT的执行模型:
- 每个线程有自己的程序计数器(PC)和调用栈
- Warp内的线程可以完全独立地执行,不再强制锁步
- 分支分化的性能损失大大降低
- 支持更细粒度的同步和通信
7.2 Ampere架构:结构化稀疏与第三代Tensor Core
Ampere架构引入了:
- 结构化稀疏:支持50%稀疏的矩阵运算,Tensor Core性能提升2倍
- 第三代Tensor Core:支持TF32、FP64和INT8精度,AI推理和训练性能大幅提升
- 异步数据传输:支持异步全局内存到共享内存的传输,隐藏数据传输延迟
7.3 Hopper架构:Transformer Engine与动态并行增强
Hopper架构引入了:
- Transformer Engine:专门优化Transformer模型的硬件,支持FP8精度,AI性能提升6倍
- 线程块集群(Thread Block Cluster):允许多个Block共享同一个SM的资源,实现更高效的通信和同步
- 分布式共享内存(Distributed Shared Memory):允许Block集群内的线程访问彼此的共享内存
- 动态并行增强:支持嵌套深度达32层的动态并行,性能提升10倍以上
7.4 Blackwell架构:第二代Transformer Engine与FP4精度
Blackwell架构(2024年发布)引入了:
- 第二代Transformer Engine:支持FP4精度,AI性能比Hopper提升4倍
- 统一内存系统 :CPU和GPU共享统一的虚拟地址空间,数据传输延迟降低90%
- 实时推理优化:专门优化大语言模型的实时推理,吞吐量提升10倍以上
八、性能优化的原则
基于CUDA执行模型,性能优化的核心原则可以总结为:
- 最大化并行度:使用足够多的线程和Block,充分利用所有SM的计算资源
- 提高占用率:合理使用寄存器和共享内存,提高SM的资源利用率
- 避免分支分化:尽量让Warp内的线程执行相同的代码路径
- 优化内存访问:实现合并访问,优先使用寄存器和共享内存
- 隐藏延迟:使用足够多的Warp来隐藏内存访问和计算延迟
- 利用硬件特性:使用Tensor Core、结构化稀疏等最新硬件特性加速计算
总结
CUDA执行模型的核心是SIMT架构,通过将计算任务分解为大量轻量级线程,以Warp为单位在SM上执行。
随着GPU架构的不断演进,CUDA执行模型也在不断完善,从最初的简单SIMT到Volta的独立线程调度,再到Hopper的线程块集群和Blackwell的统一内存系统,NVIDIA一直在努力提高GPU的可编程性和性能。对于开发者来说,深入理解这些底层机制,才能充分发挥GPU的计算能力。