🏠 总目录📚 本教程 速查
📑 本页目录(点开跳转)

附录 A · 速查

📌 Ctrl+F 搜。不要通读。 用法:写代码 / 看 profiler / 定容量时卡住 → 搜关键词 → 拿到数字 → 回去干活。

唯一的例外是最后的「🧮 十道计算题」 —— 那一节要你动笔,不是拿来搜的。公式看懂了,和能口算出来,隔着一层。


🔢 一张表:必须记住的量级

层级 带宽 相对 HBM
HBM(A100 / H100) 2.0 / 3.35 TB/s
NVLink 450–900 GB/s ~1/4
PCIe 4.0/5.0 32–64 GB/s ~1/40 ⚠️
InfiniBand 25–50 GB/s ~1/60
以太网 1–12 GB/s ~1/300

三个比值:Shared Mem 比 HBM 快 5 倍 / HBM 比 PCIe 快 40 倍 / NVLink 比网络快 20 倍

GPU BF16 算力 显存 带宽 互联
A100 80G 312 TFLOPS 80 GB 2.0 TB/s NVLink 600 GB/s
H100 SXM 989(FP8 1979) 80 GB 3.35 TB/s NVLink 900 GB/s
RTX 4090 165 24 GB 1.0 TB/s ⚠️ 仅 PCIe

🧮 必背公式

   算术强度 = FLOP ÷ 搬运字节数
   A100 平衡点 = 312 TFLOPS ÷ 2.0 TB/s ≈ 156 FLOP/字节
   → 大于 156 是算力瓶颈,小于是带宽瓶颈
   训练 FLOP:每 token ≈ 6 × 参数量
              (前向 2N + 反向对输入 2N + 反向对权重 2N)
   ⚠️ 序列 ≥8K 时要加 attention 项:12 × 层数 × hidden × 序列长
   MFU = (6 × 参数量 × tokens/秒) ÷ (GPU数 × 峰值FLOPS)
   训练时间 ≈ 6ND ÷ (GPU数 × 峰值FLOPS × MFU)
   训练成本 ∝ 1 / MFU      ⭐ MFU 翻倍 = 成本减半
   ⭐ 推理心算:最快解码速度 = 显存带宽 ÷ 模型大小
     7B BF16(14GB)在 A100(2TB/s)→ ≈143 tok/s
   ⭐ 训练显存 ≈ 16 × 参数量(B) GB + 激活
     (BF16参数2 + BF16梯度2 + FP32主权重4 + Adam m 4 + v 4 = 16)
   KV Cache = 2 × 层数 × 序列长 × KV维度 × batch × 字节数
   气泡占比 = (P−1) ÷ (M+P−1)     ⭐ 黄金法则 M ≥ 4P
   Ring AllReduce 每卡通信量 ≈ 2 × 数据量(与卡数无关)
   checkpoint 最优间隔 ≈ √(2 × 单次耗时 × MTBF)
   每百万 token 成本 = GPU时价 ÷ (吞吐 × 3600 × 利用率) × 1e6

📊 MFU 基准

MFU 评价 该干什么
< 20% 💀 先查数据管线
20–35% ⚠️ 查检查点配置、通信、融合
35–45% 🟡 常规优化还有空间
45–55% 良好
55–60% 接近天花板
> 60% 🤔 检查公式是否算错

天花板是 60% 不是 100%:通信、LayerNorm/Softmax、数据加载、 kernel 启动、优化器更新都占时间但不算有效 FLOP。


💾 显存四大块(7B 为例)

项目 公式 7B 和 batch 有关?
参数 P × 2 14 GB
梯度 P × 2 14 GB
优化器状态 P × 12 84 GB
激活 ∝ batch×seq×hidden×层数 只有这块

诊断分叉:把 batch 调到 1 还 OOM 吗? 还 OOM → 前三块的问题(ZeRO / 量化 / LoRA),调 batch 没用 不 OOM → 激活的问题(梯度检查点 / FlashAttention)


🧰 显存优化速查

