NVIDIAGPU 架构中的不变常量(宏观 → 微观)
第一层:整个 GPU 芯片
这一层几乎没有不变的常量。 GPU 芯片的 SM 总数、GPC 总数、L2 缓存大小,都随架构和型号剧烈变化。旗舰卡可能有 128 个 SM,入门卡可能只有 20 个,这是 GPU 厂商划分产品线的主要手段。
第二层:SM 内部(流多处理器)
进入 SM 这一层,开始出现硬性常量:
-
每个SM内部都是由4个warp scheduler?
- Fermi是2个, B200,和RTX 5090是8个
-
每个 SM 的寄存器总量:65536 个 × 32位 =64K
从 Kepler 到 Blackwell,这个数字从未变过。它直接决定了一个 SM 在给定寄存器用量下最多能塞多少线程。如果一个 Kernel 每个线程用了 128 个寄存器,那一个 SM 最多就只够容纳 65536 ÷ 128 = 512 个线程。
-
Volta架构后, L1 和 SMEM 合并为统一 SRAM(可动态调整比例),但最小值统一为 16 KB
这个数值是硬件设计时在功能性和灵活性之间权衡的结果:(但是两者的总量是逐渐增大的)
- 保留 16 KB L1 是为了保证 GPU 流水线的基本数据通路,比如处理栈操作、寄存器溢出、常数内存访问等。
- 保留 16 KB SMEM 是为了保证 CUDA 编程模型的基础功能可以运行,即使 Kernel 没有显式使用
__shared__变量,编译器也可能隐式依赖它来做 Block 内通信。
第三层:线程块(Block)
Block 是编程模型的核心,这里出现了最重要的硬性常量:
- 每个 Block 最多 1024 个线程
这个上限从 Kepler 时代确立,至今未变。blockDim.x * blockDim.y * blockDim.z的总乘积不得超过 1024,编译器会强制执行。 - 每个 Block 的维度限制 :
- x 维度:最多 1024
- y 维度:最多 1024
- z 维度:最多 64
第四层:Warp(线程束)
Warp 是 SM 内部的调度和执令单位,这一层也有硬性常量:
- 一个 Warp 固定 32 个线程
从 CUDA 诞生第一天至今,所有 NVIDIA GPU 的 Warp 大小都是 32。这不是硬件可配置项,而是 ISA(指令集架构)的一部分。Warp Shuffle 指令(__shfl_xor_sync)的 Butterfly 归约模式,其 5 轮迭代(log2(32) = 5)正是基于这个固定的 32。 - Warp Shuffle 的掩码必须是 2 的幂
这不是硬件限制,而是算法本身的数学要求。__shfl_xor_sync的 mask 参数必须是 2 的幂,从 1、2、4、8、16,正好对应 5 轮迭代。这个规律在任何架构上都不变。
第五层:单个线程
- 每个线程最多 255 个寄存器
这个上限从 Tesla 架构到 Blackwell 从未改变。根源在于 PTX 指令集里寄存器地址字段是 8 位,只能编址 0-255。如果 Kernel 变量太多,编译器会触发 Register Spilling,把溢出变量打入 Local Memory(实际在显存里),性能会急剧下降。
第六层:数据类型与向量化
-
最大向量化加载宽度:128 位(即
float4/uint4)所有 NVIDIA GPU 的单条加载/存储指令最多一次搬运 128 位。这就是为什么用
float4一次读 4 个 float,而不是float8。这个限制来自内存总线带宽和指令编码格式,是硬件物理限制,不随架构改变。 -
__shfl_xor_sync的活跃线程掩码:0xffffffff这表示一个 Warp 里所有 32 个线程都参与通信。32 个 1 正好对应 32 个线程,这个值在任何架构上都是固定的。写成代码就是
0xffffffff。 -
Bank Conflict 的 Bank 数量:32 个
GPU 共享内存被划分为 32 个 Bank,每个 Bank 的宽度是 4 字节。当多个线程同时访问同一个 Bank 的不同地址时,就会发生 Bank Conflict。这个 Bank 数量从 Kepler 起一直是 32,和 Warp 大小是 32 形成匹配设计。
-
Sector 的大小是 32 字节
32 字节是 GPU 显存系统从 DRAM 传输到 L2 缓存时的最小访问粒度,是硬件物理层的规定,所有 NVIDIA 架构(从 Fermi 到 Blackwell)都是 32 字节,从未改变。
💎 完整的不变常量清单
从宏观到微观,下面是一张完整的常量速查表:
| 类别 | 参数 | 常量值 | 覆盖范围 |
|---|---|---|---|
| Warp | Warp 大小 | 32 线程 | 全架构 |
| Shuffle 活跃掩码 | 0xffffffff |
全架构 | |
| Block | 最大线程数 | 1024 | 全架构 |
| x 维度上限 | 1024 | 全架构 | |
| y 维度上限 | 1024 | 全架构 | |
| z 维度上限 | 64 | 全架构 | |
| 线程 | 最多寄存器数 | 255 | 全架构 |
| SM 内部 | 寄存器文件总量 | 65536(64K) | Kepler ~ Blackwell |
| 共享内存 Bank 数 | 32 | Kepler ~ 全架构 | |
| L1 缓存最小值 | 16 KB | Volta ~ Blackwell | |
| 共享内存最小值 | 16 KB | Volta ~ Blackwell | |
| 内存体系 | 最大向量化访存宽度 | 128 位(float4) | 全架构 |
| Global Memory 最小事务粒度 | 32 字节 | 全架构 | |
| Sector 大小(DRAM → L2 最小传输单元) | 32 字节 | Fermi ~ Blackwell | |
| 调度器 | 每个 SM 的 Warp Scheduler 数 | 4(Fermi 除外) | Kepler ~ Hopper |