GPU 架构十年演化与 CUDA 编程模型的同步膨胀

如果只用一个数字概括过去十年 NVIDIA 数据中心 GPU 的演进,它是 2380× — 这是 P100 (2016) 到 Rubin R100 (2026) 的 AI 算力提升倍数。同期 CUDA Core 的 FP32 算力只涨了 10×。两个数差出两个数量级,几乎可以说:这十年 NVIDIA 做了一件事 — 把通用算力的预算挪去堆 Tensor Core,再把混合精度卷到 FP4

但这不是「换了一颗芯片」就完事的。Tensor Core 不是更快的 CUDA Core,它是完全不同拓扑的电路;为了喂饱它,SM 内部新增了 TMA、TMEM、cluster 共享 SMEM;为了让程序员能写出能驾驭它的代码,CUDA 编程模型在 Thread/Block/Grid 三层之间硬塞进了 Warp 和 Cluster 两层。所以同一个 torch.matmul(a, b) 在 V100、A100、H100、B200 上写法完全不变,但底下 cuBLAS 每一代都被 NVIDIA 重写一遍。这篇文章把硬件演化与编程模型膨胀放在一起讲,因为它们是同一件事的两条线索

概览 — 一张图压缩十年

七代旗舰横向对照 — Pascal · Volta · Turing · Ampere · Hopper · Blackwell · Rubin

七代数据中心 GPU 的横向对照,每一行都是 NVIDIA 战略决策的物理结果:

年份架构旗舰卡制程晶体管FP32 (CUDA Core)Tensor Core 主精度Tensor Core 最低精度HBMNVLink
2016PascalP10016 nm15 B10.6 TF— (无 TC)16 GB HBM2160 GB/s
2017VoltaV10012 nm21 B15.7 TF125 TF (FP16)125 TF32 GB HBM2300 GB/s
2018TuringT412 nm14 B8.1 TF65 TF (FP16)130 TOPS (INT8)16 GB GDDR6
2020AmpereA1007 nm54 B19.5 TF312 TF (FP16)624 TOPS (INT8)80 GB HBM2e600 GB/s
2022HopperH1004 nm80 B67 TF990 TF (FP16)1979 TF (FP8)80 GB HBM3900 GB/s
2024BlackwellB2004 nm × 2 die208 B80 TF2250 TF (FP16)9000 TF (FP4)192 GB HBM3e1.8 TB/s
2026RubinR1003 nm336 B~100 TF~8000 TF (FP16)50,000 TF (FP4)288 GB HBM43.6 TB/s

看最右两列,你会看到一个反向剪刀差:CUDA Core FP32 算力从 10.6 → 100 TFLOPS 涨了约 10×;Tensor Core 最低精度从 0 → 50,000 TFLOPS 涨了无穷倍。这两条曲线的剪刀差就是这篇文章的核心叙事

算力提升从哪里来 — 几何叠加 · 通用 10× · 专用 200×

把 2380× 拆开来看,绝大多数不是「通用算力变快」,而是「围绕矩阵乘的几条专项乘子相乘」。下面这张图把四个独立乘子摆在同一根对数轴上 — 长度越长,贡献越大:

P100 (2016) → R100 (2026) · AI 算力 2380×四个独立乘子几何叠加 · 长度 ∝ log₁₀(倍数)通用算力工艺 · 频率 · SM 数16 nm → 3 nm · 频率 · 多 die× 10CUDA Core 自然增长Tensor Core 专项电路拓扑标量 FMA → 二维 MAC 阵列× 28同 SM 内 TC vs CUDA Core (FP16)精度下移FP16 → FP8 → FP6 → FP4× 8每代位宽减半 · 同硅片 MAC 数 × 22:4 结构化稀疏Ampere 起 · 跳过零值× 2每代默认开启10×100×1000×log scale几何叠加:10×28×8×2≈ 4500× · 实际有重叠 → 约 2380×主要贡献者:Tensor Core 拓扑 + 精度下移占总增益 ~95%
2380× 的来源拆解 — 横轴对数刻度,bar 长度 ∝ log₁₀(倍数)。蓝色一项(× 10)是 CUDA Core 视角下的通用算力增长 — 工艺、频率、SM 数十年累积。橙·绿·红三项加起来约 448×,是把硅片预算挪到 Tensor Core 的回报 — 拓扑替换 · 精度下移 · 稀疏。CUDA Core 路径占比不到 5%。

下一步要回答的是 — Tensor Core 凭什么能涨这么快?它跟 CUDA Core 究竟差在哪?为什么是「卷它」而不是「卷 CUDA Core」?这要钻到 SM 内部去看。

SM 内部解剖 — 共享前端 · 五种并列电路

五种并列的执行单元 — 不是「核心 + 多种调度」

一个 SM(Streaming Multiprocessor,流式多处理器) 是 GPU 物理层面的「车间」;一颗 B200 有 148 个 SM。误区是把 SM 想成「一种核心 + 多种调度方式」 — 事实是 SM 内部有五种完全独立的执行单元,平级摆放,共享同一个前端控制 + 同一块寄存器与 SMEM

NVIDIA Blackwell SM 内部架构官方图
NVIDIA Blackwell Ultra SM 官方架构图(来源 · NVIDIA Developer Blog)— 顶部 Warp Scheduler + Dispatch + 寄存器堆是共享前端;中部 128 个 CUDA Core(蓝)、4 个第 5 代 Tensor Core(绿)、4 个 SFU 并列;紫色块是新增的 256 KB TMEM;底部 SMEM/L1 共 228 KB。五种执行单元平级摆放 — 不存在「Tensor Core 调度 CUDA Core」这种关系。

