推理部署---CUDA 执行模型(SM、Block、Warp 与 SIMT)

一、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的指令。其核心工作流程如下:

  1. Block分配 :当核函数启动时,CUDA运行时将Block分配到空闲的SM上。一个Block一旦被分配到某个SM,就会在该SM上执行完毕,不会迁移到其他SM
  2. Warp生成:SM将Block内的线程按顺序划分为多个Warp,每个Warp包含32个连续的线程。
  3. Warp调度:Warp调度器从就绪队列中选择一个Warp,将其指令发射到计算核心执行。
  4. 指令执行:计算核心并行执行Warp内所有线程的同一条指令。
  5. 上下文切换:当某个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)

影响占用率的三个主要因素

  1. 每个Block使用的寄存器数:每个线程使用的寄存器数 × Block大小
  2. 每个Block使用的共享内存数
  3. 每个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执行的四个关键特征

  1. 锁步执行(Lockstep Execution):Warp内的所有线程在同一时刻执行同一条指令
  2. 线程独立状态:每个线程有自己的PC、寄存器和栈,可以独立分支
  3. 分支分化(Branch Divergence):当Warp内的线程执行不同的代码路径时,会发生分支分化,导致性能下降
  4. 延迟隐藏:通过快速切换Warp来隐藏内存访问和计算延迟

4.3 分支分化(Branch Divergence)

分支分化是SIMT架构最主要的性能瓶颈之一。当Warp内的线程遇到条件分支时:

  1. SM会依次执行所有分支路径
  2. 对于每个分支路径,只有属于该路径的线程会被激活
  3. 不属于该路径的线程会被禁用(Masked)
  4. 当所有分支路径执行完毕后,线程重新汇合

分支分化的性能损失

  • 如果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调度策略

  1. Round-Robin(轮询):按顺序循环调度所有就绪Warp(默认策略)
  2. GTO(Greedy Then Oldest):优先调度最近就绪的Warp,然后调度最老的Warp(Volta及以上架构)
  3. 优先级调度:支持不同优先级的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内同步的方法:

  1. 全局内存标志位:使用原子操作设置和检查全局内存中的标志位(适用于所有架构)
  2. 协作组(Cooperative Groups):CUDA 9.0引入的特性,支持灵活的线程组同步,包括Grid级同步
  3. 动态并行(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周期(缓存命中) 二维/三维数据访问

内存访问的性能优化原则

  1. 合并访问(Coalesced Access):Warp内的线程访问连续的全局内存地址,这样可以合并为一个内存事务
  2. 优先使用寄存器和共享内存:尽量将频繁访问的数据放在寄存器和共享内存中
  3. 利用缓存:合理利用L1和L2缓存,减少全局内存访问次数
  4. 避免共享内存体冲突(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执行模型,性能优化的核心原则可以总结为:

  1. 最大化并行度:使用足够多的线程和Block,充分利用所有SM的计算资源
  2. 提高占用率:合理使用寄存器和共享内存,提高SM的资源利用率
  3. 避免分支分化:尽量让Warp内的线程执行相同的代码路径
  4. 优化内存访问:实现合并访问,优先使用寄存器和共享内存
  5. 隐藏延迟:使用足够多的Warp来隐藏内存访问和计算延迟
  6. 利用硬件特性:使用Tensor Core、结构化稀疏等最新硬件特性加速计算

总结

CUDA执行模型的核心是SIMT架构,通过将计算任务分解为大量轻量级线程,以Warp为单位在SM上执行。

随着GPU架构的不断演进,CUDA执行模型也在不断完善,从最初的简单SIMT到Volta的独立线程调度,再到Hopper的线程块集群和Blackwell的统一内存系统,NVIDIA一直在努力提高GPU的可编程性和性能。对于开发者来说,深入理解这些底层机制,才能充分发挥GPU的计算能力。

相关推荐
淮南颂恩少儿编程C++1 小时前
在淮南:编程信息学培训与 C++ 信奥赛:从 CSP 到 NOI 的进阶之路
人工智能·学习·青少年编程
甲维斯1 小时前
真不想吹Claude Fable了,奈何实力不允许!
人工智能·ai编程·游戏开发
想要成为计算机高手1 小时前
用meta quest 3 遥操宇树机器人-xr_teleoperate 复现(含docker安装与配置方式)
人工智能·docker·机器人·xr·g1·具身智能
aqi001 小时前
15天学会AI应用开发(六)使用离线大模型对文本生成摘要
人工智能·python·ai编程
qq_411262421 小时前
AI-02模组架构与Coze智能体接入说明
人工智能·ai·架构·esp32-c3·coze·四博
果丁智能1 小时前
民宿/网约房数字化升级:基于智能锁的身份核验与远程授权解决方案
人工智能·智能家居
知识浅谈1 小时前
人工智能日报 每日AI新闻(2026年6月12日):Agent安全、AI编程与国内高考场景加速落地
人工智能·安全·ai编程
麦哲思科技任甲林1 小时前
让AI帮我们写工作日志
人工智能·ai编程·日志
invicinble1 小时前
对于使用qoder --ai ide相关使用心得
ide·人工智能