手段 省哪块 省多少 代价
FlashAttention 激活 O(n²)→O(n) 几乎无
BF16 参数+激活 ÷2 ✅ 几乎无 ⭐
梯度检查点 激活 O(L)→O(√L) +20~35% 时间
ZeRO-2 梯度+优化器 ÷8 通信不变
ZeRO-3/FSDP 全部 ÷N +50% 通信
8-bit Adam 优化器 12→4 字节 极小质量损失
LoRA 梯度+优化器 ÷100 只适用微调
CPU offload 任意 ⚠️ 慢很多

🕸️ 并行策略速查

数据并行 张量并行 流水线并行
切什么 数据 层内矩阵 层(按深度)
通信频率 每步 1 次 每层 4 次 每切分点 1 次
通信量 2×参数量 很大 很小
能跨机
救"单层装不下" ✅ ⭐
主要缺点 不省显存 必须机内 气泡

黄金法则:TP 机内(NVLink)/ PP 跨机 / DP 最外层。 记忆:通信最凶的贴着最快的线。

恒等式(全教程出现 3 次):AllReduce = ReduceScatter + AllGather —— 它解释了 ZeRO-2 为什么免费、序列并行为什么不增加通信。

决策顺序:装得下 → DP+ZeRO-2 / 不够 → FSDP / 多机 → HYBRID_SHARD / 单层装不下 → +TP(≤8) / 还不够 → +PP(M≥4P) / MoE → +EP / 长序列 → +CP


🚀 推理速查

Prefill Decode
每步 token 全部输入 1 个
算术强度 ~2 💀
瓶颈 算力 带宽
指标 TTFT TPOT
占时间 ~10% ~90%

Decode 的 MFU 只有 1–5% 是正常的 —— 带宽瓶颈下算力本来就用不满。 推理该看带宽利用率和吞吐,不是 MFU。

优化顺序: ① 换推理引擎(vLLM/SGLang/TRT-LLM,5–10 倍)② 连续批处理 ③ 权重量化 ④ KV Cache 量化 ⑤ 张量并行 ⑥ 投机解码(仅低并发) ⑦ 前缀缓存

KV Cache 方案 相对大小 说明
MHA 早期模型
GQA-8 1/4 ~ 1/8 几乎无损,选模型时就要看
MQA 1/32 有质量下降
MLA ≈ GQA 分 2.25 组 DeepSeek,低秩压缩 + 吸收 + RoPE 解耦16 章第四节

⚙️ 常用配置片段

# 混合精度(BF16,不需要 GradScaler)
import torch
import torch.nn.functional as F
with torch.autocast("cuda", dtype=torch.bfloat16):
    loss = model(x)
loss.backward()
torch.nn.utils.clip_grad_norm_(model.parameters(), 1.0)

# AdamW 分组:bias/norm 不加 weight decay
decay = [p for n,p in model.named_parameters() if p.ndim > 1 and "bias" not in n]
nodecay = [p for n,p in model.named_parameters() if p.ndim <= 1 or "bias" in n]
opt = torch.optim.AdamW([{"params":decay,"weight_decay":0.01},
                         {"params":nodecay,"weight_decay":0.0}], lr=3e-4, fused=True)

# FlashAttention(自动选后端)
out = F.scaled_dot_product_attention(q, k, v, is_causal=True)

# DDP 梯度累积
ctx = nullcontext() if is_last else model.no_sync()

# vLLM
llm = LLM(model=..., tensor_parallel_size=2, gpu_memory_utilization=0.90,
          enable_prefix_caching=True, kv_cache_dtype="fp8",
          enable_chunked_prefill=True)
# 环境变量
export PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True   # 抗碎片
export NCCL_DEBUG=INFO                                    # 看实际通信路径
export TORCH_NCCL_BLOCKING_WAIT=1                         # 超时报错而非挂死
export TORCH_LOGS="graph_breaks,recompiles"               # 查 compile 断图

# 诊断命令
nvidia-smi topo -m                    # 拓扑(NV8 好 / SYS 差)
nsys profile -t cuda,nvtx,nccl ...    # 看通信计算是否重叠

🩺 诊断速查表