这张图里最容易被误读的就是 CUDA Core 与 Tensor Core 的并列关系。一个常见的错误模型是「Tensor Core 内部协调多个 CUDA Core 完成矩阵乘」 — 这是错的。Tensor Core 自己有独立的、专为矩阵乘设计的硅片电路;一颗 B200 SM 里 Tensor Core 占的硅片面积比 CUDA Core 还多。这个判断的反证非常直接:CUDA Core FP32 算力 80 TFLOPS,而 Tensor Core FP16 算力 2250 TFLOPS — 高 28×。如果 Tensor Core 真的是「调度 CUDA Core 实现」,这 28× 从哪儿来?

Warp scheduler 怎么分发指令 — 五条管线物理独立 · 共享前端

更准确的说法是 — warp scheduler 根据指令类型分发到不同管线:fma.f32 走 CUDA Core 管线、mma.sync 走 Tensor Core 管线、ex2.f32 走 SFU 管线、ld.global 走 LD/ST 管线、cuda::memcpy_async 走 TMA 管线。这五条管线物理上完全独立,只是共享前端的取指、解码、寄存器堆。这跟 CPU 里 AVX 单元、标量 ALU、AES 引擎并列的关系完全同构。

CUDA Core vs Tensor Core 的电路差异 — FMA 流水线 vs 脉动阵列

钻到电路层面,两者的差异完全不是「大小」的问题,是拓扑的问题。

标量 FMA 流水线 — CUDA Core 的电路

一个 CUDA Core 是个标量 FMA 单元:一个 24×24-bit 整数乘法器 + 一个 24-bit 加法器 + 流水线寄存器,大约 2-3 万晶体管。一周期吞吐 1 次 FMA(= 2 次浮点运算)。SM 里 128 个 CUDA Core 就是 128 个独立的 FMA 电路并排摆放,每个独立工作。

二维 PE 阵列 — Tensor Core 的电路

一个 Tensor Core 是个二维乘加器阵列,借鉴了 systolic array 的核心思想。数据按时序流入,每个 PE(Processing Element) 同时做一次乘加,结果传给邻居或累加在本地:

CUDA CORE · 标量 FMA · 流水线d = a × b + c~2 万晶体管每周期 1 次 FMA每线程独立发指令128 个独立单元 / SM总:80 TFLOPS FP32控制开销大 · 走 warp scheduler 动态调度TENSOR CORE · SYSTOLIC-LIKE PE 阵列A→a₀a₁a₂a₃B ↓b₀b₁b₂b₃PEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPE→ C[i][j]累加结果留在PE 本地寄存器4×4 阵列 · 16 个 PE 同时工作实际 Blackwell 单条 mma 形状达 128×256×16一条指令吞吐 ~50 万次 MAC硬连线控制 · 一条 mma.sync 激活整阵列几周期同 SM 算力比:CUDA Core 80 TFLOPS FP32vsTensor Core 2,250 TFLOPS FP16 · 9,000 TFLOPS FP4硅片面积比:CUDA Core ~30%vsTensor Core ~40%(B200 SM 估算 · 同代差 28-112×)
左:CUDA Core 是标量 FMA + 流水线,每条指令独立通过 warp scheduler 调度。右:Tensor Core 是二维 PE 阵列,蓝色 A 矩阵从左流入、绿色 B 矩阵从上流入,16 个 PE 同时做乘加,累加结果留在 PE 本地寄存器 — 不是同一种电路的两个规模,是完全不同的拓扑

为什么相差几百倍 — 三条物理原因

为什么这种拓扑能带来几百倍提升?三条物理原因:

NVIDIA 在专利和论文里故意不公开承认 Tensor Core 是 textbook 意义上的 systolic array(Google TPU 倒是大方承认),内部很可能掺杂了 adder tree 等变体。但这不影响理解 — 关键判断是 「铺一层硬连线的 MAC 阵列」,而不是「一种更快的 FMA」。

电路差异速查表 — 拓扑 · 控制 · 编程粒度

下面这张表帮你把电路差异钉死:

维度CUDA CoreTensor Core
电路拓扑标量 FMA + 流水线二维 MAC 阵列 + 硬连线数据通路
一次操作的 MAC 数1几千到几十万(随代际增长)
控制方式动态调度(warp scheduler 每条指令派发)硬连线(一条指令激活阵列几周期)
编程粒度每线程独立发指令32 线程组成的 warp 协作发射
适合工作标量 / 向量 / 控制流 / 激活函数矩阵乘 / 卷积
硅片面积比~30%~40%(B200 SM 估算)

SFU / TMA / TMEM — 围绕喂饱 Tensor Core 的辅助电路

Tensor Core 算力涨太快,反过来逼出了一连串配套电路。它们不增加 FLOPS,但能保证 Tensor Core「不饿肚子」 — 而饿肚子是 GPU 优化的第一大敌。

SFU — 超越函数硬连线

SFU(Special Function Unit) 处理超越函数 — sin / cos / exp / log / sqrt / rsqrt。电路上是一块小 ROM(预存几十到几千个采样点)加一个乘加器:用输入 x 的高位查表找到两个采样点,用低位做线性或二次插值,几个周期出结果。这比让 CUDA Core 跑泰勒展开多项式快几十倍。代价是精度 — __expf(x) 走 SFU 大概 8-9 位有效精度,expf(x) 走软件实现有完整 23 位。SFU 数量少(每 SM 4 个 vs CUDA Core 128 个,比例 1:32)的原因是它是流水线化的:每周期能接收新指令,4 个 SFU 正好支持一个 warp 不阻塞地执行超越函数。

