投机采样(Speculative Decoding):草案模型、并行验证与加速原理

投机采样(Speculative Decoding)是当前 LLM 推理延迟优化的核心技术——用一个小草案模型快速生成候选 token,再用大模型一次并行验证多个候选,单步接受多个 token,显著降低自回归解码的串行延迟。

LLM 自回归解码的根本瓶颈是串行:每一步只能生成一个 token,而 Decode 阶段的计算密度极低(带宽受限)。投机采样(Speculative Decoding)换了个思路:让一个小草案模型替你「猜」后面的几个 token,大模型一次并行验证这一串——猜对了就一次接受多个 token,用「一次并行验证」换「多步串行生成」。本文把投机采样的原理、实现路径(草拟-验证、Medusa、EAGLE)、正确性保证、工程取舍与踩坑讲透。

前置:/ai-vllm-system/(连续批处理与解码)、/ai-attention-optimization/(Attention 优化与 KV Cache)、/ai-kernel-fusion-optimization/(算子融合与推理内核)、/ai-llm-inference-architecture/(推理服务架构)。

目录

1. 自回归解码的瓶颈:串行与低算力利用

先看清「为什么慢」:

自回归解码:
□ 每个 token 依赖前一个 token → 严格串行
□ Decode 阶段计算量小(读 KV Cache + 算一个 token)
  → 计算密度低,主要受「显存带宽」限制
□ 大模型的带宽受限 → 单 token 延迟高

算力利用视角:
□ Prefill(处理 prompt):计算密集,GPU 算力用满
□ Decode(生成 token):带宽受限,算力利用率 < 10%
  → 大量算力在 Decode 阶段闲置

关键矛盾:
算力闲置 vs 解码串行 → 投机采样用「并行验证」补上

为什么慢的根因:Decode 阶段「算力闲置 + 串行约束」是投机采样要解决的根本矛盾。如果能让一个步骤「同时尝试多个 token」,就用闲置算力换取了串行步数的减少。

2. 投机采样的核心思想:草拟与并行验证

投机采样的两个主角:草案模型与验证步骤:

核心流程:
1. 草案模型(小/快)快速生成 γ 个候选 token
   (γ 通常 4-8 个)
2. 大模型一次性对 γ 个候选做「并行 forward」
   → 一次前向同时算 γ 个位置的概率分布
3. 逐 token 对比:大模型的分布决定「接受哪些」
4. 接受 k 个 → 这一次「一步走了 k 步」

关键洞察:
□ γ 个候选的 forward 是「并行」的(矩阵运算)
  → 一个 token 的延迟 ≈ 一次 forward 的延迟(并行批量)
□ 如果草案猜得准(接受率高)→ 有效步长 >> 1
  → 串行步数显著减少
直觉示例:
草案模型猜了 5 个 token:A B C D E
大模型一次 forward,算出这些位置的分布
接受 4 个(A B C D)→ 这一步实际走了 4 步
→ 原本 5 次串行 decode,压缩成 1 次并行 + 1 次修正

工程要点:投机采样的本质是**「用并行换串行」——草案负责猜,大模型负责验证,一次 forward 验证 γ 个候选。收益取决于接受率**(草案猜得准不准),接受率越高、γ 越大,加速越明显。

3. 草拟-验证(Draft-Verify)流程详解

标准的草拟-验证循环(如 vLLM 的 speculative decoding 实现):

循环步骤(每轮):
1. 草案模型基于「当前 KV Cache + 已生成序列」生成 γ 个候选 token
2. 把 γ 个候选「接在序列后」,大模型一次 forward
   → 得到每个候选位置的真实概率分布
3. 从第一个候选开始逐 token 验证:
   - 大模型采样位置 i 的 token t_i
   - 与草案的候选对比:相等 → 接受;不等 → 在此处打断
4. 如果中途被拒绝 → 用大模型自己的采样结果替换,重置草案上下文
5. 接受 k 个 token → 更新 KV Cache,继续下一轮

注意:
□ 草案模型也用 KV Cache(自己的,通常小得多)
□ 被拒绝的 token 处,草案的后续预测作废(重新草拟)
伪代码示意:
while 未结束:
  draft_tokens = draft_model.generate(seq, γ)
  probs = target_model.forward(seq + draft_tokens)  # 并行
  accept_len = verify(draft_tokens, probs)          # 逐 token 接受
  seq += draft_tokens[:accept_len] + (target_sample if rejected)

工程要点:草拟-验证循环的关键是**「草案每轮重猜、大模型每轮并行验证」**——接受的部分直接进序列,被拒绝处用大模型的采样替换并重草拟。草案模型自己的 KV Cache 是独立的,两者互不污染。

4. 正确性保证:拒绝采样与分布保持