症状 最可能的原因 章节
MFU < 20% 数据管线没喂饱 22
单卡快多卡慢 通信 / 拓扑 0514
batch=1 也 OOM 优化器状态 0911
显存够却 OOM 碎片 09
开了 AMP 没变快 维度没对齐 / 模型太小 06
compile 没提速 graph break 07
FlashAttention 没生效 自定义 attention mask 08
FSDP 没省显存 没设 auto_wrap_policy 11
保存 checkpoint 时 OOM 用了 FULL_STATE_DICT 1121
推理吞吐低 KV 碎片 / 没连续批处理 1617
TPOT 有毛刺 长 prefill 插队 17
训练卡死无报错 AllReduce 挂死 1021
loss 突然尖峰 异常数据 / FP16 溢出 2106
恢复后精度异常 checkpoint 漏存数据位置 21

⚠️ 十个最容易踩的坑

后果
nvidia-smi GPU-Util 当性能指标 它只说"有 kernel 在跑",5% 算力也显示 100% ⭐
自定义 attention mask 静默禁用 FlashAttention
FSDP 没设 auto_wrap_policy 显存没省还 OOM ⭐
梯度累积忘 no_sync() 通信量翻 N 倍
sampler.set_epoch() 等于没 shuffle
梯度裁剪前忘 unscale_() 裁剪阈值失效(FP16)
矩阵维度不是 8 的倍数 用不上 Tensor Core
量化后只看 PPL 数学和代码能力可能已经崩了
checkpoint 漏存数据位置 恢复后样本重复/遗漏,且不报错
不设 NCCL_BLOCKING_WAIT 一卡挂全场等,GPU 显示 100% 但没进展 ⭐

📖 术语对照

中文 英文 一句话
算力利用率 MFU 有效算力 ÷ 峰值算力
算术强度 Arithmetic Intensity 每搬一字节能做多少次运算
首字延迟 TTFT 由 Prefill 决定
每字延迟 TPOT 由 Decode 决定,通常主导端到端
预填充 Prefill 一次处理全部输入,算力瓶颈
解码 Decode 一次一个 token,带宽瓶颈
气泡 Bubble 流水线填充/排空时的空闲
分片 Sharding 把状态切开分给多卡(ZeRO)
连续批处理 Continuous Batching 以迭代为单位调度
分页注意力 PagedAttention KV Cache 的虚拟内存分页
投机解码 Speculative Decoding 小模型猜、大模型验,精确无损
前缀缓存 Prefix Caching 共享前缀的 KV 只算一次
张量/流水线/数据并行 TP / PP / DP 三个正交的切分维度
专家并行 EP MoE 的专家分到不同卡,用 All2All

🧮 十道计算题(这些公式的直接应用)

为什么要有这一节:上面所有公式,本板块都讲透了物理原因, 甚至给了 max_batch() 这样能直接跑的脚本 —— 但从来没让你自己算过一次。 而定容量、选卡、定 SLO,在工作里天天要口算;面试白板上也是现场算。

⚠️ 十道题全部只用本板块已经给过的公式,不引入任何新知识。 建议:先自己算,再点开答案,一道题一两分钟。算不出来不要紧 —— 顺着答案里的 🔗 回去看那一章就行。

1️⃣ 训练显存:70B 全参训练,8 张 A100 80G 够吗?

Llama-3 70B,BF16 + Adam,全参数训练。手上 8 张 A100 80G(共 640 GB)。装得下吗?差多少?

👀 答案

用哪个公式训练显存 ≈ 16 × 参数量(B) GB + 激活

代入:16 × 70 = 1120 GB(这还没算激活)

拆开看:参数 140(70×2)+ 梯度 140(70×2)+ 优化器状态 840(70×12:FP32 主权重 4 + Adam 的 m 4 + v 4)

结果:640 GB 远远不够,差 480 GB —— 卡数还要再翻一倍多才勉强放下静态部分。

💡 这个数告诉你什么1120 里有 87.5% 是梯度和优化器状态,参数本身只占 12.5%。 所以省显存的重点从来不在参数上,而在后两块(ZeRO / LoRA)。 ⭐ 这条 16×N 的价值在于它能让你 30 秒否掉一个方案,不用打开计算器。

🔗 第 3 章 显存与带宽墙 · 第 11 章 ZeRO 与 FSDP