TMA — 张量异步搬运的专用单元

TMA(Tensor Memory Accelerator) 是 Hopper 引入的「张量搬运专用单元」。它解决的问题是 — 用 LD/ST 搬大张量太浪费:让一个 warp 的 32 个线程各自算地址、循环、加载,指令开销巨大。TMA 把这事抽象成「张量描述符 + 一条指令」:你预先构造一个 tensor map 描述要搬的张量(多维 shape、stride、起始地址),然后一个线程发一条指令,TMA 硬件自己生成地址序列、批量发起内存请求、写入 SMEM,完成后通过 async barrier 通知。这是个带状态机的小处理器,内部含 AGU(Address Generation Unit)、request scheduler、layout transformer。最关键的是 — TMA 是异步的,发指令的线程立刻返回去算别的,数据到位时再同步。这就解锁了 warp specialization 模式 — producer warp 一直发 TMA,consumer warp 一直算 Tensor Core,两者完全重叠。

TMA 异步张量搬运 vs LDGSTS 指令对照
NVIDIA 官方对照图(来源)— 左:Ampere A100 时代用 LDGSTS 指令搬张量,需要 warp 内每个线程算地址、发 load。右:Hopper H100 起一个线程发一条 TMA 指令,整块张量异步搬到 SMEM,其余线程同时去算 Tensor Core。这正是 warp specialization 的物理基础。

TMEM — Tensor Core 专用累加内存 · Blackwell 起

TMEM(Tensor Memory) 是 Blackwell 才出现的 — 256 KB 的 Tensor Core 专用 SRAM,绑在 SM 内部。它解决的是更深一层的瓶颈 — 当 Tensor Core 算力涨到几千 PFLOPS 时,连寄存器堆都喂不饱。Hopper 之前 mma 的操作数和累加器都在 warp 32 个线程的寄存器里,寄存器堆的端口带宽成了瓶颈。Blackwell 引入 TMEM,操作数和累加器直接放在专用 SRAM 里,新指令 tcgen05.mma 操作数明确指向 TMEM 而非寄存器,彻底绕过寄存器端口。这就是为什么 Blackwell 在 FP64 GEMM 上能跑到理论峰值的 80.7%(H200 同样规模只到 55.6%)。

单元作用电路本质引入代际
SFU超越函数ROM + 插值乘加器Volta 之前就有
TMA张量异步搬运AGU + 状态机 + layout 转换Hopper
TMEMTensor Core 专用累加内存独立 SRAM + 专用读写端口Blackwell

这三件事合起来,讲了同一个故事 — Tensor Core 越强,围绕它的辅助电路就越多越专用。这是「专用化阶梯」越往上爬越窄的物理体现。

内存层次 — 显式管理是 GPU 的本质特色

显式 vs 隐式的边界 — CPU 让你忘 · GPU 让你直面

GPU 的存储层次远比 CPU 复杂,核心差异不在「层数」,而在 「显式」与「隐式」的边界。CPU 让你忘记缓存的存在 — 写 int x = arr[i],硬件自动从 cache 取数据。GPU 强迫你直面 — 写 __shared__ float tile[256] 声明,然后必须显式 tile[tid] = gmem[idx] 把数据搬进去,再 __syncthreads() 等待。

层 · TIER存储管理方式容量带宽L1 · 最快L2L3L4L5L6 · 互连外部 · 最慢寄存器(Register)每线程私有 · 编译器自动分配编译器分配变量声明 · 隐式访问256 KB/ SM · 片内≈ ∞SMEM__shared__ 显式声明程序员手动搬L1 Cache硬件缓存 GMEM 访问硬件自动228 KB/ SM · 共享 SRAM运行时可配比例40 TB/sTMEMTensor Core 专用 · Blackwell 起程序员显式tcgen05.alloc / dealloc256 KB/ SM100 TB/sL2 Cache全 GPU 共享 · 跨 SM硬件自动程序员可 hint 不可控192 MBB20020 TB/sGMEM(HBM3e)主显存 · 所有 SM 共享混合cudaMalloc 显式 · 访问隐式192 GBHBM3e · B2008 TB/sPeer GPU HBM经 NVLink 5 · 跨卡 peer-to-peerNCCL / NVSHMEM集合通信或单边 RDMAN × 192 GB机柜内1.8 TB/sCPU 主内存通过 PCIe 5 或 NVLink-C2C 接入cudaMemcpyCPU↔GPU 拷贝 · 程序员发起TB 级主机内存64 / 900 GB/sPCIe / C2C程序员显式管理硬件自动管理混合(分配/访问语义不同)GPU 之外 · 经互连访问
GPU 七层内存层次 — 从上到下越来越慢、越来越大。橙色边框 = 程序员显式管理(SMEM、TMEM:必须 declare + 手动搬数据);蓝色边框 = 硬件自动管理(Register、L1、L2:写代码访问即可);绿色边框 = 混合(GMEM、Peer GPU HBM:分配显式、访问隐式)。虚线层是 GPU 之外、需要跨互连访问。

为什么显式管理是必须的 — 一个 SM 跑 2048 个线程

