投机解码
解码每生成一个 token 就要读一遍全部权重——访存受限,带宽是唯一瓶颈(见 Roofline)。但有一个被浪费的事实:大模型一次前向的算力只用了不到 1%。投机解码(speculative decoding)利用这个浪费:用便宜的小模型(或草稿机制)连猜几个 token,大模型一次前向并行验证——验证一步出多个 token,吞吐提升 2–3 倍。本章讲清楚它为什么成立、怎么实现、以及什么时候它没用。
核心思想:猜与验
Section titled “核心思想:猜与验”标准解码:每步大模型一次前向,出一个 token(访存受限,算力浪费 ~99%)。
投机解码:两阶段循环:
草稿阶段:小模型(如 1B)快速连猜 k 个 token ← 便宜,访存量小验证阶段:大模型一次前向,并行验证这 k 个 token ← 一次前向算 k+1 个位置 (从左到右逐个接受,第一个不匹配处截断)关键在验证阶段:大模型一次前向并行算 k+1 个位置(teacher forcing 的天然性质——已知前缀时,一次前向能同时算出每个位置的分布)。从左到右接受:与小模型猜测一致的接受,第一个不一致的截断,用大模型在该位置的采样补上。
数学保证:接受准则按严格数学设计(接受概率 ,拒绝时按残差分布重采样),输出分布与大模型独立解码完全相同——投机解码是无损的,不改变输出分布。
速度账:为什么快
Section titled “速度账:为什么快”每轮循环的期望产出与时间:
- 产出:期望接受 比例,每轮平均出 个 token
- 时间:小模型 k 次前向(快)+ 大模型 1 次前向(与单 token 解码同价,这是关键)
以接受率 α=0.7、k=4、小模型成本为大模型 10% 计:每轮期望出 ~2.9 个 token,时间 1.4 个"大模型步"——约 2 倍加速。两个参数的直觉:
- 接受率 α 是生命线:小模型与大模型越"像"(同系列、同 tokenizer、蒸馏过),接受率越高。α<0.5 时加速比跌到 1.3 以下
- k 不是越大越好:k 太大,验证批次里被截断的浪费增多,且小模型的猜测时间线性涨
草稿来源:三种方案
Section titled “草稿来源:三种方案”| 方案 | 草稿是什么 | 优点 | 缺点 |
|---|---|---|---|
| 独立小模型 | 同系列小模型(如 70B+1B) | 简单,即插即用 | 接受率受小模型质量限制 |
| 自投机/EAGLE | 大模型自己的浅层草稿头 | 接受率高(草稿头与大模型共训) | 要训练草稿头 |
| n-gram/查找表 | 前缀 n-gram 匹配 | 零成本,代码/重复文本强 | 自由文本弱 |
EAGLE 类(大模型自身的草稿头)是当前的主流:接受率 0.8+,加速比 2.5–3.5。
与批处理的冲突:什么时候没用
Section titled “与批处理的冲突:什么时候没用”投机解码与高并发批处理互相冲突——这是工程上最重要的认知:
- 投机解码的收益来自"单请求的算力浪费"(batch 小时,算力空着,验证白赚)
- batch 大时(如 64+ 并发),decode 已被批处理抬到接近计算受限(见连续批处理),验证阶段一次要算 batch × k 个位置——算力不再富裕,投机解码反而添乱
| 场景 | 建议 |
|---|---|
| 单请求/低并发,延迟敏感 | ✅ 投机解码,延迟降 2–3 倍 |
| 高并发批处理 | ❌ 关掉,批处理已吃满算力 |
| 中等并发 | 实测,存在一个临界 batch(典型 8–32) |
| 本地单用户部署(个人/Agent 场景) | ✅ 最典型的收益场景 |
判断标准:decode 阶段的算术强度。batch 小 → 强度 ~1,有巨大的验证空间;batch 大 → 强度已高,没空间了。
- vLLM/SGLang 原生支持:配
speculative_model与num_speculative_tokens(k),见服务框架 - k 的选择:2–5 起步扫一遍,与接受率联动(α 高时 k 可以大)
- tokenizer 必须一致:草稿与大模型的 tokenizer 不同则无法对齐(独立小模型方案的隐藏约束)
- 监控:接受率(per-step accepted tokens)是生命线指标,接受率跌破 0.5 时关掉投机
- 与 KV 配合:验证阶段会为被拒的猜测留 KV 页,投机解码下 KV 管理要多一档余量(见 KV Cache)
- 解码访存受限、算力浪费 ~99%:投机解码用小模型猜、大模型并行验证,把浪费换成吞吐。
- 数学无损:输出分布与独立解码完全相同;加速比 ≈ 每轮期望产出 ÷ (1 + k·小模型成本比)。
- 接受率 α 是生命线:同系列/蒸馏小模型或 EAGLE 类草稿头(α 0.8+)是主流。
- 与批处理冲突:低并发延迟敏感时开,高并发批处理时关——看 decode 的算术强度。
- k 不是越大越好;接受率跌破 0.5 就该关。
- 连续批处理与调度 — 上一章:批处理与投机的冲突
- 算术强度与 Roofline — 一切收益的数学根源
- 量化:权重、激活与 KV cache — 另一条延迟优化路线
- 分布式推理:Prefill/Decode 分离 — 下一章