2️⃣ 推理显存:同一个 70B,改成推理呢?

只做推理(BF16 权重)。(a) 单张 A100 80G 装得下吗?(b) 两张呢?(c) 换成 INT4 呢?

👀 答案

用哪个公式:推理显存 = 权重 + KV Cache(没有梯度和优化器状态)

💡 这个数告诉你什么:训练(1120 GB)是推理权重(140 GB)的 8 倍 —— 这就是"训练要集群、推理常常单机"的数字来源。 ⭐ 而 INT4 把"两张卡勉强跑"变成"一张卡舒服跑":量化在推理侧省的不只是时间,还有卡数。

🔗 第 18 章 量化 · 第 16 章 KV Cache

3️⃣ KV Cache 大小:长上下文 + 大 batch

Llama-3 70B:80 层、GQA-8(8 个 KV 头)、head_dim 128、BF16seq=8192batch=16 时 KV Cache 多大?如果它是 MHA(64 个 KV 头)呢?

👀 答案

用哪个公式KV Cache = 2 × 层数 × 序列长 × KV维度 × batch × 字节数

   KV 维度 = 8 × 128 = 1024
   每 token 每层 = 2 × 1024 × 2 字节 = 4 KB
   × 80 层                          = 320 KB / token   ⭐
   × 8192                           = 2.62 GB / 请求
   × 16                             = 42 GB

MHA 版本:KV 维度 = 64 × 128 = 8192,是 GQA-8 的 8 倍 → 336 GB 💀

💡 这个数告诉你什么:42 GB 已经超过 INT4 权重(35 GB)本身了 —— 长上下文 + 高并发的场景,KV Cache 才是主角,权重反而是配角。 ⭐ 而 MHA 那个 336 GB 说明:GQA 不是"一个优化",是长上下文可行性的前提。

🔗 第 16 章 KV Cache

4️⃣ 最大 batch:量化到底买回来多少并发?

A100 80G,7B 模型:32 层、GQA-8、head_dim 128seq=4096,留 10% 余量。 (a) FP16 权重(14 GB)+ FP16 KV,最多多少并发? (b) INT4 权重(3.5 GB)+ FP8 KV(1 字节),最多多少并发?

👀 答案

用哪个公式:第 16 章的 max_batch() —— (可用显存 − 权重) ÷ 每请求 KV

(a)

   可用     = 80 × 0.9 − 14 = 58 GB
   每 token = 2 × 32 × 8 × 128 × 2 字节 = 128 KB
   每请求   = 128 KB × 4096 = 0.537 GB
   → 58 ÷ 0.537 ≈ 108 并发

(b)

   可用     = 80 × 0.9 − 3.5 = 68.5 GB
   每 token = 2 × 32 × 8 × 128 × 1 字节 = 64 KB
   每请求   = 64 KB × 4096 = 0.268 GB
   → 68.5 ÷ 0.268 ≈ 255 并发     ⭐ 2.4 倍

💡 这个数告诉你什么:这 2.4 倍是两个量化分别出力的结果 —— 权重量化抬高分子(58 → 68.5,只涨 18%),KV 量化压低分母(÷2)。 拆开验证一下:只做权重量化 = 68.5 ÷ 0.537 ≈ 128;只做 KV 量化 = 58 ÷ 0.268 ≈ 216。 ⭐ 高并发下 KV 量化比权重量化更值钱 —— 这就是第 18 章"两者都要做"的数字依据。

🔗 第 16 章 KV Cache · 第 18 章 量化

5️⃣ 算术强度:Decode 到底离平衡点多远?

7B BF16 在 A100(312 TFLOPS / 2.0 TB/s,平衡点 156)。 Decode 阶段 batch=1 的算术强度是多少?batch 要多大才能翻到计算密集那一侧?

👀 答案

用哪个公式算术强度 = FLOP ÷ 搬运字节数;每 token 前向 FLOP ≈ 2 × 参数量(6N 里的前向那一项)

   FLOP     = 2 × 7e9        = 1.4e10
   搬运字节 ≈ 权重 14 GB     = 1.4e10
   → 算术强度 = 1.4e10 ÷ 1.4e10 = 2 FLOP/字节   💀