显式管理为什么对 GPU 是必须的?因为 GPU 一个 SM 同时跑 64 个 warp × 32 线程 = 2048 个线程,根本没法给每个线程配 cache + 预取器。CPU 一个核心服务一个线程,给它配几兆 cache 完全 OK;GPU 每线程能分到的硬件资源少得多,只能让线程之间显式组织数据共享 — 这就是 SMEM 必须存在的根本原因。

管理方式速查表 — 分配 · 搬运 · 访问 · 释放

存储分配数据搬运访问释放
寄存器编译器自动隐式自动
SMEM程序员声明程序员手动搬隐式自动(block 结束)
TMEM程序员显式 alloc程序员搬通过 tcgen05 指令程序员 dealloc
Constant程序员声明程序员一次性灌入隐式自动
L1 / L2硬件自动隐式
GMEMcudaMalloccudaMemcpy隐式cudaFree
其他 GPU HBMNCCL 分配NCCL/NVSHMEM通过 APINCCL 释放

整个 GPU 性能优化的本质,就是 — 让数据尽量留在层次的上半部分(寄存器/SMEM/TMEM/L2),少回 HBM。kernel fusion、FlashAttention、CUTLASS、warp specialization,所有这些技术的核心都是这一件事。

精度演化 — FP4 不是省钱 · 是把芯片当 4 颗用

为什么要下移精度 — 同硅片塞更多 MAC

混合精度是这十年算力提升的第二条主线 — 与 Tensor Core 拓扑并列。每一代都引入一种更低的精度,理由不是「省钱」,是 把同样硅片当多颗用

NVIDIA Hopper 新增 FP8 精度的 E4M3 / E5M2 格式
NVIDIA 官方图(来源)— Hopper 引入两种 FP8 格式:E4M3(4 位指数 + 3 位尾数,精度优先,用于前向)与 E5M2(5 位指数 + 2 位尾数,范围优先,用于反向)。Blackwell 在此基础上再加 FP6 与 FP4。

物理基础 — 乘法器面积 ∝ 位宽²

物理上的根本原因:乘法器的面积大致正比于位宽的平方

同样的硅片面积,FP4 乘法器能塞下的数量是 FP32 的 100 倍以上。换种说法 — FP4 不是「便宜的 FP16」,而是「同样硅片塞 4 倍 MAC」

下面是 B200 上各精度的 Tensor Core 算力对照:

精度输入位宽累加B200 算力相对 FP32 倍数
FP32 (CUDA Core)32-bit32-bit80 TFLOPS
TF32 (Tensor Core)19-bit 实效32-bit~1,100 TFLOPS~14×
FP16 / BF16 (Tensor Core)16-bit32-bit2,250 TFLOPS28×
FP8 (E4M3 / E5M2)8-bit32-bit4,500 TFLOPS56×
FP6 (E3M2 / E2M3)6-bit32-bit~6,750 TFLOPS84×
FP4 (E2M1)4-bitFP32 或 FP169,000 TFLOPS112×
FP4 + 2:4 稀疏4-bitFP32 或 FP1618,000 TFLOPS225×
FP64 (Tensor Core)64-bit64-bit40 TFLOPS0.5×

注意 — Tensor Core 并不只跑低精度。它也支持 FP32(走 TF32 模式)、FP64(HPC 用)。但低精度算力远远高于高精度,这是性能/精度的主动权衡,不是能力限制。

代际新增的精度 — 每代下移一级

每一代新增的精度,对应的硬件代际:

代际年份新增精度主要驱动场景
Volta2017FP16 (Tensor Core 首次)训练
Turing2018INT8 / INT4推理量化
Ampere2020TF32 / BF16 / 2:4 稀疏训练数值稳定 + 自动加速
Hopper2022FP8 (E4M3 + E5M2)LLM 训练 + 推理
Blackwell2024FP6 + FP4 + microscalingLLM 推理极致吞吐
Rubin2026优化 FP4 + 更多 microscalingAgent / reasoning 推理

每代新增一种精度 — 但能不能用起来是另一回事。FP8 从 H100 发布(2022)到生产可用(2024)用了两年,主要靠 NVIDIA 的 Transformer Engine 库做自动 scaling factor 管理。FP4 也类似 — 硬件支持容易,数值稳定是软件的工作。

Transformer Engine 概念示意
Transformer Engine 概念图(NVIDIA 来源)— 每层运行时统计激活数值范围,动态选择 FP8 / BF16 / FP16,把缩放因子(scaling factor)自动管理。让程序员写 BF16 训练代码,底层悄悄走 FP8 Tensor Core,精度损失可控。

TF32 与 Transformer Engine — 不改代码而悄悄加速

TF32 是个特别值得品味的设计。它对程序员的接口是 FP32(8 位指数 + 24 位尾数,与 IEEE FP32 相同),但内部把尾数截到 10 位(与 FP16 相同)、保留 8 位指数。于是同样一段 cublasSgemm 调用 — 用户什么都不改,FP32 矩阵乘自动走 Tensor Core,速度比真 FP32 快 ~14 倍,精度损失对深度学习几乎无感。这是 NVIDIA 让 Tensor Core 「悄悄接管所有 FP32 矩阵乘」的精妙之处。

代际深度变迁 — Pascal · Volta · Turing · Ampere · Hopper · Blackwell · Rubin

完整 H100 GPU 框图 · 144 SM
完整 H100 GPU 框图(NVIDIA 来源)— 8 个 GPC × 9 TPC × 2 SM = 144 SM,周围是 60 MB L2 cache + 6 颗 HBM3。每个 GPC 就是 Thread Block Cluster 的物理边界,cluster 内 block 共享 SMEM。

