跳到主要内容

L1.1 单卡异构芯片微架构深挖

三维坐标 layer: L1(计算编排)level: Seniorpillar: 硬件架构

本文是 L1 计算层的开篇。目标是把一块加速芯片拆到能跑指令的最小执行单元——理解 GPU 的 SM 如何用 warp 调度掩盖延迟、Tensor Core 如何把低精度变成吞吐倍数、昇腾如何用三类异构单元做指令级异步流水。读完你应当能回答:「为什么同一段 matmul,换个 dtype 吞吐能翻一倍」。

学习目标

  • 前置知识:读过 L0 全层(尤其 L0.2 三大物理墙:知道算力墙/显存墙、Roofline 拐点);写过基础 Python;知道「GPU 比 CPU 适合并行」即可。无需 CUDA 编程经验。
  • 学完产出:① 能画出一个 SM 的内部结构(Warp Scheduler / CUDA Core / Tensor Core / 寄存器堆 / Shared Memory),并说清各自职责与约束;② 能用「延迟掩盖 + 高 occupancy」一句话讲清 GPU 为什么靠 warp 调度而非降低单指令延迟取胜,并解释寄存器用太多反而变慢的反直觉现象;③ 能说清 Tensor Core「精度换吞吐」的硬件根因,区分 FP8 的 E4M3/E5M2 用途;④ 能对比 GPU 的「隐式 SIMT 延迟掩盖」与昇腾 DSA 的「显式流水编排」两种延迟工程哲学,理解它如何决定异构移植成本;⑤ 亲手跑一个 micro-benchmark,量化同一个 GEMM 在 CUDA Core 与 Tensor Core 上的吞吐倍数。
  • 阅读姿势:盯住一条主线——「AI 芯片的所有微架构设计,都是为了让算术单元永远有活干」。无论是 GPU 的海量 warp,还是昇腾的三单元异步流水,本质都在解决同一个问题:用并行/流水掩盖「数据搬运比计算慢得多」这堵物理墙。

背景与现状

异构芯片微架构(Heterogeneous Chip Microarchitecture) 的核心命题只有一个:用最小的硅面积和功耗,喂饱尽可能多的乘加运算(MAC)。CPU 把晶体管堆在分支预测、乱序执行、巨大缓存上以优化「单线程延迟」;而 AI 加速芯片走的是相反路线——把晶体管砸在海量算术单元 + 高带宽片上存储上,以「吞吐」为唯一信仰,用大规模并行去掩盖单条指令的延迟。

从产业视角看,单卡微架构的演进可以概括为三个台阶:

  • 通用并行时代(~2016 前):以 CUDA Core 为主力,标量/向量 FMA(Fused Multiply-Add)逐元素算。GEMM(通用矩阵乘)受限于寄存器与访存,算力利用率长期在 30%~50%。
  • 张量加速时代(2017 起):NVIDIA Volta 引入 Tensor Core,把「4×4 矩阵块乘加」做成单条硬件指令(MMA / WGMMA),低精度 GEMM 吞吐相比 CUDA Core 提升一个数量级。这是大模型训练能「跑得起」的硬件前提。
  • 专用数据流时代(2019 起):华为昇腾以 达芬奇(Da Vinci)架构 为代表的 DSA(Domain-Specific Architecture,领域专用架构),把矩阵、向量、标量做成物理隔离的三类单元,靠指令级异步流水榨干每一个时钟周期。Google TPU 的脉动阵列(systolic array)是同一思想的另一条路径。
  • 极低精度 + 机柜即芯片时代(2025–2026):FP4 进入硬件主流——NVIDIA Blackwell(NVFP4)、Blackwell Ultra(GB300,2025 H2 量产)与 AMD MI350/MI355X(CDNA4,原生 FP4/FP6)把推理低精度做成标配;同时「单卡」的边界被进一步打破,机柜级 scale-up 域(GB300 NVL72、华为 CloudMatrix CM384、AMD Helios)成为新的「逻辑单芯片」。NVIDIA Rubin(VR200,HBM4 + NVLink 6 + Vera CPU) 已在 GTC 2025 公布路线,规划 2026 H2 量产。