batch = B 时:权重仍然只读一遍,FLOP 变 B 倍 → 算术强度 ≈ 2B 要 ≥ 156 → B ≥ 78

💡 这个数告诉你什么:这个 2 正是第 15 章那句"算术强度 ≈ 2,离平衡点 156 差 78 倍"的来源 —— ⭐ "差 78 倍"和"batch 要 78"是同一个数,因为它们本来就是同一件事。 而 78 并发在题 4(a) 的配置下(上限 108)虽然放得下, 但那已经吃掉大半 KV 容量、TPOT 也会明显变差 —— 要同时守 SLO,现实里很难稳定跑在那儿。 这就是"Decode 几乎永远待在访存这一侧"的完整逻辑链。

🔗 第 4 章 Roofline 与 MFU · 第 15 章 推理和训练是两回事

6️⃣ Roofline:Prefill 在哪一侧?它要多久?

同样 7B BF16 在 A100,这回是 Prefill 一次 2048 token 的输入。 算术强度多少?在 Roofline 的哪一侧?耗时下限是多少?

👀 答案
   FLOP     = 2 × 7e9 × 2048 = 2.87e13
   搬运字节 ≈ 权重 14 GB      = 1.4e10
   → 算术强度 = 2.87e13 ÷ 1.4e10 = 2048 FLOP/字节
     (注意它就是 2 × token 数,和上一题同构)

2048 ≫ 156 → 重度计算密集。 性能上限 = min(峰值算力 312 TFLOPS,带宽 × 强度 = 2.0e12 × 2048 = 4.1e15) → 受算力限制

耗时下限 = 2.87e13 ÷ 312e12 ≈ 92 ms(这是 MFU=100% 的理想值;按现实 40% 算约 230 ms)

💡 这个数告诉你什么:对照一个 decode step 的下限 = 14 GB ÷ 2 TB/s = 7 ms, ⭐ 一次 2048 token 的 Prefill ≈ 13 个 decode step。 这就是"长 Prefill 插进 decode 批次会造成 TPOT 毛刺"(第 17 章)的数字版 —— 也正是 chunked prefill 和 P/D 分离要解决的那件事。

🔗 第 4 章 · 第 15 章 · 第 17 章

7️⃣ MFU:这个训练跑得算好还是算差?

64 张 A100(BF16 峰值 312 TFLOPS)训 7B,实测 210,000 tokens/秒。 MFU 多少?落在哪一档?如果实测只有 12,000 tokens/秒呢?

👀 答案

用哪个公式MFU = (6 × 参数量 × tokens/秒) ÷ (GPU数 × 峰值FLOPS)

   分子 = 6 × 7e9 × 2.1e5 = 8.82e15
   分母 = 64 × 312e12     = 2.00e16
   → MFU ≈ 44%            🟡 接近「良好」档的下沿

12,000 tokens/秒的情况:分子 = 6 × 7e9 × 1.2e4 = 5.04e14 → MFU ≈ 2.5% 💀

💡 这个数告诉你什么:44% 意味着"常规优化还有空间,但不必大改" —— 而且要记得天花板是 60% 不是 100%(通信、LayerNorm、数据加载都占时间却不算有效 FLOP)。 ⭐ 至于 2.5% 那种量级:第一件事是查数据管线,不是调模型。 差两个数量级的问题,不可能是算子融合能解释的。

🔗 第 4 章 Roofline 与 MFU · 本页上面的「MFU 基准」表 · 第 22 章 数据管线与存储

8️⃣ 吞吐上限:单请求最快能吐多快?

单请求解码速度的理论上限: (a) 70B BF16 在 H100(3.35 TB/s) (b) 同样 70B 但 INT4 (c) 70B BF16 在 A100(2.0 TB/s)

👀 答案

用哪个公式最快解码速度 = 显存带宽 ÷ 模型大小

   (a) 3350 GB/s ÷ 140 GB = 24 tok/s
   (b) 3350 GB/s ÷  35 GB = 96 tok/s   ⭐
   (c) 2000 GB/s ÷ 140 GB = 14 tok/s