把这十年逐代拆开看,每一代都恰好对应一个 AI 工作负载的时代转折:

Pascal · Volta · Turing — 2016-2018 · Tensor Core 时代开启

Pascal (2016, P100) — 数据中心 GPU 元年。第一次抛弃 GDDR 用 HBM2(720 GB/s),第一次引入 NVLink(160 GB/s,~PCIe 5 倍),第一次原生 FP16(走 CUDA Core,2× FP32 吞吐)。还没有 Tensor Core。这一代证明了「GPU 进数据中心训深度学习」这件事的商业可行。GPT-2 / BERT 时代的训练几乎都在 P100 上跑过。

Volta (2017, V100) — Tensor Core 时代开启。第一代 Tensor Core 每 SM 8 个,做 4×4×4 FP16 矩阵乘,带来 12× 训练加速。这是 GPU 设计哲学的根本转变 — 从「通用并行计算芯片」变成「专为矩阵乘加速的 AI 芯片」。从这一代开始,每代的算力提升主要来自 Tensor Core,而非 CUDA Core。GPT-3 最初就是在 V100 集群上训出来的。

Turing (2018, T4 + RTX 20) — 推理市场分化。T4 是低功耗(70W),引入 INT8 Tensor Core,主打推理服务;同代消费 RTX 20 系列引入 RT Core(光追硬件)。证明了「训练用 V100、推理用 T4」的差异化策略可行。

Ampere · Hopper — 2020-2022 · LLM 训练工业化

Ampere (2020, A100) — LLM 训练工业化。第三代 Tensor Core 引入 TF32(让大量 FP32 代码自动加速,几乎不改代码)、BF16(数值范围更大,训练更稳)、2:4 结构化稀疏(再翻倍吞吐)。新增 MIG(一颗 A100 切 7 个小 GPU)、第二代 NVLink(600 GB/s)、HBM2e。A100 是 NVIDIA 最长青的卡 — 直到 2026 年仍在大量数据中心服役。

Hopper (2022, H100) — Transformer 专用化。第四代 Tensor Core + Transformer Engine 软件层 = 首次原生 FP8 + 自动量化。引入 TMA 解决「Tensor Core 太快、寄存器搬不过来」、引入 Thread Block Cluster 让多个 SM 协同(8 个 block 一个 cluster,共享分布式 SMEM)。NVLink 3 (900 GB/s) + HBM3 (3 TB/s)。H100 在 Transformer 训练上比 A100 快 6-9×。Grace-Hopper Superchip (GH200) 第一次让 CPU 和 GPU 通过 NVLink-C2C 紧耦合。

Blackwell · Rubin — 2024-2026 · 多 die + FP4 + 平台

Blackwell (2024, B200) — 双 die + FP4 时代。第一次双 die 设计 — 两个 reticle-limit die 通过 10 TB/s 内部互联,对软件呈现为单一 GPU,共 208 B 晶体管。第五代 Tensor Core 原生 FP4 / FP6,配合第二代 Transformer Engine 的 micro-tensor scaling。引入 TMEM(256 KB Tensor Core 专用 SRAM)、2-CTA Cluster(两个 SM 共喂一个 Tensor Core 的 UMMA)、解压缩引擎(LZ4/Snappy/Deflate,服务数据分析)。NVLink 5 (1.8 TB/s) + HBM3e (8 TB/s, 192 GB)。GB200 NVL72 把 72 颗 B200 + 36 颗 Grace CPU 整合到一个机柜。

Rubin (2026, R100) — 平台时代。336 B 晶体管,真正的多 die 设计(两个计算 die + 两个 I/O die)。HBM4 (288 GB, 22 TB/s 带宽,~2.8× B200)。224 SM/GPU,FP4 算力 50 PFLOPS(稀疏)。NVLink 6 (3.6 TB/s/GPU)。最关键的变化是哲学层面 — NVIDIA 不再卖 GPU,卖整个机柜级 AI 计算平台,Vera Rubin 平台围绕「七芯片协同」组织(R100 GPU + Vera CPU + NVLink 6 Switch + ConnectX-9 + BlueField-4 + Spectrum-6 + 整合的 Groq 3 LPU)。

十年主线归纳 — 精度 · 阵列 · 存储 · 互联 · 商业形态

把十年放在同一张表里,主线非常清晰:

主线体现
精度下移FP16 → INT8 → BF16 → FP8 → FP4,每代加一种
Tensor Core 阵列规模4×4×4 → 16×16×16 → 64×8×16 → 128×256×16
片上存储显式化SMEM 扩大 → cp.async → TMA → Cluster → 分布式 SMEM → TMEM
互联指数增长NVLink 160 GB/s → 3600 GB/s · HBM 720 GB/s → 22 TB/s
商业形态卖 GPU → 卖 DGX → 卖机柜 → 卖 AI 工厂

CUDA Core 在这张表里几乎缺席 — 它的 FP32 算力从 10.6 → 100 TFLOPS,十年只涨 10×。通用算力让位给专用算力,是这十年最直接的判断。

编程模型同步膨胀 — Thread → Warp → Block → Cluster → Grid

从三层到五层 — Warp 与 Cluster 被塞进中间

