推理
对应课程 Lecture 10:Inference(Percy)
训练是“一次性大工程”,推理却是每天发生亿万次的持续成本。这一讲拆解语言模型推理的机制与优化。
自回归解码的两个阶段
生成一个长度为
预填充(prefill)
把用户的提示(prompt)一次性喂进模型,并行计算所有位置的 KV。这是大批次矩阵乘法,计算受限,延迟约等于一次大前向。
解码(decode)
之后每次只生成一个 token:拿最新 token 的 Q,与缓存里全部历史 K、V 算注意力,输出下一个 token,再把它的 KV 追加进缓存。
关键点:每一步都要把全部权重和全部 KV 缓存从显存读一遍,却只做“一列”的计算——运算强度极低,是典型的带宽受限。这就是为什么:
- 解码速度 ≈ 显存带宽 ÷ 需要读的字节数;
- 7B 模型(bf16 权重 14GB)在 3TB/s 带宽上,单流解码上限约 200 token/s;
- 量化、GQA(减少 KV)、批处理(摊薄权重读取)都直指这个瓶颈。
KV 缓存:推理的显存大头
缓存大小 =
例:8B 模型(32 层、8 个 KV 头、128 维、fp16)在 32K 上下文、单请求下,KV 缓存约 4GB——和权重同量级。上下文越长、并发越多,缓存越占主导。这就是为什么 GQA(MQA)几乎是现代标配:KV 头从 32 减到 8,缓存直接缩 4 倍。
批处理:把带宽摊薄
单流解码浪费:读一遍权重只算一个 token。批处理(batching) 让
- 权重搬运成本不变,KV 缓存随
线性增长; - 总吞吐近似
(直到显存或算力饱和)。
连续调度
静态批处理的问题:批次里最长的请求拖住所有人(短请求干等)。连续批处理(continuous batching,如 vLLM) 在每步动态换入/换出请求:
- 某请求生成完毕 → 立刻腾出位置,新请求加入;
- 配合 PagedAttention(把 KV 缓存像操作系统分页一样按块管理,消除碎片),显存利用率大幅提升。
这套“操作系统化”的调度是现代推理引擎(vLLM、SGLang、TensorRT-LLM)吞吐优势的来源。
推理并行与投机解码
推理侧的并行
训练的并行策略在推理里换了个性格:
- TP 仍然常用(权重切分),但通信开销在带宽受限的解码阶段占比更高;
- PP 可以缓解显存,但增加延迟;
- 聚焦带宽:权重切得越散,每卡读的越少,单步越快——切分本质是在借别人的带宽。
投机解码(speculative decoding)
带宽受限意味着单步“算力过剩”。投机解码利用这一点:
- 一个便宜的小模型(draft model)快速猜出
个后续 token; - 大模型一次并行验证这
个猜测(一次 prefill 式计算); - 从左到右接受所有与目标分布一致的 token,第一个不一致处拒绝并回退。
数学上,通过精心设计的接受/拒绝规则,输出分布与目标大模型完全相同——无损加速。速度增益 = 被接受的 token 数,一般 2~3 倍。变体:自投机(同一模型的多层提前退出)、树形投机(多个候选分支)。
其他降本手段
| 手段 | 原理 | 代价 |
|---|---|---|
| 量化(推理) | 权重/缓存用 8bit 甚至 4bit 存储 | 需要校准,极端量化有质量损失 |
| KV 缓存压缩 | 低精度缓存、缓存淘汰(H2O)、跨层共享 | 长上下文质量需仔细验证 |
| 前缀缓存 | 相同系统提示/文档只算一次 KV | 管理缓存命中的复杂性 |
| 短化思考链 | 减少“思考” token 的生成量 | 影响推理类任务的质量 |
推理成本的直觉
一次推理的成本 ≈ 权重字节 × 读取次数(受批处理摊薄)+ KV 字节 × 访问次数。所有优化都在压这三项:权重变小(量化)、读的次数变少(批处理/投机解码)、KV 变小(GQA/压缩/前缀缓存)。
小结
- 推理分 prefill(计算受限)与 decode(带宽受限)两阶段,decode 是成本大头。
- KV 缓存是显存大头,GQA 是第一道防线;连续批处理 + 分页管理大幅提升吞吐。
- 投机解码用小模型草稿 + 大模型并行验证,做到无损加速。
- 推理工程与训练共享 roofline 思维,但瓶颈从算力转向了显存带宽。