💡 这个数告诉你什么(三点): ① 24 tok/s 大约"比人读得快一点" —— 所以 70B 单请求做流式输出勉强够用,再慢就难受了。 ② ⭐ H100 的算力是 A100 的 3 倍多,但解码只快 3350÷2000 = 1.7 倍 —— 这个上限只和带宽有关,和算力完全无关。 拿算力当选卡依据在推理侧会算错账。 ③ 想再快,只剩两条路:把模型变小(量化 / 蒸馏 / 剪枝)或者投机解码(下一题)。

🔗 第 4 章 · 第 15 章 · 第 18 章 量化

9️⃣ 投机解码:接受率掉了还能救吗?

草稿模型成本是目标模型的 1/10(c = 0.1),一次猜 k = 4 个。 (a) 接受率 α = 0.8 时加速比多少? (b) α 掉到 0.5 呢? (c) α = 0.5 时把 k 加到 8,能救回来吗?

👀 答案

用哪个公式加速比 ≈ (1 + α + α² + … + αᵏ) ÷ (1 + c·k)

   (a) 分子 = 1+0.8+0.64+0.512+0.410 = 3.36
       分母 = 1 + 0.1×4 = 1.4
       → 2.4 倍  ⭐

   (b) 分子 = 1+0.5+0.25+0.125+0.063 = 1.94
       分母 = 1.4
       → 1.4 倍

   (c) k=8:分子最多收敛到 1÷(1−0.5) = 2.00
       分母 = 1 + 0.1×8 = 1.8
       → 1.11 倍   💀 比 k=4 还差

💡 这个数告诉你什么:⭐ 接受率是这里唯一重要的变量 —— 0.8 掉到 0.5,加速比从 2.4 掉到 1.4。 而 (c) 说明加大 k 救不了低接受率:分子是等比级数(α=0.5 时天花板就是 2), 分母却是线性增长的 —— 加 k 只是往分母上倒钱。 ⚠️ 而且这一切的前提是算力闲置:高并发下这个公式根本不适用,投机解码是净亏。

🔗 第 19 章 投机解码

🔟 量化后显存:14B 这一整套账

14B 模型。(a) FP16 权重多大?(b) 全参训练大概要多少?(c) INT8 / INT4 权重分别多大? (d) A100 80G 上跑 INT4(40 层、GQA-8、head_dim 128、KV 用 FP16、seq=4096),能开多少并发?这时候 KV 和权重谁大?

👀 答案
   (a) FP16 权重 = 14 × 2   = 28 GB
   (b) 全参训练  = 16 × 14  = 224 GB + 激活
   (c) INT8 = 14 GB INT4 = 7 GB
   (d) 可用     = 80 × 0.9 − 7 = 65 GB
       每 token = 2 × 40 × 8 × 128 × 2 字节 = 160 KB
       每请求   = 160 KB × 4096 = 0.655 GB
       → 65 ÷ 0.655 ≈ 99 并发
       此时 KV 占 99 × 0.655 ≈ 65 GB,是权重(7 GB)的 9 倍多  ⭐

💡 这个数告诉你什么:⭐ 量化省的是"固定的那一块"。 并发一上来,KV Cache 就成了绝对主角 —— 65 : 7。 所以第 18 章那句"权重量化和 KV Cache 量化两者都要做",在这个比例面前就不是客套话了: 把 KV 也降到 FP8,分母减半,并发直接到约 198

🔗 第 16 章 KV Cache · 第 18 章 量化 · 第 3 章 显存与带宽墙

十道题全对了说明什么:你已经能在没有文档、没有计算器的情况下, 判断一个模型装不装得下、该买哪张卡、能开多少并发、优化的天花板在哪。 这些数字在真实工作里比任何一个框架的 API 都更耐用 —— 框架半年一变,带宽和字节数不会。


🔗 跨教程

这里学的 相关
反向传播要缓存激活 ML 基础 08数学原理 12
Adam 的 m、v ML 基础 09
Transformer / attention 全景导论 02
推理成本与部署 智能体工程教程
先测再优化的方法论 ML 基础 11Kaggle

👉 回到首页

打卡记录保存在你的浏览器里,首页能看到总进度