业界信号(截至 2026 年中):H100 单卡 FP16 稠密约 990 TFLOPS、FP8 稠密约 1979 TFLOPS(稀疏可再翻倍至 ~3958),而其 FP32 CUDA Core 仅约 67 TFLOPS——近一个数量级的差距全部来自专用单元 + 低精度。到 Blackwell Ultra(GB300)这一代,单 GPU 已携 288GB HBM3e、密集 FP4 推理迈入 ~15 PFLOPS 级;而即将到来的 Rubin 平台官方宣称单机柜(Vera Rubin NVL144)FP4 推理达 EFLOPS(每秒百亿亿次)级「读懂 Tensor Core / 低精度数据流」依旧是 L1 工程师的入场券,只是标尺每年都在往上跳。

原理与架构

理解单卡微架构,最有效的方式是从 GPU 的最小执行集群 SM(Streaming Multiprocessor,流式多处理器)开始,再横向对比昇腾的 DSA 路线。

2.1 NVIDIA GPU:SM 内部结构

一颗 H100 GPU(GH100)由 132 个 SM 组成;每个 SM 是一个相对独立的「微型并行处理器」,内部划分为 4 个 处理块(Processing Block / SM Sub-Partition),每块各有一个 Warp Scheduler。下图是单个 SM 的内部解剖:

逐组件读这张图

组件职责关键约束
Warp Scheduler每周期挑选一个就绪 warp,向执行单元发射指令调度的是「warp」而非单线程,是 latency hiding 的引擎
CUDA Core标量/向量 FMA,处理 FP32/INT32/FP64逐元素算,GEMM 吞吐低
Tensor Core一条指令完成一个矩阵块的乘加累加低精度专用,吞吐是 CUDA Core 的 8~16 倍
寄存器堆(Register File)每 SM 共 64K × 32-bit,线程私有寄存器用太多 → occupancy(占用率)下降
Shared Memory / L1SM 内 SRAM,软件可控的暂存区Hopper 上与 L1 共 256 KB,可配置切分

2.2 Warp 调度:32 线程 SIMT 与延迟掩盖

GPU 的执行模型是 SIMT(Single Instruction, Multiple Threads,单指令多线程)。硬件把线程以 32 个为一组打包成一个 warp,同一个 warp 内的 32 个线程锁步执行同一条指令,只是各自操作不同的数据。

为什么是 warp 而不是单线程?答案是 延迟掩盖(latency hiding)

核心机制:当 Warp 0 因访存阻塞(HBM 延迟可达数百时钟周期)时,调度器零开销地切换到其他就绪 warp 继续发射指令。只要 SM 上「常驻的 warp 足够多」(高 occupancy),访存延迟就被计算完全掩盖——GPU 不靠降低单条指令延迟取胜,而靠永远有活干。这也解释了一个反直觉现象:寄存器/shared memory 用得太多会限制常驻 warp 数,反而因延迟暴露而变慢。

要点在于:SIMT 的代价是 warp divergence(线程束分歧)。若一个 warp 内 32 个线程走进不同的 if/else 分支,硬件只能串行执行每条分支路径,性能腰斩。这是 GPU 编程「避免分支」铁律的微架构根源。

2.3 Hopper/Blackwell Tensor Core 与 FP16→FP8→FP4

Tensor Core 的本质是一个硬连线的小矩阵乘加器:一条 MMA 指令直接吃下两个小矩阵块,输出乘加累加结果,省掉了 CUDA Core 逐元素 FMA 时反复读写寄存器的开销。精度越低 → 单位面积塞下的乘加器越多 → 吞吐越高,这是低精度换吞吐的硬件根因。

架构 / 卡代次新增精度支持代表算力(稠密 / 稀疏)
Volta V1001st GenFP16FP16 ~125 TFLOPS
Ampere A1003rd Gen+ TF32 / BF16 / INT8FP16 ~312 / 624 TFLOPS
Hopper H1004th Gen+ FP8(E4M3 / E5M2)FP16 ~990,FP8 ~1979 / 3958 TFLOPS(稠密/稀疏)
Blackwell B2005th Gen+ FP4(含微缩放 MXFP / NVFP4)FP8 ~4500,FP4 ~9000 / 18000 TFLOPS(稠密/稀疏)
Blackwell Ultra B300/GB3005th Gen+强化 NVFP4 推理密集 FP4 ~15 PFLOPS 级,288GB HBM3e(2025 H2 量产)
Rubin VR200(路线图)6th GenHBM4 + NVLink 6单 GPU FP4 ~50 PFLOPS 级(官方宣称,2026 H2 规划)

表中 Blackwell Ultra 与 Rubin 为 2025–2026 的最新代次:Blackwell Ultra(GB300)已于 2025 下半年量产Rubin(VR200,搭 HBM4、NVLink 6、自研 Vera CPU)截至 2026 年中仍属「已发布路线图、尚未量产出货」,FLOPS 为官方路线图宣称值,最终量产规格以厂商 datasheet 为准。