投机采样最容易被质疑的一点:「猜的会不会改变输出分布」——不会,有严格的数学保证:

拒绝采样(Rejection Sampling):
□ 草案的分布 q 与大模型的分布 p 不同
□ 接受规则要「校准」:让接受后的最终分布 == 大模型的 p
□ 关键:接受概率要按 p 与 q 的比例调整
  → 草案猜「低概率」的 token 时,被接受的概率也低

正确性定理:
□ 只要接受规则正确(按 q/p 校准),输出分布 == 大模型直接采样
□ 采样参数(temperature 等)要一致
□ 贪心(greedy)解码:接受「草案 token == 大模型 argmax」即保持贪心

工程含义:
□ 投机采样不改「模型能力」,只改「生成速度」
□ 可以安全用于生产(分布不变)
□ 但:自定义采样逻辑时不能乱改接受规则
接受规则示意:
target_prob = p(token)         # 大模型概率
draft_prob  = q(token)         # 草案概率
if draft_token == target_sample: 接受
else if target_prob > draft_prob: 接受(概率 = (p-q)/p)
else: 拒绝(概率 = 1 - q/p)

工程要点:投机采样的正确性靠**「拒绝采样校准」**——接受规则让最终分布与大模型直接采样等价。这让它可以「无风险地用于生产」(输出分布不变,只是更快)。代价是草案不能太差(接受率低则加速小)。

5. 草案模型选型:小模型、N-gram 与自草拟

草案模型怎么选,直接决定接受率与加速:

草案模型方案:
□ 独立小模型:同架构小 10-50x 的模型(如 Llama-70B 配 7B draft)
  → 接受率高,但加载两个模型(显存开销 + 管理复杂)
□ N-gram / 基于检索:用「前缀匹配历史文本」草拟
  → 零显存额外开销,但只在「可预测文本」接受率高
□ 自草拟(Self-Draft):用大模型自身的浅层/子结构草拟
  → 无需第二个模型

选型权衡:
□ 小模型:通用性最好,接受率最稳
□ N-gram:零成本,适合「对话/代码补全」这类可预测文本
□ 自草拟:无额外显存,但实现复杂

γ(草拟长度)选择:
□ 太短:一次验证的收益小
□ 太长:草案后面容易猜错(接受率下降)→ 一般 4-8

工程要点:草案模型的选择是**「显存成本 vs 接受率」**的权衡——独立小模型接受率最稳但占显存,N-gram 零成本但只在可预测文本好用。γ 不是越大越好,要匹配草案的「预测能力边界」,一般 4-8 个。

6. Medusa 与 EAGLE:无独立草案模型的加速

两类「不靠第二个模型」的投机采样方案:

Medusa(多头草拟头):
□ 在模型「最后一层」加多个「草拟头」(Medusa heads)
□ 每个 head 预测「后第 k 个 token」的分布(并行)
□ 微调 Medusa heads(很小,不动主模型)
□ 优点:无独立草案模型、显存小、垂直集成

EAGLE(无独立模型草拟):
□ 利用「主干模型的特征」草拟(在隐藏层做草拟)
□ 结构:一个轻量草拟头 + 特征拼接
□ 接受率比独立小模型还高(特征更准)

对比:
□ 独立草案模型:通用、实现简单、双模型管理
□ Medusa/EAGLE:显存省、集成好、接受率更高
  → 但需要额外训练(Medusa heads / EAGLE 模块)
选型场景:
□ 快速部署/通用场景 → 独立草案模型(现成)
□ 显存紧张/追求集成 → Medusa(训练成本低)
□ 追求最高接受率 → EAGLE(需训练草拟模块)

工程要点:Medusa/EAGLE 的价值是**「没有第二个模型,靠模型自身的结构草拟」**——Medusa 加草拟头、EAGLE 用隐藏层特征,两者都省显存且接受率不错,但都要少量额外训练。选型看「要省显存还是图省事」。

7. 加速收益与实测表现

投机采样的加速能到什么量级,取决于接受率:

加速公式(理论):
有效步长 = E[接受数] ≈ γ × 接受率
加速比 ≈ 有效步长(理想情况,忽略草案模型开销)

实测量级(社区报告):
□ 接受率 0.6-0.8、γ=4 → 加速 2-3x(常见水平)
□ EAGLE/Medusa 类 → 更高(可达 3x+)
□ 依赖场景:代码/结构化文本接受率高,随机文本接受率低

影响加速的因素:
□ 草案模型质量:越准加速越大
□ 场景可预测性:代码补全 > 自由对话
□ γ 与接受率的匹配:γ 超草案能力 → 加速打折
□ 硬件:草案模型也要占算力,预算紧张时加速缩水
加速瓶颈:
□ 草案模型本身的 forward 时间(草拟 5 个 token 也要算)
□ 大模型 γ 个候选的 forward(比单 token 慢一点)
→ 净加速 = 减少的串行步数 - 草拟/验证的开销

