Skip to content

推理

对应课程 Lecture 10:Inference(Percy)

训练是“一次性大工程”,推理却是每天发生亿万次的持续成本。这一讲拆解语言模型推理的机制与优化。

自回归解码的两个阶段

生成一个长度为 T 的回答,分两个阶段:

预填充(prefill)

把用户的提示(prompt)一次性喂进模型,​并行计算所有位置的 KV。这是大批次矩阵乘法,​计算受限​,延迟约等于一次大前向。

解码(decode)

之后每次只生成一个 token​:拿最新 token 的 Q,与缓存里全部历史 K、V 算注意力,输出下一个 token,再把它的 KV 追加进缓存。

关键点:每一步都要把全部权重和全部 KV 缓存从显存读一遍​,却只做“一列”的计算——运算强度极低,是典型的带宽受限​。这就是为什么:

  • 解码速度 ≈ 显存带宽 ÷ 需要读的字节数;
  • 7B 模型(bf16 权重 14GB)在 3TB/s 带宽上,单流解码上限约 200 token/s;
  • 量化、GQA(减少 KV)、批处理(摊薄权重读取)都直指这个瓶颈。

KV 缓存:推理的显存大头

缓存大小 = 2×nlayers×nkvheads×dhead×T×精度字节×batch

例:8B 模型(32 层、8 个 KV 头、128 维、fp16)在 32K 上下文、单请求下,KV 缓存约 4GB——和权重同量级​。上下文越长、并发越多,缓存越占主导。这就是为什么 GQA(MQA)几乎是现代标配:KV 头从 32 减到 8,缓存直接缩 4 倍。

批处理:把带宽摊薄

单流解码浪费:读一遍权重只算一个 token。​批处理(batching)B 个请求共享同一次权重读取:

  • 权重搬运成本不变,KV 缓存随 B 线性增长;
  • 总吞吐近似 ×B(直到显存或算力饱和)。

连续调度

静态批处理的问题:批次里最长的请求拖住所有人(短请求干等)。​连续批处理(continuous batching,如 vLLM) 在每步动态换入/换出请求:

  • 某请求生成完毕 → 立刻腾出位置,新请求加入;
  • 配合 PagedAttention​(把 KV 缓存像操作系统分页一样按块管理,消除碎片),显存利用率大幅提升。

这套“操作系统化”的调度是现代推理引擎(vLLM、SGLang、TensorRT-LLM)吞吐优势的来源。

推理并行与投机解码

推理侧的并行

训练的并行策略在推理里换了个性格:

  • TP 仍然常用(权重切分),但通信开销在带宽受限的解码阶段占比更高;
  • PP 可以缓解显存,但增加延迟;
  • 聚焦带宽​:权重切得越散,每卡读的越少,单步越快——切分本质是在借别人的带宽​。

投机解码(speculative decoding)

带宽受限意味着单步“算力过剩”。​投机解码利用这一点:

  1. 一个便宜的小模型(draft model)快速猜出 k 个后续 token;
  2. 大模型一次并行验证k 个猜测(一次 prefill 式计算);
  3. 从左到右接受所有与目标分布一致的 token,第一个不一致处拒绝并回退。

数学上,通过精心设计的接受/拒绝规则,​输出分布与目标大模型完全相同——无损加速。速度增益 = 被接受的 token 数,一般 2~3 倍。变体:自投机(同一模型的多层提前退出)、树形投机(多个候选分支)。

其他降本手段

手段原理代价
量化(推理)权重/缓存用 8bit 甚至 4bit 存储需要校准,极端量化有质量损失
KV 缓存压缩低精度缓存、缓存淘汰(H2O)、跨层共享长上下文质量需仔细验证
前缀缓存相同系统提示/文档只算一次 KV管理缓存命中的复杂性
短化思考链减少“思考” token 的生成量影响推理类任务的质量

推理成本的直觉

一次推理的成本 ≈ 权重字节 × 读取次数(受批处理摊薄)+ KV 字节 × 访问次数。所有优化都在压这三项:​权重变小(量化)、读的次数变少(批处理/投机解码)、KV 变小(GQA/压缩/前缀缓存)​。

小结

  • 推理分 prefill(计算受限)与 decode(带宽受限)两阶段,decode 是成本大头。
  • KV 缓存是显存大头,GQA 是第一道防线;连续批处理 + 分页管理大幅提升吞吐。
  • 投机解码用小模型草稿 + 大模型并行验证,做到无损加速。
  • 推理工程与训练共享 roofline 思维,但瓶颈从算力转向了显存带宽。
最近更新