📑 本页目录(点开跳转)
15 · 推理和训练是两回事
⏱ 28 分钟 | ⭐⭐ 把训练经验套到推理上是最贵的错误
🎯 一句话
训练是算力瓶颈,推理(解码阶段)是带宽瓶颈 —— 两者的瓶颈完全相反。 这意味着几乎所有训练侧的优化直觉,到推理侧都要反过来想。
🔀 一、一次推理请求分成两个完全不同的阶段
用户输入 "请解释一下量子纠缠"(假设 10 个 token),模型输出 500 个 token —— 这一次请求会被拆成两个性质完全不同的阶段:
并行度高 ✅
【算力瓶颈】
占时间 ~10%
并行度 = 1 ⚠️
【带宽瓶颈】⭐
占时间 ~90% ⭐
| Prefill | Decode | |
|---|---|---|
| 每步处理的 token | 全部输入(几百~几万) | 1 个 |
| 矩阵乘的形状 | 矩阵 × 矩阵 | 向量 × 矩阵 ⭐ |
| 算术强度 | 高(几百) | ~2 💀 |
| 瓶颈 | 算力 | 显存带宽 ⭐ |
| 决定的指标 | TTFT(首字延迟) | TPOT(每字延迟) |
| 优化方向 | 更强的算力、并行 | 减少数据搬运 |
🔑 这张表是这一章的全部。 Prefill 和 Decode 是两个性质完全不同的工作负载,跑在同一个模型上。 很多推理系统的设计(甚至硬件选型)都源于这个分裂。
💀 二、Decode 为什么这么惨
生成 1 个 token 要做什么:
① 把【全部模型权重】从 HBM 读进来
② 和一个【长度为 1】的向量相乘
③ 丢掉
⭐ 读了 14GB 的权重(7B BF16),只做了很少的计算
→ 算术强度 ≈ 2
→ 离 A100 的平衡点 156 差了【78 倍】💀
理论上限(第 4 章那个心算公式):
$$\text{最快解码速度} = \frac{\text{显存带宽}}{\text{模型大小}}$$
7B BF16(14GB)在 A100(2TB/s):
2000 / 14 ≈ 143 tokens/秒 ← 单请求的物理上限 ⭐
⚠️ 注意:这个上限和 GPU 的算力【完全无关】
换 H100(989 TFLOPS,是 A100 的 3 倍算力)
→ 但带宽只有 3.35TB/s(1.7 倍)
→ 解码速度也只提升 1.7 倍,不是 3 倍
🔑 这解释了一个常见的困惑: "为什么我换了更强的卡,生成速度没快多少?" 因为你买的是算力,而你的瓶颈是带宽。
⭐ 三、批处理:Decode 唯一的救命稻草
⭐ 关键洞察:读一遍权重,可以【同时服务多个请求】
batch=1: 读 14GB → 生成 1 个 token → 效率 1/14GB
batch=32: 读 14GB → 生成 32 个 token → 效率 32/14GB ⭐ 32 倍!
→ 权重的读取成本被【摊薄】了
吞吐 vs batch size(7B 模型,A100)示意:
batch=1 → ~140 tok/s (单请求也是 140)
batch=8 → ~1000 tok/s (单请求 ~125,略降)
batch=32 → ~3500 tok/s (单请求 ~110)
batch=128 → ~8000 tok/s (单请求 ~62,明显降)⚠️
batch→∞ → 受算力限制,不再增长
🔑 两个关键结论: ① 批处理几乎是免费的吞吐 —— 这是推理优化的第一原则 ② 但单请求延迟会随 batch 增大而变差 —— 吞吐和延迟的经典权衡
🔗 第 17 章讲怎么在动态到达的请求上做批处理, 那才是真正的难点。
⚠️ 但批处理有个天花板:KV Cache
batch 越大,KV Cache 占的显存越多
7B 模型,seq=2048,batch=32:
KV Cache ≈ 2 × 32层 × 2048 × 4096 × 2字节 × 32 = 34 GB ⭐
→ 显存装不下 → batch 上不去 → 吞吐上不去
⭐ 所以【KV Cache 管理才是推理吞吐的真正瓶颈】(第 16、17 章)
📊 四、推理的四个核心指标
| 指标 | 含义 | 由什么决定 |
|---|---|---|
| TTFT | Time To First Token(首字延迟) | Prefill 速度 + 排队时间 |
| TPOT | Time Per Output Token(每字延迟) | Decode 速度(带宽)⭐ |
| 吞吐 | 总 tokens/秒 | batch size(受 KV Cache 限制) |
| 成本 | 每百万 token 的钱 | 吞吐 ÷ GPU 单价 |
端到端延迟 = TTFT + TPOT × 输出长度
例:TTFT=200ms, TPOT=25ms, 输出 500 token
→ 200 + 25×500 = 12.7 秒
⭐ 注意:TPOT 占了 98% —— 优化 TTFT 意义不大
⭐ 不同产品对这两个指标的要求完全不同: - 聊天/流式输出 → TTFT 要低(用户要立刻看到字),TPOT 要跟得上阅读速度(~50ms 够) - 批量处理/离线 → 只关心吞吐,两个延迟都无所谓 - 代码补全 → TTFT 极度敏感(超过 200ms 用户就放弃了) - Agent / 长思考 → 输出很长,TPOT 是决定性的
🔄 五、训练直觉到推理的翻译表
| 训练侧的直觉 | 推理侧的实际情况 |
|---|---|
| "换算力更强的卡" | ⚠️ 看带宽,不是算力 ⭐ |
| "MFU 45% 算不错" | ⚠️ Decode 阶段 MFU 通常只有 1-5%,这是正常的 ⭐ |
| "梯度检查点省显存" | ❌ 推理没有反向,不适用 |
| "ZeRO 切优化器状态" | ❌ 推理没有优化器状态,只有权重和 KV Cache |
| "大 batch 影响收敛" | ✅ 推理没有收敛问题,batch 越大越好(受显存限) |
| "量化会掉精度" | ✅ 但推理侧收益大得多(直接提速),值得权衡 ⭐ |
| "FlashAttention 省显存" | ✅ 仍然有用,但推理的大头是 KV Cache |
💥 "Decode 的 MFU 只有 1-5%"这一条经常引起恐慌: 有人看到推理时 GPU 算力利用率极低,就以为配置错了,拼命调优。 实际上这是物理决定的 —— 带宽瓶颈下算力本来就用不满。 推理该看的指标是"带宽利用率"和"吞吐",不是 MFU。
🧭 六、推理优化的正确顺序
① 用专门的推理引擎(vLLM / SGLang / TensorRT-LLM)
→ 别用 HuggingFace 的 generate() 上生产 ⭐
→ 光这一步常常就是 5-10 倍
② 开【连续批处理】(第 17 章)
→ 吞吐再翻几倍
③ 量化权重(第 18 章)
→ 模型小一半 → 解码速度快一倍 + 能开更大 batch
④ 量化 KV Cache
→ 能开更大 batch
⑤ 张量并行(如果单卡装不下,或要降 TPOT)
⑥ 投机解码(第 19 章)—— 低延迟场景
⑦ 前缀缓存(相同的系统提示词只算一次)⭐
⭐ 第 ⑦ 条常常被忽略但收益巨大: 如果你的所有请求都带着同一个 2000 token 的系统提示词, 前缀缓存能把 Prefill 的成本降到接近零。 vLLM 的
enable_prefix_caching=True。🚧 第 ① 条留了个尾巴:这里说了「换个专门的引擎常常 5–10 倍」,却没说该换成哪个。 三个名字并排放着,你并不知道自己的场景该选谁。 👉 第 20 章 · 推理服务化开头有一张七个引擎的横评和一棵四问决策树 (单机还是集群?要不要动态加载多个 LoRA?跑在自己机器上还是 GPU 集群?延迟敏感还是吞吐优先?)。 在你按上面这个顺序动手之前,先去那里把 ① 定下来——顺序里后面六步都建立在引擎选型之上。
🔗 和站内其他章的关系
| 相关的地方 | 这里的位置 |
|---|---|
| 第 3 章 batch=1 矩阵乘算术强度 ~2 | Decode 的全部困境 ⭐ |
| 第 4 章 带宽 ÷ 模型大小 | 解码速度的物理上限 |
| 第 16 章 KV Cache | 批处理的天花板 |
| 第 17 章 连续批处理 | 动态请求下的批处理 |
| 第 18 章 量化 | 推理侧收益远大于训练侧 |
| 《大模型全景导论》06 推理优化 先理解瓶颈在哪:两个阶段 | 同一件事的一页纸版;本章补上"Decode 算力闲置 95%"背后的那个数字 ⭐ |
| 《模型上线之后》18 成本与容量 LLM 服务的成本结构 | Prefill/Decode 的拆分,就是那边"输入便宜、输出贵"的物理原因 ⭐ |
| 《智能体工程教程》16 企业落地与生产化 算账的三条口诀 | Agent 输出长、还要循环多轮 —— 它的账几乎全压在 Decode 这一侧 |
✅ 检查点
- 一次推理请求分成哪两个阶段?各自的瓶颈是什么?
- Decode 阶段的算术强度是多少?为什么这么低?
- 单请求解码速度的物理上限公式是什么?7B 在 A100 上是多少?
- 为什么"换更强的卡"对解码速度提升有限?
- 批处理为什么能提高吞吐?它的天花板是什么?
- TTFT 和 TPOT 分别由什么决定?端到端延迟里哪个占主导?
- 四种产品形态对延迟指标的要求有什么不同?
- 为什么 Decode 阶段 MFU 只有 1-5% 是正常的?该看什么指标?
- 推理优化的第一步是什么?为什么第 ⑦ 条常被忽略?
👀 答案
- Prefill(一次性处理全部输入,算力瓶颈,占时间 ~10%)和 Decode(一个一个生成,带宽瓶颈,占时间 ~90%)。
- 约 2。因为生成 1 个 token 要把全部模型权重从 HBM 读进来,却只和一个长度为 1 的向量相乘——读了 14GB 只做了很少计算,离平衡点 156 差 78 倍。
- 显存带宽 ÷ 模型大小。7B BF16(14GB)在 A100(2TB/s)≈ 143 tokens/秒。
- 因为上限只和带宽有关,和算力无关。H100 算力是 A100 的 3 倍但带宽只有 1.7 倍,解码速度也只快 1.7 倍。
- 因为读一遍权重可以同时服务多个请求,权重读取成本被摊薄。天花板是 KV Cache 显存——batch 越大 KV Cache 越多(7B/seq2048/batch32 就要 34GB),装不下就上不去。
- TTFT 由 Prefill 速度 + 排队时间决定,TPOT 由 Decode 速度(带宽)决定。端到端 = TTFT + TPOT×输出长度,TPOT 占主导(例子里占 98%)。
- 聊天/流式:TTFT 要低、TPOT 跟上阅读速度即可;批量离线:只关心吞吐;代码补全:TTFT 极度敏感(>200ms 就放弃);Agent/长思考:TPOT 是决定性的。
- 因为带宽瓶颈下算力本来就用不满,这是物理决定的不是配置错误。该看带宽利用率和吞吐,不是 MFU。
- 第一步:用专门的推理引擎(vLLM/SGLang/TensorRT-LLM),别用 HF 的
generate()上生产——光这一步常常 5-10 倍。第 ⑦ 条前缀缓存常被忽略是因为它看起来简单,但如果所有请求都带同一个长系统提示词,它能把 Prefill 成本降到接近零。
🛑 可以停在这里
⚡ 走神救援
⭐⭐训练是算力瓶颈,Decode 是带宽瓶颈——完全相反。一次请求分两阶段:Prefill(一次处理全部输入、矩阵×矩阵、算力瓶颈、占时间 10%、决定 TTFT)和 Decode(一次 1 个 token、向量×矩阵、算术强度只有 2、带宽瓶颈、占时间 90%、决定 TPOT)。💀Decode 惨在:生成 1 个 token 要把全部权重从 HBM 读一遍却只和长度为 1 的向量相乘,离平衡点差 78 倍。⭐⭐物理上限 = 显存带宽 ÷ 模型大小(7B 在 A100 ≈ 143 tok/s),⭐和算力完全无关——换 H100 算力 3 倍但带宽只 1.7 倍,解码也只快 1.7 倍(这解释了"换了更强的卡为什么没快多少")。⭐批处理是唯一救命稻草:读一遍权重同时服务多个请求,权重成本被摊薄(batch=32 效率 32 倍);但单请求延迟随 batch 变差,且天花板是 KV Cache 显存(7B/seq2048/batch32 就要 34GB)→ ⭐KV Cache 管理才是推理吞吐的真正瓶颈。四指标:TTFT / TPOT / 吞吐 / 成本;端到端 = TTFT + TPOT×输出长度,⭐TPOT 通常占 98%,优化 TTFT 意义不大(除非是代码补全那种 TTFT 极度敏感的场景)。⭐训练直觉的翻译:看带宽不是算力、Decode 的 MFU 只有 1-5% 是正常的(物理决定,别恐慌,该看带宽利用率和吞吐)、梯度检查点/ZeRO 都不适用、推理没有收敛问题所以 batch 越大越好、量化在推理侧收益大得多。优化顺序:①⭐先换专门的推理引擎(vLLM/SGLang/TRT-LLM),别用 HF generate() 上生产——光这步常 5-10 倍 ②连续批处理 ③量化权重 ④量化 KV Cache ⑤张量并行 ⑥投机解码 ⑦⭐前缀缓存(同一个长系统提示词只算一次,能把 Prefill 成本降到接近零)。
下一节 👉 16-KV-Cache.md ⭐⭐