🏠 总目录📚 本教程 推理≠训练 ← →
📑 本页目录(点开跳转)

15 · 推理和训练是两回事

⏱ 28 分钟 | ⭐ 把训练经验套到推理上是最贵的错误


🎯 一句话

训练是算力瓶颈,推理(解码阶段)是带宽瓶颈 —— 两者的瓶颈完全相反。 这意味着几乎所有训练侧的优化直觉,到推理侧都要反过来想。


🔀 一、一次推理请求分成两个完全不同的阶段

用户输入 "请解释一下量子纠缠"(假设 10 个 token),模型输出 500 个 token —— 这一次请求会被拆成两个性质完全不同的阶段:

Prefill(预填充)一次性处理全部 10 个输入 token
并行度高 ✅
【算力瓶颈】
占时间 ~10%
→
Decode(解码)一个一个地生成 500 个 token,每次只处理 1 个
并行度 = 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 这一侧

✅ 检查点

  1. 一次推理请求分成哪两个阶段?各自的瓶颈是什么?
  2. Decode 阶段的算术强度是多少?为什么这么低?
  3. 单请求解码速度的物理上限公式是什么?7B 在 A100 上是多少?
  4. 为什么"换更强的卡"对解码速度提升有限?
  5. 批处理为什么能提高吞吐?它的天花板是什么?
  6. TTFT 和 TPOT 分别由什么决定?端到端延迟里哪个占主导?
  7. 四种产品形态对延迟指标的要求有什么不同?
  8. 为什么 Decode 阶段 MFU 只有 1-5% 是正常的?该看什么指标?
  9. 推理优化的第一步是什么?为什么第 ⑦ 条常被忽略?
👀 答案
  1. Prefill(一次性处理全部输入,算力瓶颈,占时间 ~10%)和 Decode(一个一个生成,带宽瓶颈,占时间 ~90%)。
  2. 约 2。因为生成 1 个 token 要把全部模型权重从 HBM 读进来,却只和一个长度为 1 的向量相乘——读了 14GB 只做了很少计算,离平衡点 156 差 78 倍。
  3. 显存带宽 ÷ 模型大小。7B BF16(14GB)在 A100(2TB/s)≈ 143 tokens/秒。
  4. 因为上限只和带宽有关,和算力无关。H100 算力是 A100 的 3 倍但带宽只有 1.7 倍,解码速度也只快 1.7 倍。
  5. 因为读一遍权重可以同时服务多个请求,权重读取成本被摊薄。天花板是 KV Cache 显存——batch 越大 KV Cache 越多(7B/seq2048/batch32 就要 34GB),装不下就上不去。
  6. TTFT 由 Prefill 速度 + 排队时间决定,TPOT 由 Decode 速度(带宽)决定。端到端 = TTFT + TPOT×输出长度,TPOT 占主导(例子里占 98%)。
  7. 聊天/流式:TTFT 要低、TPOT 跟上阅读速度即可;批量离线:只关心吞吐;代码补全:TTFT 极度敏感(>200ms 就放弃);Agent/长思考:TPOT 是决定性的。
  8. 因为带宽瓶颈下算力本来就用不满,这是物理决定的不是配置错误。该看带宽利用率和吞吐,不是 MFU。
  9. 第一步:用专门的推理引擎(vLLM/SGLang/TensorRT-LLM),别用 HF 的 generate() 上生产——光这一步常常 5-10 倍。第 ⑦ 条前缀缓存常被忽略是因为它看起来简单,但如果所有请求都带同一个长系统提示词,它能把 Prefill 成本降到接近零。

🛑 可以停在这里

⚡ 走神救援

⭐⭐ 训练是算力瓶颈,而解码是带宽瓶颈——完全相反。

一次请求分两段:Prefill 一次处理全部输入、是矩阵乘矩阵、算力瓶颈、决定首字延迟;Decode 一次只出一个 token、是向量乘矩阵、算术强度极低、带宽瓶颈、占掉绝大部分时间。

💀 Decode 惨在哪:⭐ 生成一个 token 要把全部权重从显存读一遍,却只和一个长度为 1 的向量相乘。 ⭐⭐ 于是物理上限就是「显存带宽除以模型大小」,和算力完全无关——⚠️ 换一张算力翻几倍但带宽只涨一点的卡,解码就只快那一点。这解释了「换了更强的卡为什么没快多少」。

⭐ 批处理是唯一的救命稻草:读一遍权重同时服务多个请求,权重成本被摊薄。⚠️ 但单请求延迟会变差,⭐ 而天花板是 KV Cache 的显存——所以 KV Cache 管理才是推理吞吐真正的瓶颈。

⭐ 四个指标里 TPOT 通常占端到端时间的绝大部分——⚠️ 所以优化首字延迟意义不大,除非是代码补全那种对它极度敏感的场景。

⭐ 训练直觉需要翻译的几条:看带宽不看算力;⭐⭐ 解码的算力利用率只有个位数百分比是正常的——那是物理决定的,别恐慌,该看的是带宽利用率和吞吐;训练那套省显存的手段这里都不适用;推理没有收敛问题,所以 batch 越大越好;量化在这一侧收益大得多。

⭐ 优化顺序的第一条最值钱:先换专门的推理引擎,别拿训练框架的生成接口上生产——光这一步常常就是几倍。 最后一条是前缀缓存:同一个长系统提示词只算一次,能把 Prefill 成本压到接近零。

下一节 👉 16-KV-Cache.md ⭐

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