工程要点:投机采样的收益是**「接受率驱动的净加速」**——2-3x 是常见区间,代码/结构化文本更高。但草案模型的算力开销会吃掉一部分收益,工程上要实测「净加速」而不是只看「有效步长」。

8. 工程实现:与批量调度、采样参数集成

投机采样在生产推理引擎里落地,有几处集成要点:

与连续批处理集成(vLLM):
□ 投机解码要融入 scheduler:草案模型与大模型共用资源
□ 批内多请求各自草拟 → 大模型「批量验证多个请求的候选」
  → 并行验证的批量效应进一步提升吞吐

采样参数一致性:
□ temperature/top_p 等参数要在草案与大模型间一致
□ 草案的采样分布要与验证规则匹配(否则拒绝采样失真)

KV Cache 处理:
□ 草案模型用自己的小 KV Cache
□ 大模型在验证时扩展 γ 个位置的 KV Cache
□ 被拒绝位置的 KV Cache 要「截断/回滚」

易集成点:
□ 贪心解码:实现最简单(比较 argmax)
□ 采样解码:拒绝采样规则要精确实现
调度示意:
请求 1 草案 5 候选 + 请求 2 草案 5 候选
→ 大模型一次前向,同时验证两个请求的候选
→ 批量并行验证:吞吐更高

工程要点:投机采样的生产集成是**「与批量调度协同」**——多请求的候选可以一起并行验证(批量效应),采样参数必须一致,KV Cache 要处理被拒绝位置的回滚。贪心解码实现最简单,采样解码要精确的拒绝采样。

9. 局限性、成本与踩坑

投机采样不是银弹,有明确的局限与成本:

局限性:
□ 随机/高熵文本:草案猜不准 → 接受率低 → 加速接近 0
□ 草案模型的显存/算力成本:显存紧张时上不起
□ 长上下文场景:草案模型的 KV Cache 也随上下文增长

踩坑:
□ γ 设得太大:草案后段全错,浪费验证算力
□ 采样参数不一致:分布被破坏(看似加速实则改变输出)
□ 把「有效步长」当「净加速」:忘了草拟开销
□ 冷启动/首 token:投机采样主要加速 decode,不加速 prefill

适用判断:
□ 高吞吐、可预测文本(代码/补全/结构化)→ 强适用
□ 低延迟交互(首 token 敏感)→ 收益有限
□ 显存已满 → 考虑 Medusa/自草拟(省显存方案)
评估指标:
□ 接受率(草案被接受的比例)
□ 有效步长(每轮实际接受的 token 数)
□ 净加速(端到端 tokens/sec,含草拟开销)
→ 只看接受率不够,要端到端测净加速

工程要点:投机采样的判断是**「场景决定收益」**——可预测文本(代码/结构化)收益大,随机对话收益小;显存紧张用 Medusa 类方案。评估看「端到端净加速」,而不是纸面接受率。

10. 速查表与一句话记忆

问题一句话答案
瓶颈是什么自回归解码串行 + Decode 算力闲置
核心思路草案猜 + 大模型并行验证
怎么保证正确拒绝采样校准,分布不变
草案怎么选小模型/ N-gram / 自草拟
无第二模型方案Medusa(草拟头)/ EAGLE(特征草拟)
加速多少接受率 0.6-0.8 → 2-3x(场景相关)
集成要点与批量调度协同、采样一致、KV 回滚
什么时候没用随机文本/显存满/首 token 敏感
看什么指标端到端净加速(不是接受率)

一句话记忆:投机采样 = 草案模型猜候选(小/N-gram/自草拟)+ 大模型并行验证 γ 个(一次 forward)+ 拒绝采样保分布(输出不变)+ Medusa/EAGLE 省显存方案(无第二模型)+ 净加速 2-3x(场景相关)——用「闲置算力的并行」换「串行步数的减少」。

延伸阅读

  • /ai-vllm-system/ — 连续批处理与调度
  • /ai-attention-optimization/ — KV Cache 与注意力优化
  • /ai-kernel-fusion-optimization/ — 推理内核与算子融合
  • /ai-llm-inference-architecture/ — 推理服务架构与调度
  • /ai-inference-benchmark/ — 解码吞吐与延迟指标
  • LLM 应用专题 — 生成式应用
  • 高性能计算专题 — GPU 内核优化

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「ai」更多文章

  1. 类别不平衡与异常检测:从重采样到半监督方法
  2. Embedding 深入:对比学习、双塔架构与向量检索工程
  3. MLOps 治理与可复现:模型注册、漂移监控与合规