FP8 的两种格式(IEEE 风格 8-bit 浮点):

  • E4M3:1 符号 + 4 指数 + 3 尾数。动态范围窄、精度高,用于前向激活与权重
  • E5M2:1 符号 + 5 指数 + 2 尾数。动态范围宽、精度低,用于反向梯度(梯度量级跨度大,需要更大动态范围避免溢出)。

Hopper 的 Transformer Engine 会在训练中逐 tensor 动态选择 FP8 格式并维护缩放因子(per-tensor scaling),自动在 E4M3/E5M2 与 BF16 之间切换,这是 FP8 训练能收敛的工程关键。Blackwell 进一步把缩放粒度细化到微缩放(micro-scaling, MXFP4)——每 32 个元素共享一个缩放因子,使 FP4 这种只有 16 个可表示值的极端低精度也能用于推理。

2.4 华为昇腾 DSA:Cube/Vector/Scalar 三单元异步协作

昇腾(Ascend)的 达芬奇架构 走的是与 GPU「同构 SIMT」不同的 DSA 数据流路线:把不同类型的运算物理隔离成三类专用单元,每类单元有自己的指令队列,彼此异步并行、靠流水线重叠隐藏延迟

三单元的分工与异步协作

  • Cube 单元(矩阵):算力主力,一拍完成 16×16 × 16×16 的矩阵乘加,对标 GPU 的 Tensor Core,承担绝大部分 GEMM / 卷积。
  • Vector 单元(向量):处理逐元素的激活、LayerNorm、Softmax 等「非矩阵」算子。
  • Scalar 单元(标量):类似一颗小 CPU,负责循环控制、地址计算、向 Cube/Vector 发射指令,是整个 Core 的「指挥中枢」。

异步流水的精髓在于:当 Cube 单元正在算第 N 块矩阵时,MTE 搬运引擎已经在异步把第 N+1 块数据从 HBM 搬进片上 buffer,同时 Vector 单元在处理第 N-1 块的激活。三类单元 + 搬运引擎在时间轴上完全重叠,靠**显式的同步指令(如 set/wait flag)**协调依赖——这与 GPU「靠海量 warp 隐式掩盖延迟」是两种截然不同的延迟工程哲学。GPU 用并行度换延迟,昇腾用显式流水换延迟。

需要强调的是:GPU 的 SIMT 把「调度」交给硬件(warp scheduler 自动切换),编程模型简单但需要高 occupancy;昇腾 DSA 把「调度」更多交给**编译器与软件(CANN / Ascend C)**显式编排流水,硬件更省、峰值利用率潜力更高,但对编译器和算子开发者的要求也更高。这正是异构芯片移植成本的核心来源。

动手实践:Tensor Core vs CUDA Core 吞吐实测

实验目标:写一个 micro-benchmark,亲手测出同一个 GEMM 在 FP32(落 CUDA Core)与 FP16/BF16(落 Tensor Core)下的 TFLOPS 差异,量化「低精度换吞吐」的真实倍数。产出物:一张吞吐对比表 + 对加速比的解释。

3.1 环境准备

# 推荐 Python 3.11,用 venv 隔离
python3 -m venv .venv && source .venv/bin/activate

# NVIDIA GPU 路径(默认装 CUDA 版 torch)
pip install torch

# Mac / CPU 替代路径(无 GPU 时)
# pip install torch --index-url https://download.pytorch.org/whl/cpu

3.2 代码:用 CUDA Event 精确计时 GEMM

import torch

def benchmark_gemm(dtype, n=4096, iters=50, warmup=10):
"""测量 n×n @ n×n GEMM 的 TFLOPS。"""
dev = "cuda" if torch.cuda.is_available() else "cpu"
a = torch.randn(n, n, device=dev, dtype=dtype)
b = torch.randn(n, n, device=dev, dtype=dtype)

# 一次 GEMM 的浮点运算量:2 * n^3(每个输出元素 n 次乘 + n 次加)
flops = 2.0 * n ** 3

if dev == "cuda":
# 预热:触发 cuBLAS handle 初始化与 kernel 选择
for _ in range(warmup):
_ = a @ b
torch.cuda.synchronize()

