📑 本页目录(点开跳转)
19 · 投机解码
⏱ 34 分钟 | 🎁 用闲置的算力换延迟
🎯 一句话
Decode 阶段算力有 95% 在闲置(第 15 章)。 投机解码把这些闲置算力用起来:先用小模型猜几个 token,再用大模型一次性验证。 猜对了就白赚,猜错了也不亏 —— 而且输出分布和原模型完全一致。
💡 一、核心思路
⭐ 关键观察:
· 大模型验证【5 个 token】和验证【1 个 token】,耗时几乎一样
(因为都是带宽瓶颈,读一遍权重的成本一样)⭐
· 所以"多算几个"是【免费的】
流程:
① 草稿模型(小,快)自回归生成 k 个候选 token
② 目标模型(大)【一次前向】并行验证这 k 个
③ 接受第一个不匹配之前的所有 token
④ 从不匹配处继续
例(k=4):
草稿模型猜: "今天 天气 真 不错"
大模型验证: ✅ ✅ ❌
↑ 在这里分歧
→ 接受 "今天 天气"(2 个),大模型自己产出第 3 个
→ 这一步产出了 3 个 token,只花了【1 次大模型前向】⭐
🔑 为什么"验证 5 个和验证 1 个一样快": Decode 是带宽瓶颈,时间几乎全花在把权重从 HBM 读一遍上。 一次读进来,算 1 个 token 和算 5 个 token 的计算差异微不足道。 这就是投机解码的物理基础。
🎲 二、为什么输出质量不会下降
⭐ 这是投机解码最漂亮的地方:
用【推测采样(speculative sampling)】的接受-拒绝规则,
可以证明【输出分布和直接用大模型采样【完全相同】】
📐 接受-拒绝规则(想看再点)
设草稿模型给出分布 $q(x)$,目标模型给出 $p(x)$,草稿采样得到 token $x$。
- 以概率 $\min\left(1, \frac{p(x)}{q(x)}\right)$ 接受
- 若拒绝,从修正分布 $\text{norm}(\max(0, p - q))$ 重新采样
可以证明:最终得到的 token 服从 $p$,和直接从目标模型采样一模一样。
💡 直觉:草稿模型高估了某个 token($q > p$)时,按比例拒绝一部分; 拒绝后从"目标模型想要但草稿模型给得不够"的那部分分布里补采样。 两边正好抵消。
🔑 这一点非常重要: 投机解码不是近似加速,它是精确的。 不像量化那样需要评估质量损失 —— 它没有质量损失。
📊 三、加速比取决于什么
$$\text{加速比} \approx \frac{1 + \alpha + \alpha^2 + \cdots + \alpha^k}{1 + c\cdot k}$$
(α = 接受率,c = 草稿模型相对目标模型的成本比)
两个关键变量:
⭐ 接受率 α:草稿模型猜得有多准
· 草稿模型越强 → α 越高,但它自己也越慢
· 典型值:0.6 ~ 0.8
⭐ 草稿成本 c:草稿模型相对目标模型多便宜
· 通常要 ≤ 1/10 才划算
典型加速比:
· 简单/重复性文本(代码、结构化输出)→ 2-3 倍 ⭐ 最适合
· 一般对话 → 1.5-2 倍
· 高创造性、高不确定性的文本 → 1.1-1.3 倍
💡 为什么代码补全场景收益最大: 代码有大量可预测的模式(缩进、括号、常见变量名、样板代码), 草稿模型的接受率能到 0.85 以上。
🧰 四、四种实现方式
| 方式 | 草稿从哪来 | 特点 |
|---|---|---|
| 独立草稿模型 | 同系列的小模型(如 Llama-7B 配 Llama-1B) | 经典做法,要额外显存 |
| n-gram / 提示词查找 ⭐ | 从输入或已生成文本里找重复片段 | 零额外模型,对 RAG/改写/代码补全极有效 |
| Medusa | 给目标模型加几个额外的预测头 | 不需要独立模型,要微调 |
| EAGLE ⭐ | 在特征层做预测,接受率更高 | 目前效果最好的方案之一 |
⭐ n-gram 投机值得特别推荐: 它不需要任何额外模型 —— 直接从提示词里找匹配的片段当草稿。 在这些场景几乎白送: - RAG(答案大量引用检索到的原文) - 代码编辑(大部分内容不变) - 文本改写/翻译(结构相似)
# vLLM 的几种配置
llm = LLM(model="meta-llama/Llama-3.1-70B",
speculative_model="meta-llama/Llama-3.2-1B", # 独立草稿
num_speculative_tokens=5)
llm = LLM(model="...", # ⭐ n-gram,零成本
speculative_model="[ngram]",
num_speculative_tokens=4,
ngram_prompt_lookup_max=4)
🌳 Medusa 和 EAGLE:不要独立模型的两条路
上面表格里这两个各只有一行,但它们值得多说两句 —— 因为它们回答的是同一个问题:怎么让"草稿成本 c"接近零,同时把接受率 α 拉高。
Medusa:给目标模型加几个预测头
在目标模型的最后一层 hidden 上,接【几个额外的线性头】(典型 4-5 个)
第 i 个头直接预测"再往后数第 i 个 token"
⭐ 一次前向就同时吐出 k 个候选 —— 草稿【不需要自回归】
→ 草稿成本几乎为零(只多几个小矩阵乘)
⚠️ 代价在于这些头彼此独立预测:第 3 个头不知道第 1、2 个头猜了什么,越往后越不准。 解法是每个头取 top-k 组成一棵候选树,用树注意力(tree attention)一次验完整棵树 —— 把所有节点拼成一个序列,配一个特制 mask 让每个节点只看得见自己的祖先。
⭐ 这是本章第一节那条物理基础的自然推广: "验证 5 个和验证 1 个一样快"→ "验证一棵树和验证一条链也差不多快"。 既然多算是免费的,那就别只猜一条路。 ⚠️ 但树不能无限大 —— 树一大 attention 的计算量就不可忽略,而且候选之间高度重复。
EAGLE:把自回归挪到特征层
EAGLE 的观察是:token 层面难猜,特征层面好猜。
❌ 普通草稿模型:在【token 空间】里自回归
token 是 hidden 特征【采样之后】的结果 —— 信息已经丢了一大截
✅ EAGLE:在目标模型的【特征(hidden state)序列】上自回归
一个很轻的单层解码器,输入是
[上一步的特征, 上一步【真正采样出来】的 token 的 embedding]
预测下一个特征,再借目标模型【自己的 LM head】把特征变回 token 分布
⭐ 接受率更高的两个原因:
① 特征比 token 信息量大(token 是特征塌缩之后的结果);
② 把 [真正采样出的 token] 一起喂进去,等于把"采样带来的不确定性"显式补回去 ——
草稿模型不用再去猜"上一步到底采样出了哪个"。
| 独立草稿模型 | Medusa | EAGLE ⭐ | |
|---|---|---|---|
| 草稿成本 c | 一份小模型 × k 步,最贵 | ≈ 0(一次前向出 k 个) | 很小(轻量解码器 × k 步) |
| 接受率 α | 取决于两个模型有多像 | 偏低(头之间互相不知道) | 最高 ⭐ |
| 要不要训练 | ❌ 现成小模型就行 ⭐ | ✅ 要训那几个头(微调级) | ✅ 要训那个解码器(微调级) |
| 额外显存 | 一整个小模型 | 几个头,很小 | 一个小解码器,很小 |
⚠️ 别去背"EAGLE 能到百分之多少接受率"这种数字 —— 它随模型、任务、树形变化很大。 要记的是这张表的结构:
独立模型 = 不用训但最贵、Medusa = 便宜但猜得糙、EAGLE = 用特征层换接受率。 ⭐ 而且它们都逃不掉第五节那条限制:草稿再便宜,高并发下算力已经用满,整体仍是负收益。
⚠️ 五、什么时候【不该】用
⚠️ 投机解码是【用算力换延迟】——
它在算力闲置时白赚,在算力紧张时【反而更慢】
❌ 高并发场景:
batch 大的时候,算力已经被用满了(第 15 章那条曲线)
→ 投机解码抢不到闲置算力,验证的开销变成纯损失
→ 吞吐【下降】💀
✅ 适合:
· 低并发、低延迟要求(代码补全、单用户交互)
· 输出高度可预测(RAG、改写、结构化生成)
| 场景 | 建议 |
|---|---|
| 单用户 / 低并发 | ✅ 开,收益明显 |
| 高吞吐批量服务 | ❌ 别开,会拖慢 ⭐ |
| 代码补全 | ✅ 强烈推荐(接受率高 + 延迟敏感) |
| RAG 问答 | ✅ 用 n-gram 投机,零成本 ⭐ |
🔑 一句话判断: 看你的 GPU 算力利用率。低(<20%)就开,高就别开。 这也再次印证了第 1 章那句 —— 每个优化都是一笔交易,要知道它拿什么换的。
🔗 和站内其他章的关系
| 相关的地方 | 这里的位置 |
|---|---|
| 第 15 章 Decode 算力闲置 95% | 投机解码的物理基础 ⭐ |
| 第 15 章 吞吐 vs 延迟权衡 | 投机解码站在延迟这边 |
| 第 1 章 每个优化都是交易 | 本章是最好的例证 ⭐ |
| 第 17 章 批处理 | 两者会互相冲突 |
| 《大模型全景导论》06 推理优化 武器三:投机解码 | 那边给"什么时候用",本章给接受-拒绝规则和加速比公式 ⭐ |
| 《智能体工程教程》11 检索与 RAG 检索结果塞进提示词 | 这正是 n-gram 投机零成本白赚的场景 —— 答案大量复用提示词里已有的片段 ⭐ |
✅ 检查点
- 投机解码的物理基础是什么?为什么"验证 5 个和 1 个一样快"?
- 流程的四步是什么?
- 为什么输出质量不会下降?这和量化有什么本质区别?
- 加速比取决于哪两个变量?典型的接受率是多少?
- 为什么代码补全场景收益最大?
- n-gram 投机的思路是什么?它在哪三个场景几乎白送?
- Medusa 的草稿成本为什么接近零?它的弱点是什么?树注意力怎么补救?
- EAGLE 为什么接受率更高?它把自回归挪到了哪一层?
- 什么时候不该用投机解码?为什么?
- 一句话的判断标准是什么?
👀 答案
- Decode 阶段算力有 95% 闲置。因为 Decode 是带宽瓶颈,时间几乎全花在把权重从 HBM 读一遍上,一次读进来算 1 个还是 5 个 token 的计算差异微不足道。
- ①草稿模型自回归生成 k 个候选 ②目标模型一次前向并行验证 ③接受第一个不匹配之前的所有 token ④从不匹配处继续。
- 因为用推测采样的接受-拒绝规则(以 min(1, p/q) 接受,拒绝后从 norm(max(0,p−q)) 补采样),可证明输出分布和直接用大模型采样完全相同。本质区别:量化是近似加速需要评估质量损失,投机解码是精确的、没有质量损失。
- 接受率 α(草稿猜得多准,典型 0.6-0.8)和草稿成本 c(通常要 ≤1/10 才划算)。
- 因为代码有大量可预测的模式(缩进、括号、常见变量名、样板代码),接受率能到 0.85 以上。
- 不用任何额外模型,直接从输入或已生成文本里找重复片段当草稿。三个场景:RAG(答案大量引用检索原文)、代码编辑(大部分内容不变)、文本改写/翻译(结构相似)。
- 因为它在目标模型最后一层 hidden 上接几个额外的线性头,第 i 个头直接预测"再往后第 i 个 token"——一次前向就吐出 k 个候选,草稿不用自回归。弱点:这些头彼此独立,第 3 个头不知道前两个猜了什么,越往后越不准。补救:每头取 top-k 组成候选树,用树注意力(拼成一个序列 + 特制 mask 让每个节点只看得见祖先)一次前向验完所有路径——这是"验证 5 个和 1 个一样快"的推广:验证一棵树和一条链也差不多快。
- 因为 token 是 hidden 特征采样之后的结果,信息已经丢了一大截。EAGLE 把自回归挪到特征(hidden state)层:一个轻量解码器,输入
[上一步的特征, 上一步真正采样出的 token 的 embedding],预测下一个特征,再借目标模型自己的 LM head 变回 token 分布。更准的两个原因:①特征比 token 信息量大 ②把真正采样出的 token 喂进去,等于把采样的不确定性显式补回去。 - 高并发场景。batch 大时算力已被用满,投机解码抢不到闲置算力,验证开销变成纯损失,吞吐反而下降。
- 看 GPU 算力利用率——低(<20%)就开,高就别开。
🛑 可以停在这里
⚡ 走神救援
⭐物理基础:Decode 阶段算力有 95% 闲置,而大模型验证 5 个 token 和验证 1 个几乎一样快(都是带宽瓶颈,读一遍权重的成本相同)→ "多算几个"是免费的。流程:小草稿模型猜 k 个 → 大模型一次前向并行验证 → 接受第一个不匹配之前的全部 → 从分歧处继续。⭐⭐输出质量不会下降——用推测采样的接受-拒绝规则(以 min(1,p/q) 接受,拒绝后从 norm(max(0,p−q)) 补采样)可证明输出分布和直接用大模型采样完全相同;⭐这和量化有本质区别:量化是近似加速要评估质量损失,投机解码是精确的。加速比取决于接受率 α(典型 0.6-0.8)和草稿成本 c(要 ≤1/10);典型收益:代码等结构化文本 2-3 倍(接受率能到 0.85,因为缩进/括号/样板代码可预测)、一般对话 1.5-2 倍、高创造性 1.1-1.3 倍。四种实现:独立草稿模型、⭐n-gram/提示词查找(零额外模型,直接从输入里找重复片段,在 RAG / 代码编辑 / 改写翻译 三个场景几乎白送)、Medusa、EAGLE。🌳后两条路解决的是同一个问题:让草稿成本 c 接近零同时把 α 拉高——⭐Medusa 在最后一层 hidden 上接几个额外的线性头,第 i 个头直接预测再往后第 i 个 token,一次前向就吐出 k 个候选、草稿不用自回归所以 c≈0;⚠️弱点是这些头彼此独立、越往后越不准 → 补救是每头取 top-k 组成候选树 + 树注意力(特制 mask 让每个节点只看得见祖先)一次验完所有路径,⭐这是"验证 5 个和 1 个一样快"的推广:验证一棵树和验证一条链也差不多快。⭐EAGLE 的观察是 token 层难猜、特征层好猜(token 是特征采样后的结果,信息丢了一大截)→ 它在目标模型的 hidden 特征序列上自回归,输入
[上一步特征, 上一步真正采样出的 token 的 embedding],再借目标模型自己的 LM head 变回 token 分布 → 接受率最高。⚠️别背"EAGLE 接受率百分之多少"这种数字,记表的结构:独立模型=不用训但最贵、Medusa=便宜但猜得糙、EAGLE=用特征层换接受率。⚠️⭐什么时候别用:高并发——batch 大时算力已被用满,投机抢不到闲置算力,验证开销变纯损失,吞吐反而下降。⭐一句话判断:看 GPU 算力利用率,低于 20% 就开,高就别开——再次印证"每个优化都是一笔交易"。
下一节 👉 20-推理服务化.md