硬件复杂度涨上去,程序员看到的编程模型也跟着膨胀。最经典的 CUDA 编程模型是三层 — Thread / Block / Grid:每个线程独立、Block 内线程共享 SMEM、Grid 是所有 Block。但 Tensor Core 时代之后,中间硬塞进 WarpCluster 两层,变成五层:

NVIDIA Thread Block Clusters 官方示意图
NVIDIA 官方 Thread Block Cluster 示意图(来源 · NVIDIA Hopper Architecture In-Depth)— 左侧是经典三层(Thread / Block / Grid),右侧是 Hopper 起新增的四层 — 中间插入 Thread Block Cluster。一个 cluster 内的所有 block 保证被调度到同一个 GPC(GPU Processing Cluster)上,彼此可通过 distributed SMEM 直接访问对方共享内存。可移植的 cluster 最大 8 个 block,Hopper 通过 opt-in 可放宽到 16 个。
软件编程模型硬件物理对应Thread私有寄存器 · 独立 PC一个执行 laneCUDA Core / Tensor Core 内一槽Warp · 32 线程SIMT · 硬件调度单位Warp Scheduler 一周期一条mma.sync 是 warp 级指令Block(CTA)共享 SMEM · __syncthreads一个 SM 整块跑不会跨 SM 拆分Cluster · 8-16 Block(Hopper+)distributed SMEM · async barrier一个 GPCSM 间高带宽互访Grid一次 kernel launch 全部 block整张 GPU148 SM + L2 + HBM橙框 = Tensor Core 时代显式暴露的层次 · Warp 一直存在 · Cluster 是 Hopper 起新增
CUDA 五层编程模型与硬件对应 — 左列软件抽象,右列物理实体。橙框两层(Warp / Cluster)是 Tensor Core 时代被显式暴露给程序员的。

为什么 Warp 必须显式化 — mma.sync 物理上是 warp 级指令

为什么 Tensor Core 时代非要把 Warp 显式化?因为 mma.sync 这条指令物理上就是 warp 级的 — 32 个线程必须协作发射,矩阵 A、B 的元素按特定布局分散在这 32 个线程的寄存器里,Tensor Core 硬件把所有线程的寄存器内容收集起来喂给阵列。一个 16×16×16 矩阵乘需要 512 个 FP16 输入 = 1024 字节,单个线程的寄存器装不下 — 必须分摊到 32 个线程。所以程序员必须从「我这个线程算什么」升级到「我们这个 warp 一起算什么」

Cluster 的引入逻辑 — 多个 SM 协同喂一个 mma

Cluster 的引入逻辑类似 — Hopper 起 Tensor Core 算力涨到需要多个 SM 一起喂数据,所以引入 cluster 让 block 在 GPC 内有共享 SMEM(distributed SMEM)、共享 TMA。Blackwell 的 2-CTA cluster 进一步把两个 SM 绑成一组共喂一个 UMMA Tensor Core 指令。

代码对照 — naive matmul → wmma → wgmma+TMA → tcgen05+TMEM

最直观的体感是看同一个任务(矩阵乘)的代码怎么随着代际膨胀。下面四段代码依次展示了 Pascal → Volta-Ampere → Hopper → Blackwell 时代写 matmul 的典型样貌。

Pascal · 朴素 thread 级 — 每线程算一个元素

__global__ void matmul_naive(float* A, float* B, float* C, int N) {
    int row = blockIdx.y * blockDim.y + threadIdx.y;
    int col = blockIdx.x * blockDim.x + threadIdx.x;
    if (row >= N || col >= N) return;

    float sum = 0;
    for (int k = 0; k < N; k++) {
        sum += A[row * N + k] * B[k * N + col];
    }
    C[row * N + col] = sum;
}

思考粒度:单个线程。每个线程算 C 里的一个元素,循环 N 次内积。代码可读性极高 — 但性能只有理论峰值的 5-10%(因为完全没用 Tensor Core,数据也直接从 GMEM 读)。

Volta–Ampere · wmma fragment — Warp 协作 · Tensor Core 首次

#include <mma.h>
using namespace nvcuda::wmma;

__global__ void matmul_wmma(half* A, half* B, float* C, int N) {
    __shared__ half tile_A[16][16];
    __shared__ half tile_B[16][16];

    // fragment 分布在整个 warp 32 个线程的寄存器里
    fragment<matrix_a, 16, 16, 16, half, row_major> a_frag;
    fragment<matrix_b, 16, 16, 16, half, col_major> b_frag;
    fragment<accumulator, 16, 16, 16, float> c_frag;
    fill_fragment(c_frag, 0.0f);

    for (int k = 0; k < N; k += 16) {
        // 异步加载到 SMEM(Ampere 起的 cp.async)
        // ... 省略加载逻辑 ...
        __syncthreads();

        load_matrix_sync(a_frag, &tile_A[0][0], 16);   // warp 协作
        load_matrix_sync(b_frag, &tile_B[0][0], 16);

        mma_sync(c_frag, a_frag, b_frag, c_frag);      // 一条指令 = 16×16×16 矩阵乘
        __syncthreads();
    }

    store_matrix_sync(&C[...], c_frag, N, mem_row_major);
}

思考粒度升级到整个 warp。注意几个关键变化 — 所有 wmma API 带 _sync 后缀,意味着「整个 warp 必须一起调用、必须同步执行」;代码里完全没有 threadIdx — fragment 把线程级的复杂度隐藏起来;混合精度首次出现(输入 half,累加 float)。性能能跑到峰值 60-80%。

Hopper · TMA + warp specialization — producer / consumer 流水重叠