start = torch.cuda.Event(enable_timing=True)
end = torch.cuda.Event(enable_timing=True)
start.record()
for _ in range(iters):
c = a @ b
end.record()
torch.cuda.synchronize()
ms = start.elapsed_time(end) / iters # 平均每次耗时(ms)
else:
import time
for _ in range(3): # CPU 维度需调小,见 Gotchas
_ = a @ b
t0 = time.perf_counter()
for _ in range(iters):
c = a @ b
ms = (time.perf_counter() - t0) / iters * 1e3

tflops = flops / (ms * 1e-3) / 1e12
return ms, tflops


if __name__ == "__main__":
dev = "cuda" if torch.cuda.is_available() else "cpu"
print(f"[device] {dev}")
# 让 cuBLAS 允许使用 TF32(Ampere+ 的 Tensor Core 加速 FP32 GEMM)
torch.backends.cuda.matmul.allow_tf32 = True

if dev == "cuda":
configs = [("FP32 (CUDA Core)", torch.float32),
("TF32 (Tensor Core)", torch.float32), # 由 allow_tf32 控制
("FP16 (Tensor Core)", torch.float16),
("BF16 (Tensor Core)", torch.bfloat16)]
# FP32 纯 CUDA Core 基线:关闭 TF32 单独测一次
torch.backends.cuda.matmul.allow_tf32 = False
ms, tf = benchmark_gemm(torch.float32)
print(f"{'FP32 (CUDA Core)':<22} {ms:8.2f} ms {tf:8.1f} TFLOPS")
torch.backends.cuda.matmul.allow_tf32 = True
for name, dt in configs[1:]:
ms, tf = benchmark_gemm(dt)
print(f"{name:<22} {ms:8.2f} ms {tf:8.1f} TFLOPS")
else:
# CPU 路径:维度调小,仅对比 float32 / bfloat16 说明原理
for name, dt in [("FP32 (CPU)", torch.float32),
("BF16 (CPU)", torch.bfloat16)]:
ms, tf = benchmark_gemm(dt, n=2048)
print(f"{name:<22} {ms:8.2f} ms {tf:8.1f} TFLOPS")

3.3 运行与观察

python tc_vs_cuda_gemm.py

NVIDIA GPU 路径(以 A100/H100 为例)的典型输出形态:

[device] cuda
FP32 (CUDA Core) ~XX ms ~19 TFLOPS ← 纯 CUDA Core 基线
TF32 (Tensor Core) ~XX ms ~156 TFLOPS ← TF32 走 Tensor Core,~8×
FP16 (Tensor Core) ~XX ms ~290 TFLOPS ← FP16 满血 Tensor Core
BF16 (Tensor Core) ~XX ms ~285 TFLOPS ← BF16 与 FP16 同档

怎么读这组数:FP32→TF32 约 8 倍、FP32→FP16 约 15 倍 的跃升,全部来自 Tensor Core 取代 CUDA Core。同一行 Python a @ b,仅改 dtype 与 allow_tf32 开关,cuBLAS 就为你选择了完全不同的底层 kernel(*_gemm_* vs *_tensorop_*)。这就是前文「精度换吞吐」的可量化证据

Mac / CPU 替代方案:无 GPU 时代码同样能跑(维度自动降到 2048),你会看到 FP32 与 BF16 的差距很小——因为CPU 没有 Tensor Core 这类矩阵专用单元,BF16 在 CPU 上往往还要软件转换,无法体现硬件加速。目的一致:通过「换 dtype 吞吐不变」反证「Tensor Core 是 GPU 独有的硬件红利」,加深对专用单元价值的理解。

踩坑预警 (Gotchas)

  • 不用 CUDA Event 计时 = 测了个寂寞:CUDA kernel 异步下发,用 Python time.time() 会把 kernel 耗时算成接近 0。GPU 路径必须用 torch.cuda.Event + synchronize()
  • 不预热 → 首次包含初始化开销:第一次 GEMM 含 cuBLAS handle 初始化和 kernel autotune,必须 warmup 10 次以上再计时。
  • TF32 默认行为因版本而异:PyTorch 不同版本对 allow_tf32 默认值不同。务必显式设置,否则你以为在测 FP32,实际跑的是 TF32,加速比会失真。
  • GEMM 维度太小测不出 Tensor Core 优势:维度 < 1024 时访存/启动开销占主导,算力跑不满。用 n=8192 这类大矩阵才能逼近峰值。
  • CPU OOM8192×8192 FP32 单矩阵约 256 MB,三个就 768 MB,低内存机器务必把 n 调到 2048。
  • 算力换算口径:本实验测的是稠密 FP16,约为官方 FP16 稀疏 标称值的一半——稀疏算力需 2:4 结构化稀疏才能达到,别拿稠密实测去对标稀疏标称。

