🏠 总目录📚 本教程 投机解码
📑 本页目录(点开跳转)

19 · 投机解码

34 分钟 | 🎁 用闲置的算力换延迟


🎯 一句话

Decode 阶段算力有 95% 在闲置(第 15 章)。 投机解码把这些闲置算力用起来:先用小模型猜几个 token,再用大模型一次性验证。 猜对了就白赚,猜错了也不亏 —— 而且输出分布和原模型完全一致。

小模型:快,一次猜 4 个t1t2t3t4大模型:慢,但一次前向能验完全部从这里开始不对一次前向验证全部 4 个接受 2 个+ 大模型自己出 1 个 = 这一轮产出 3 个让小模型先猜,大模型只做「批量验证」⭐ 关键:验证 4 个和生成 1 个,大模型的耗时几乎一样(都是一次前向)所以只要猜中率够高就是净赚 —— 而且输出分布和原模型【完全一致】
小模型先猜 4 个,大模型一次前向就能验完全部,接受前面对的部分。⭐ 关键在于:验证 4 个和生成 1 个,大模型的耗时几乎一样 —— 所以猜中率够高就是净赚,而且输出分布和原模型完全一致

💡 一、核心思路

   ⭐ 关键观察:
   · 大模型验证【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$。

可以证明:最终得到的 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 投机零成本白赚的场景 —— 答案大量复用提示词里已有的片段 ⭐

✅ 检查点

  1. 投机解码的物理基础是什么?为什么"验证 5 个和 1 个一样快"?
  2. 流程的四步是什么?
  3. 为什么输出质量不会下降?这和量化有什么本质区别?
  4. 加速比取决于哪两个变量?典型的接受率是多少?
  5. 为什么代码补全场景收益最大?
  6. n-gram 投机的思路是什么?它在哪三个场景几乎白送?
  7. Medusa 的草稿成本为什么接近零?它的弱点是什么?树注意力怎么补救?
  8. EAGLE 为什么接受率更高?它把自回归挪到了哪一层?
  9. 什么时候不该用投机解码?为什么?
  10. 一句话的判断标准是什么?
👀 答案
  1. Decode 阶段算力有 95% 闲置。因为 Decode 是带宽瓶颈,时间几乎全花在把权重从 HBM 读一遍上,一次读进来算 1 个还是 5 个 token 的计算差异微不足道
  2. ①草稿模型自回归生成 k 个候选 ②目标模型一次前向并行验证 ③接受第一个不匹配之前的所有 token ④从不匹配处继续。
  3. 因为用推测采样的接受-拒绝规则(以 min(1, p/q) 接受,拒绝后从 norm(max(0,p−q)) 补采样),可证明输出分布和直接用大模型采样完全相同。本质区别:量化是近似加速需要评估质量损失,投机解码是精确的、没有质量损失
  4. 接受率 α(草稿猜得多准,典型 0.6-0.8)和草稿成本 c(通常要 ≤1/10 才划算)。
  5. 因为代码有大量可预测的模式(缩进、括号、常见变量名、样板代码),接受率能到 0.85 以上
  6. 不用任何额外模型,直接从输入或已生成文本里找重复片段当草稿。三个场景:RAG(答案大量引用检索原文)、代码编辑(大部分内容不变)、文本改写/翻译(结构相似)。
  7. 因为它在目标模型最后一层 hidden 上接几个额外的线性头,第 i 个头直接预测"再往后第 i 个 token"——一次前向就吐出 k 个候选,草稿不用自回归。弱点:这些头彼此独立,第 3 个头不知道前两个猜了什么,越往后越不准。补救:每头取 top-k 组成候选树,用树注意力(拼成一个序列 + 特制 mask 让每个节点只看得见祖先)一次前向验完所有路径——这是"验证 5 个和 1 个一样快"的推广:验证一棵树和一条链也差不多快
  8. 因为 token 是 hidden 特征采样之后的结果,信息已经丢了一大截。EAGLE 把自回归挪到特征(hidden state)层:一个轻量解码器,输入 [上一步的特征, 上一步真正采样出的 token 的 embedding],预测下一个特征,再借目标模型自己的 LM head 变回 token 分布。更准的两个原因:①特征比 token 信息量大 ②把真正采样出的 token 喂进去,等于把采样的不确定性显式补回去
  9. 高并发场景。batch 大时算力已被用满,投机解码抢不到闲置算力,验证开销变成纯损失,吞吐反而下降
  10. 看 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 / 代码编辑 / 改写翻译 三个场景几乎白送)、MedusaEAGLE。🌳后两条路解决的是同一个问题:让草稿成本 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

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