NVIDIA GPU 中的 SM、Warp 与 Occupancy
更新日期:2026-10-10
数据口径:表中 SM 数量均指具体产品对 CUDA 暴露的、实际启用的 SM 数量;多 GPU 模组按"每颗 GPU"统计,除非另有说明。
1. CUDA 的执行层次
NVIDIA GPU 的 CUDA 执行层次如下:
text
GPU
└── 多个 SM(Streaming Multiprocessor)
└── 一个或多个驻留的 Thread Block / CTA
└── 多个 Warp
└── 32 个 Thread
各层含义如下:
- Thread:CUDA 的逻辑执行实例。每个线程具有自己的线程编号、寄存器状态、地址和分支状态。
- Warp :NVIDIA GPU 的基本 SIMT 执行组,固定包含 32 个线程。
- Thread Block / CTA:能够使用 Shared Memory 和组内同步进行协作的一组线程。一个 Block 在整个执行期间驻留在同一个 SM 上。
- SM:负责创建、管理、调度和执行 Warp 的物理计算单元。一个 SM 内通常包含 Warp Scheduler、寄存器文件、Shared Memory/L1、Load/Store 单元、标量/浮点执行单元和 Tensor Core 等资源;具体组成随架构变化。
- GPU:由多个 SM、L2 Cache、显存控制器和片上互连等单元构成。
2. Thread Block 与 Warp 的换算
一个 Warp 固定包含 32 个线程。一个 Thread Block 包含的 Warp 数量为:
text
每个 Block 的 Warp 数
= ceil(每个 Block 的线程数 / 32)
示例:
| 每个 Block 的线程数 | 形成的 Warp 数 | 说明 |
|---|---|---|
| 128 | 4 | 每个 Warp 都有 32 个有效线程 |
| 256 | 8 | 每个 Warp 都有 32 个有效线程 |
| 300 | 10 | 前 9 个 Warp 完整,最后一个 Warp 只有 12 个有效线程 |
| 512 | 16 | 每个 Warp 都有 32 个有效线程 |
| 1024 | 32 | CUDA Block 的常见线程数上限 |
线程数不是 32 的整数倍时,最后一个 Warp 仍按完整 Warp 分配执行资源,超出 Block 线程范围的 Lane 保持非活动状态。
3. SM 与 Warp 的关系
一个 SM 可以同时保存多个 Warp 的执行上下文,包括程序计数器、寄存器状态和其他调度状态。这些 Warp 称为驻留 Warp(Resident Warp)。
text
一个 SM
├── Resident Warp 0
├── Resident Warp 1
├── Resident Warp 2
├── ...
└── Resident Warp N
驻留并不表示所有 Warp 在同一个时钟周期同时执行。Warp 可以处于以下状态:
- Resident / Active:执行资源已经分配,Warp 已驻留在 SM 上。
- Eligible / Ready:下一条指令的操作数和执行条件已经满足,可以被调度。
- Issued:Warp Scheduler 在当前发射时机选择该 Warp,并向其活动线程发射指令。
- Stalled:Warp 正在等待内存、数据依赖、Barrier、Fence 或其他资源。
Warp Scheduler 从就绪 Warp 中选择指令发射。当一个 Warp 等待高延迟操作时,SM 可以切换到其他就绪 Warp,从而隐藏访存或流水线延迟。
4. 不同计算能力下每个 SM 的最大驻留 Warp 数
每个 SM 的最大驻留 Warp 数由 Compute Capability 决定。
| Compute Capability | 典型架构/产品 | Warp 大小 | 每个 SM 最大驻留 Warp | 每个 SM 最大驻留线程 |
|---|---|---|---|---|
| 7.5 | Turing:T4、RTX 20 系列 | 32 | 32 | 1024 |
| 8.0 | Ampere 数据中心:A100、A30 | 32 | 64 | 2048 |
| 8.6 | Ampere 消费级/工作站:RTX 30、A10 | 32 | 48 | 1536 |
| 8.7 | Ampere 嵌入式:Jetson Orin | 32 | 48 | 1536 |
| 8.9 | Ada:RTX 40、L4、L40S | 32 | 48 | 1536 |
| 9.0 | Hopper:H100、H200 | 32 | 64 | 2048 |
| 10.0 | 数据中心 Blackwell:B200、GB200 | 32 | 64 | 2048 |
| 10.3 | Blackwell Ultra:B300、GB300 | 32 | 64 | 2048 |
| 12.x | RTX Blackwell:RTX 50 系列 | 32 | 48 | 1536 |
该上限是架构上限。具体 Kernel 的实际驻留 Warp 数通常更低,并由 Block 规模、寄存器和 Shared Memory 等资源共同决定。
5. NVIDIA 主流 GPU 的 SM 数量
下表列出常见产品的实际启用 SM 数,以及按架构上限计算的整颗 GPU 理论最大驻留 Warp 数。
text
整颗 GPU 的理论最大驻留 Warp 数
= SM 数量 × 每个 SM 最大驻留 Warp 数
| 产品 | 架构 | Compute Capability | SM 数量 | 每个 SM 最大驻留 Warp | 整颗 GPU 理论最大驻留 Warp | 理论最大驻留线程状态 |
|---|---|---|---|---|---|---|
| NVIDIA T4 | Turing | 7.5 | 40 | 32 | 1,280 | 40,960 |
| GeForce RTX 2080 Ti | Turing | 7.5 | 68 | 32 | 2,176 | 69,632 |
| NVIDIA A100 | Ampere 数据中心 | 8.0 | 108 | 64 | 6,912 | 221,184 |
| GeForce RTX 3070 Laptop GPU | Ampere | 8.6 | 40 | 48 | 1,920 | 61,440 |
| GeForce RTX 3070 | Ampere | 8.6 | 46 | 48 | 2,208 | 70,656 |
| GeForce RTX 3090 | Ampere | 8.6 | 82 | 48 | 3,936 | 125,952 |
| GeForce RTX 3090 Ti | Ampere | 8.6 | 84 | 48 | 4,032 | 129,024 |
| GeForce RTX 4090 | Ada Lovelace | 8.9 | 128 | 48 | 6,144 | 196,608 |
| NVIDIA H100 PCIe | Hopper | 9.0 | 114 | 64 | 7,296 | 233,472 |
| NVIDIA H100 SXM | Hopper | 9.0 | 132 | 64 | 8,448 | 270,336 |
| NVIDIA B200 | Blackwell 数据中心 | 10.0 | 148 | 64 | 9,472 | 303,104 |
| NVIDIA B300 | Blackwell Ultra | 10.3 | 148 | 64 | 9,472 | 303,104 |
| GeForce RTX 5090 | Blackwell 消费级 | 12.0 | 170 | 48 | 8,160 | 261,120 |
"理论最大驻留线程状态"表示 GPU 最多能够在片上保存多少个逻辑线程的执行状态,不表示这些线程在同一周期全部执行。
5.1 产品版本差异
同一代 GPU 的不同产品可能启用不同数量的 SM:
text
完整 GH100 裸片:144 SM
H100 SXM: 132 SM
H100 PCIe: 114 SM
text
完整 GB202 裸片:192 SM
RTX 5090: 170 SM
text
完整 AD102 裸片:144 SM
RTX 4090: 128 SM
因此,裸片设计中的最大 SM 数不能直接作为具体显卡的 SM 数。CUDA 调优应以运行时查询到的具体设备属性为准。
6. Occupancy
Occupancy 通常译为占用率,表示一个 SM 上实际驻留的 Warp 数与该架构每个 SM 最大驻留 Warp 数之比。
text
Occupancy
= 实际驻留 Warp 数 / 每个 SM 最大驻留 Warp 数
Occupancy 是每个 SM 的指标,不是整颗 GPU 的统一线程利用率。
6.1 驻留 Warp 数的计算
text
warps_per_block
= ceil(threads_per_block / 32)
text
resident_blocks_per_sm
= min(
Block 数上限,
线程数上限,
Warp 数上限,
寄存器容量限制,
Shared Memory 容量限制
)
text
resident_warps_per_sm
= resident_blocks_per_sm × warps_per_block
text
occupancy
= resident_warps_per_sm / max_warps_per_sm
影响 Occupancy 的主要因素包括:
- 每个 Block 的线程数;
- 每个线程使用的寄存器数量;
- 每个 Block 使用的静态和动态 Shared Memory;
- 每个 SM 的最大线程数、Warp 数和 Block 数;
- 寄存器和 Shared Memory 的硬件分配粒度。
6.2 RTX 3070 Laptop GPU 示例
RTX 3070 Laptop GPU 的主要参数为:
text
SM 数量:40
Compute Capability:8.6
每个 SM 最大驻留 Warp:48
每个 SM 最大驻留线程:1536
采用 256 个线程的 Block:
text
每个 Block 的 Warp 数
= 256 / 32
= 8
若资源允许每个 SM 驻留 6 个 Block:
text
驻留 Warp 数
= 6 × 8
= 48
Occupancy
= 48 / 48
= 100%
若寄存器或 Shared Memory 只允许每个 SM 驻留 4 个 Block:
text
驻留 Warp 数
= 4 × 8
= 32
Occupancy
= 32 / 48
≈ 66.7%
整颗 RTX 3070 Laptop GPU 的理论最大驻留规模为:
text
40 SM × 48 Warp/SM
= 1920 Warp
1920 Warp × 32 Thread/Warp
= 61,440 个逻辑线程状态
7. Occupancy 与性能的关系
较高的 Occupancy 能够提供更多候选 Warp,便于 Warp Scheduler 在某些 Warp 等待内存或数据依赖时切换到其他 Warp,从而隐藏延迟。
Occupancy 不等于 GPU 利用率,也不是越高越好。以下情况可能使较高 Occupancy 无法带来更高性能:
- 所有驻留 Warp 同时等待显存;
- Kernel 受显存带宽限制;
- 分支发散导致大量 Lane 非活动;
- 为提高 Occupancy 而限制寄存器,产生 Register Spill;
- 为减少 Shared Memory 而缩小 Tile,导致数据复用下降;
- 少量 Warp 已经足以隐藏当前指令延迟。
性能优化的目标是提供足够的可执行 Warp,同时保留合理的寄存器、Shared Memory、Tile 大小和数据复用能力,而不是机械地追求 100% Occupancy。
8. SM 数量不能直接代表 GPU 性能
SM 数量只表示一颗 GPU 包含多少个并行计算单元。跨架构比较时,GPU 性能还取决于:
text
SM 数量
× 每个 SM 的执行能力
× 工作频率
× Tensor Core 代际和数据类型
× 显存带宽与容量
× L2 Cache 和片上互连
× 功耗限制
× 实际工作负载
例如 RTX 5090 有 170 个 SM,B200 有 148 个 SM,但两者的产品定位、SM 结构、Tensor Core、内存系统和支持的数据类型不同,不能仅根据 SM 数量判断总体性能。
9. 查询实际设备参数
9.1 CUDA Runtime
cpp
#include <cuda_runtime.h>
#include <iostream>
int main() {
int device = 0;
cudaDeviceProp prop{};
cudaError_t status = cudaGetDeviceProperties(&prop, device);
if (status != cudaSuccess) {
std::cerr << "CUDA error: "
<< cudaGetErrorString(status) << '\n';
return 1;
}
const int maxWarpsPerSM =
prop.maxThreadsPerMultiProcessor / prop.warpSize;
std::cout << "GPU: " << prop.name << '\n';
std::cout << "Compute Capability: "
<< prop.major << '.' << prop.minor << '\n';
std::cout << "SM count: "
<< prop.multiProcessorCount << '\n';
std::cout << "Warp size: "
<< prop.warpSize << '\n';
std::cout << "Max resident threads per SM: "
<< prop.maxThreadsPerMultiProcessor << '\n';
std::cout << "Max resident warps per SM: "
<< maxWarpsPerSM << '\n';
return 0;
}
9.2 PyTorch
python
import torch
properties = torch.cuda.get_device_properties(0)
print("GPU:", properties.name)
print("Compute Capability:", torch.cuda.get_device_capability(0))
print("SM count:", properties.multi_processor_count)
9.3 Nsight Compute
bash
ncu --section LaunchStats --section Occupancy ./your_program
Nsight Compute 可以显示:
- Block 和 Grid 规模;
- 每线程寄存器数;
- 每 Block Shared Memory;
- 理论 Occupancy;
- Achieved Occupancy;
- Occupancy 的主要限制资源。
10. 核心关系
text
一个 Warp = 32 个 Thread
text
一个 Block 的 Warp 数
= ceil(Block 线程数 / 32)
text
一个 SM 可以驻留多个 Block
一个 Block 被拆成多个 Warp
Warp Scheduler 从就绪 Warp 中选择指令发射
text
Occupancy
= 每个 SM 实际驻留 Warp 数
÷
每个 SM 最大驻留 Warp 数
text
整颗 GPU 的理论最大驻留 Warp 数
= SM 数量 × 每个 SM 最大驻留 Warp 数
SM 数量描述整颗 GPU 的并行计算单元规模;每个 SM 的最大驻留 Warp 数描述该 SM 可保存的线程级并行状态;Occupancy 描述具体 Kernel 对这一驻留能力的使用程度。
参考资料
- NVIDIA CUDA Programming Guide:SIMT Architecture、Hardware Multithreading、Compute Capabilities。
- NVIDIA CUDA GPU Compute Capability 产品列表。
- NVIDIA RTX Blackwell GPU Architecture Whitepaper。
- NVIDIA Hopper Architecture In-Depth。
- NVIDIA Ampere、Ada Lovelace 架构白皮书与产品规格。
- NVIDIA CUDA MPS MLOPart 技术说明(B200/B300 SM 数量)。