// 极度简化版 — 真实 CUTLASS 代码长几倍
__global__ void matmul_hopper(...) {
    __shared__ AsyncBarrier bar;
    extern __shared__ half smem_buffer[];

    int warpId = threadIdx.x / 32;

    if (warpId == 0) {
        // Producer warp — 只发 TMA 指令搬数据,不算
        for (int k = 0; k < N; k += TILE_K) {
            cuda::memcpy_async(smem_A, gmem_A_tile, tma_desc_A, bar);
            cuda::memcpy_async(smem_B, gmem_B_tile, tma_desc_B, bar);
            bar.arrive();
        }
    } else {
        // Consumer warps — 只算 Tensor Core,不搬
        for (int k = 0; k < N; k += TILE_K) {
            bar.wait();                                   // 等数据到位
            wgmma::mma_async(c_frag, smem_A, smem_B);     // 异步 mma!
            wgmma::commit_group();
            wgmma::wait_group<0>();
        }
    }
}

思考粒度再升级 — warp specialization。不同 warp 干完全不同的活 — 有的专门搬数据(producer),有的专门算 Tensor Core(consumer),两条流水通过 async barrier 同步。wgmma(warpgroup MMA)替代 wmma,操作数可以直接来自 SMEM 而不必先加载到寄存器。async barrier 不数线程,数字节数 — 「我等 16 KB 数据到位」。性能能跑到峰值 85-95%,但这种代码已经基本只有 CUTLASS / FlashAttention 团队能直接写。

Blackwell · tcgen05 + TMEM — 2-CTA cluster · 操作数绕过寄存器

__global__ void matmul_blackwell(...) {
    // TMEM 显式分配
    auto tmem_c = tcgen05::alloc<float, 128>();
    __shared__ AsyncBarrier bar;

    if (in_producer_warp) {
        // TMA multicast — 一次加载,2-CTA cluster 内的两个 SM 都收到
        cuda::memcpy_async_tma_multicast(smem_A, gmem_A, cluster);
        cuda::memcpy_async_tma_multicast(smem_B, gmem_B, cluster);
    } else {
        // 操作数来自 SMEM,结果写入 TMEM(不抢寄存器)
        tcgen05::mma(tmem_c, smem_A, smem_B);
        tcgen05::commit();
    }

    // 从 TMEM 取出结果
    tcgen05::load(c_reg, tmem_c);
    tcgen05::dealloc(tmem_c);
}

又多一层手动管理 — TMEM 显式 alloc / dealloctcgen05.mma 指令的操作数来自 SMEM、累加器在 TMEM,彻底绕过寄存器堆。2-CTA cluster 让两个相邻 SM 通过 distributed SMEM + TMA multicast 共喂一个 mma。一次激活整个 cluster 的工作量非常大。

代际复杂度对照 — 每代代码量翻 2-3 倍

把这四段代码摆在一起,演化趋势一目了然:

代际思考粒度新增的「程序员要操心的事」代码量级
Pascal 之前Threadthread / block / grid 三件套~20 行
Ampere+ Warpfragment 布局 / _sync 语义 / cp.async~100 行
Hopper+ ClusterTMA descriptor / warp specialization / async barrier~300 行
Blackwell(Cluster 升级)TMEM alloc/dealloc / tcgen05 / 2-CTA / multicast~500 行

每代复杂度大致翻 2-3 倍。但这只是直接写裸 CUDA 的视角 — 真实世界里 90% 的人不写这种代码。

抽象层吸收复杂度 — torch.matmul 不变 · 底下 cuBLAS 每代重写

五层用户的代码量级 — 从 1 行到 1000 行汇编

这才是 NVIDIA 设计哲学的精髓 — 硬件复杂度暴涨,被层层抽象吸收,普通用户体验保持稳定甚至变简单

同样的矩阵乘任务,不同人群实际写的代码量级:

用户群体调用方式代码量级性能需要懂什么
普通 AI 工程师torch.matmul(a, b)1 行接近峰值几乎什么都不用懂
自定义算子工程师Triton @triton.jit + tl.dot~50 行 Python80-95% 峰值tile 划分 / SMEM 概念
高性能库开发者CUTLASS 模板~100 行 C++接近峰值Tensor Core / CuTe layout
裸 CUDA 工程师直接 mma.sync~300 行 C++取决于功力warp / SMEM bank / mma 指令
极致优化者内联 PTX~1000 行汇编理论极限寄存器分配 / 指令调度 / 依赖追踪

越往下,控制力越强,但工作量爆炸。FlashAttention 作者 Tri Dao 写的就是裸 CUDA + 内联 PTX 那一层,所以一个人能比 cuBLAS 团队的某些 kernel 还快。但绝大多数 AI 工程师只在最顶上那一层。

为什么手写不一定比 cuBLAS 快 — NVIDIA 的护城河不止硬件

一个有趣的反转 — 90% 的情况下,PyTorch + cuBLAS 比一个普通工程师手写的 CUDA 快得多。原因有三个:

所以 NVIDIA 的护城河不只是硬件,更是这一整套从顶到底的软件栈。这也是为什么 AMD GPU 性能数字上能追平甚至超过 NVIDIA,但生态上还差一大截 — 硬件可以追,这十几年积累的库和编译器追不上

软件栈与开源版图 — 开源的外壳 · 闭源的核心

CUDA 软件栈分层 — L7 框架 → L1 硬件 · 七层切片