深入思考

下面三题每题先给题干,再用 <details> 折叠一份图文并茂的参考答案。建议先合上答案自己想 3 分钟,再展开对照。

思考题 1:占用率与寄存器的权衡

你写了一个 CUDA kernel,为了减少访存把大量中间结果缓存在寄存器里,结果性能不升反降。结合 2.2 节的 warp 调度与 occupancy 机制,解释「寄存器用量 ↑ → 常驻 warp 数 ↓ → 延迟掩盖能力 ↓」的因果链,并说明你会用什么指标(提示:nsight compute 的 achieved occupancy)来定位。

展开参考答案(含寄存器-occupancy 因果链图 + 算一遍)

结论:寄存器是 SM 上一块固定大小的「公共资源」,每个线程占得越多,能同时常驻的 warp 就越少;常驻 warp 一旦不足以填满访存延迟,SM 就会空转——于是「省了访存」反而「赔了并行」。

用具体数字算一遍(以 H100 一个 SM 为例,数量级估算):

  1. 一个 SM 的寄存器堆共 64K × 32-bit = 65536 个寄存器(4 个处理块合计)。
  2. 若每线程用 32 个寄存器:可常驻线程 ≈ 65536 / 32 = 2048 个 = 64 个 warp(每 warp 32 线程)——接近 SM 上限(H100 每 SM 最多 64 warp),occupancy ≈ 100%。
  3. 若你为了缓存中间结果,把每线程寄存器堆到 128 个:可常驻线程 ≈ 65536 / 128 = 512 个 = 16 个 warp,occupancy 直接掉到 ~25%。
  4. 后果:HBM 访存延迟约数百周期,需要足够多的就绪 warp 轮换填满;只剩 16 个 warp 时,调度器很快就「无 warp 可切」,SM 只能干等数据返回——这就是「省了访存却赔了并行」。

怎么定位:用 nsight computencu)看 Achieved Occupancy(实测占用率)与 Registers Per Thread。若 achieved occupancy 远低于 theoretical(如 25% vs 理论可达 50%+),且寄存器用量很高,就是寄存器压力(register pressure)限制了并行。对策:用 __launch_bounds__-maxrregcount 限制寄存器、把部分中间结果改放 shared memory、或拆分 kernel——在「访存次数」与「并行度」之间找平衡点,而非单边优化。

思考题 2:FP8 训练为何需要 Transformer Engine

直接把模型权重和激活粗暴转成 FP8 训练通常会发散。结合 2.3 节 E4M3/E5M2 的动态范围差异与 per-tensor scaling,论证「为什么前向用 E4M3、反向梯度用 E5M2」,以及缩放因子若缺失会引发怎样的数值灾难。

展开参考答案(含 FP8 格式选型 + 缩放因子作用图)

结论:FP8 只有 8 个 bit,可表示的数值范围极窄。前向激活/权重数值集中、要精度 → 用尾数多的 E4M3;反向梯度量级跨度大、要范围 → 用指数多的 E5M2;而 per-tensor scaling(缩放因子)负责把每个 tensor 的真实数值「平移」到 FP8 能表示的窗口里,缺了它就会大面积溢出/下溢成 0。

为什么前向 E4M3、反向 E5M2

  • 前向(权重/激活):经过 normalization,数值分布相对集中、量级稳定,但对精度敏感(精度损失会逐层累积)。E4M3 用 3 位尾数换取更高精度,动态范围窄一点可以接受。
  • 反向(梯度):梯度量级在不同层、不同训练阶段可以跨好几个数量级,动态范围是第一需求——一旦溢出/下溢,梯度直接失真。E5M2 用 5 位指数换取更宽范围,牺牲尾数精度(梯度本就带噪声,精度低些可容忍)。

缩放因子缺失的数值灾难:FP8 E4M3 的最大可表示值约 448、最小正规数约 2⁻⁶。若某个 tensor 的梯度量级是 1e-7,不乘缩放因子直接转 FP8 → 全部下溢成 0(梯度消失,模型不再更新);反之激活值偏大不缩放 → 上溢成 Inf → 反传出 NaN → 训练崩溃。Transformer Engine 的核心工作就是:为每个 tensor 实时统计幅值、动态维护一个缩放因子,计算前 × scale 把数值搬进 FP8 窗口、计算后 ÷ scale 还原,并配合 BF16 主权重保证更新精度——这就是 FP8 训练能稳定收敛的工程关键。