把这十几年沉淀的 CUDA 库生态画出来,你会看到一个反直觉的事实 — 最核心、用得最多的几个库恰恰是闭源的,开源的都是上层、外围、面向定制化的部分。

L7 · 用户应用PyTorch · JAX · TensorFlow✅ 完全开源L6 · 训练 / 推理高层Megatron · NeMo大模型训练✅ Apache 2.0Transformer EngineFP8/FP4 训练✅ Apache 2.0TensorRT-LLM推理⚠️ 前端开源 / 核心闭源vLLM · SGLang推理服务✅ Apache 2.0L5 · 自定义算子 / DSLCUTLASS · CuTeGEMM 模板库✅ BSD-3-ClauseTriton (OpenAI)Python DSL✅ MITCUB / Thrust并行原语✅ Apache 2.0NCCL · NVSHMEM通信✅ BSD-3L4 · 基础数学库 · 核心闭源cuBLAS · cuBLASLt线性代数❌ NVIDIA ProprietarycuDNNDL 算子❌ Proprietary(前端 ✅)cuFFT / cuSPARSEFFT / 稀疏❌ ProprietaryTensorRT推理引擎⚠️ OSS 部分开源L3 · CUDA Runtime / Driver · 闭源CUDA Runtime · Driver · PTX 编译器❌ NVIDIA Proprietary · 只有 header 和 .soL2-L1 · 硬件GPU 硬件 · CUDA Core / Tensor Core / TMA / NVLinkSASS 机器码 · 不公开 · PTX 编译为 SASS 是 NVCC 内部
CUDA 软件栈与开源状态 — 红框是 NVIDIA 闭源(cuBLAS / cuDNN / cuFFT / CUDA Runtime),绿框是完全开源(CUTLASS / Triton / NCCL / Transformer Engine / Megatron / vLLM),橙框是部分开源(TensorRT 系)。最关键的几个库 — 恰恰是闭源的。

开源 / 闭源边界 — 最常用的几个库恰恰是闭源

很多人误以为 cuBLAS、cuDNN 是开源的 — 实际上它们是 NVIDIA 最严密保护的产品。pip install nvidia-cublas-cu12 装的不是源码,是预编译好的 .so 二进制文件,license 字段明确写 LicenseRef-NVIDIA-Proprietary

开源状态License你能看到什么
CUDA Runtime / Driver❌ 闭源NVIDIA Proprietary只有 header 和 .so
cuBLAS / cuBLASLt❌ 闭源NVIDIA Proprietary只有 header 和 .so
cuDNN(核心)❌ 闭源NVIDIA Proprietary只有 header 和 .so
cuDNN Frontend(C++ wrapper)✅ 开源MITwrapper,调用闭源 cuDNN
cuFFT / cuSPARSE / cuSOLVER❌ 闭源NVIDIA Proprietary只有 header 和 .so
CUTLASS✅ 完全开源BSD-3-Clause全部 C++ 模板源码
Triton(OpenAI)✅ 完全开源MIT全部源码
NCCL✅ 完全开源BSD-3全部源码
NVSHMEM(2024 后)✅ 开源BSD-3全部源码
Transformer Engine✅ 完全开源Apache 2.0全部源码
TensorRT⚠️ 部分开源Apache 2.0(plugins)仅 plugins、parsers,核心闭源
TensorRT-LLM⚠️ 部分开源Apache 2.0(前端)前端 Python,依赖闭源 TensorRT
RAPIDS(cuDF / cuML)✅ 完全开源Apache 2.0全部源码
Megatron-Core / NeMo✅ 完全开源Apache 2.0全部源码

真正的护城河 — 不是单库 · 是十几年的生态

NVIDIA 用「开源的外壳 + 闭源的核心」这种产品策略:让用户能扩展(写自定义 plugin、改 CUTLASS 模板、定制 NCCL 通信),但不能复制核心实现。AMD ROCm 哪怕把对应库全部开源(rocBLAS / MIOpen 都是开源的),性能上仍然落后 cuBLAS / cuDNN 2-3 年 — 因为 cuBLAS / cuDNN 的优化技巧(用 Tensor Core 的最新指令、调度 warp、用 TMA)藏在二进制里,AMD 没法「抄」,只能逆向工程或重新发明。

这就是 NVIDIA 真正的护城河 — 不只是某一个库,是几十个库十几年积累的整体生态

总结 — 卷 Tensor Core · 卷精度 · 卷抽象层

三条主线 — Tensor Core · 精度 · 抽象层

把十年浓缩成一句话:NVIDIA 这十年只做了三件事 — 卷 Tensor Core、卷混合精度、卷抽象层吸收复杂度

具体说:

为什么是 Tensor Core — 物理 · 架构 · 商业三层原因

如果再追问「为什么是 Tensor Core 而不是 CUDA Core」 — 答案在三层:

未来 5 年的展望 — FP2 · 更大 Cluster · 平台化

未来 5 年这条线还会继续走 — Rubin Ultra (2027) / Feynman (2028) 已经在路线图上,FP2 / INT2 可能再下一代出现,Cluster 可能从 8-16 block 扩到几十,TMEM 可能进一步分化出更多专用存储。但对你而言,这条主线一旦抓住,以后看任何 NVIDIA 新闻、新架构、新产品 — 都能立刻判断它的本质是什么:它无非是在「卷 Tensor Core / 卷精度 / 卷抽象层」这三条线上的某一处再加一刀。

参考资料 — 白皮书 · 论文 · 文档

白皮书与官方文档

论文与工程博客

教科书与课程