思考题 3:两种延迟工程哲学的取舍

GPU 靠海量 warp 隐式掩盖延迟,昇腾靠编译器显式编排 Cube/Vector/Scalar 流水。结合 2.4 节,分析:在「峰值算力利用率」「编程门槛」「算子覆盖度」三个维度上,这两条路线各自的优势与代价是什么?为什么这直接决定了「把模型从 GPU 迁到昇腾」的真实成本?

展开参考答案(含两种延迟哲学对比图)

结论:GPU 把「让单元有活干」的责任交给硬件(warp scheduler 自动切换),编程简单、生态成熟,代价是要堆高 occupancy 才能跑满;昇腾把这份责任交给编译器/软件(CANN/Ascend C 显式编排流水),硬件更省、峰值潜力更高,代价是编程门槛高、算子覆盖度需逐个建设——而迁移成本恰恰压在「编译与算子」这一层。

三维度对比:

维度GPU(隐式 SIMT)昇腾(显式流水)
峰值算力利用率中高,但强依赖 occupancy 调优;调不好则远低于峰值潜力更高——流水编排得当可逼近峰值,但「编排得当」本身很难
编程门槛低:写好并行逻辑,调度交给硬件高:算子开发者要显式管理三单元同步与数据搬运(set/wait flag)
算子覆盖度高:CUDA 生态 + cuBLAS/cuDNN/CUTLASS 多年沉淀,长尾算子齐全建设中:主流算子覆盖好,长尾/自定义算子常需手写 Ascend C

为什么决定迁移成本:模型最终都要落成针对特定硬件的 kernel。GPU 上「贴着 CUDA 优化」的算子(手写 CUDA / Triton / 依赖 cuBLAS)换到昇腾,调度哲学从「硬件隐式」变成「软件显式」——之前不用操心的流水编排,现在要由 CANN/Ascend C 重新表达;GPU 生态里现成的长尾算子,昇腾上可能要逐个补齐。上层框架(PyTorch + torch_npu、MindIE)能抽象掉一部分,但「代码 → 硬件指令」这一跳的算子覆盖与性能调优无法抽象掉——这正是 L1.1 这层微架构差异,最终放大成 L2/L3 迁移工作量的根本原因(详见 L1.6 芯片横评与 L2 编译层)。

延伸阅读

1. 核心 Paper / 白皮书

  • NVIDIA H100 Tensor Core GPU Architecture Whitepaper(2022)— 第 4 代 Tensor Core、FP8、TMA、Thread Block Cluster 的一手定义。
  • NVIDIA Blackwell Architecture Technical Brief(2024)— FP4 / 微缩放(MXFP)与第 5 代 Tensor Core。
  • NVIDIA GTC 2025 主题演讲与 Rubin / Vera 路线图(2025)— Blackwell Ultra(GB300)量产、Rubin(HBM4 + NVLink 6 + Vera CPU)2026 规划的一手来源。
  • FP8 Formats for Deep Learning(Micikevicius et al., 2022)— E4M3/E5M2 格式与 FP8 训练的理论依据。
  • DaVinci: A Scalable Architecture for Neural Network Computing(华为,HotChips 2019)— 昇腾 Cube/Vector/Scalar 三单元架构的官方阐述。

2. 相关高 Star 仓库与源码必读路径

  • NVIDIA/cutlass — 看 include/cutlass/gemm/examples/,理解 Tensor Core MMA / WGMMA 指令如何被组织成高性能 GEMM。
  • NVIDIA/TransformerEngine — 看 transformer_engine/pytorch/ 下的 FP8 recipe 与 scaling 逻辑,对应 2.3 节。
  • triton-lang/triton — 看 python/tutorials/03-matrix-multiplication.py,用 Triton 写一个能调用 Tensor Core 的 GEMM kernel。

3. 优质博客 / 视频 / 公开课

  • NVIDIA 技术博客「Programming Tensor Cores」与「Using FP8 with Transformer Engine」系列。
  • 华为昇腾社区「CANN 算子开发」与「Ascend C」编程指南,理解 DSA 显式流水编排。
  • 公开课 Stanford CS149(Parallel Computing)/ MIT 6.5940(TinyML),建立 SIMT 与延迟掩盖的系统观。

下一篇L1.2 互联拓扑:NVLink / InfiniBand / RoCE:把视野从「单卡内部」放大到「卡间互联」,讲清当算力被切到多卡后,数据如何在芯片之间高速流动。