Speculative Decoding:用「猜测-验证」让大模型推理快 2-3 倍
title: "Speculative Decoding:用「猜测-验证」让大模型推理快 2-3 倍" date: "2026-02-25" tags: ["LLM", "Inference", "Speculative Decoding", "Performance"] description: "深入解析 Speculative Decoding 的核心原理:draft model 猜测 + target model 验证,在不改变输出分布的前提下实现 2-3x 推理加速。"#
问题:自回归解码的延迟困局#
大模型推理有一个根本性的瓶颈:自回归解码是串行的。生成 K 个 token 需要跑 K 次 forward pass,每次只产出一个 token。
这意味着一个 70B 参数的模型,哪怕你的 GPU 算力有富余,latency 依然被「串行步数」锁死。batch size 增大可以提升 throughput,但对单条请求的 latency 毫无帮助。
根本原因在于:大模型推理通常是 memory-bandwidth bound,而非 compute bound。GPU 的算力在自回归推理中大量闲置——每一步 forward pass 都需要加载完整的模型权重,但实际做的计算量(一个 token 的矩阵运算)远低于硬件峰值。
有没有办法在不改变模型、不改变输出分布的前提下,让推理变快?
Speculative Decoding 说:有,而且很优雅。
核心思想:猜测 + 验证#
Speculative Decoding 的灵感来自 CPU 的 speculative execution(分支预测):先猜测后续指令,猜对了就赚到,猜错了回滚。
迁移到 LLM 推理:
- Draft phase:用一个小而快的 draft model(如 7B)自回归生成 γ 个候选 token
- Verify phase:把这 γ 个 token 一次性喂给大的 target model(如 70B)做并行 scoring
- Accept/Reject:用 modified rejection sampling 决定接受前几个 token,拒绝后面的
关键洞察:target model 并行评估 γ 个 token 的延迟,和它生成 1 个 token 的延迟几乎相同。因为两者都是 memory-bandwidth bound,计算量的差异被内存带宽掩盖了。
传统解码 (K=5): M → M → M → M → M = 5 次 forward
Speculative (γ=5): m → m → m → m → m → M = 5 次小 forward + 1 次大 forward
↑ draft model ↑ target model (并行验证全部)如果 5 个猜测全部被接受,你用「5 次小 forward + 1 次大 forward」替代了「5 次大 forward」——加速比取决于 draft model 有多快、猜得有多准。
Modified Rejection Sampling:数学上精确#
Speculative Decoding 最精妙的部分是:它的输出分布和原始 target model 完全一致。不是近似,是精确。
设 target model 对位置 t 的概率分布为 ,draft model 为 。对于 draft model 猜测的 token :
- 以概率 接受
- 否则拒绝,从修正分布 中重新采样
def speculative_decode(draft_model, target_model, prefix, gamma=5):
# Phase 1: Draft model 生成 gamma 个候选 token
draft_tokens = []
draft_probs = []
x = prefix
for _ in range(gamma):
q = draft_model.get_probs(x) # draft 分布
token = sample(q)
draft_tokens.append(token)
draft_probs.append(q)
x = x + [token]
# Phase 2: Target model 并行评估所有位置
这个算法的巧妙之处:
- 全部接受时:生成了 γ+1 个 token(draft 的 γ 个 + bonus 1 个)
- 第 k 个被拒绝时:生成了 k+1 个 token(前 k 个接受 + 重采样 1 个)
- 最坏情况:第一个就被拒绝,但仍然生成了 1 个 token——不会比原来慢
接受率决定一切#
设 draft model 的平均接受率为 α(每个 token 被接受的概率),每轮猜测 γ 个 token。期望每轮生成的 token 数为:
设 target model 单次 forward 耗时为 ,draft model 为 ,加速比为:
几个关键推论:
| 接受率 α | γ=4 期望 tokens | 加速比 (Tq/Tp≈0.05) |
|---|---|---|
| 0.5 | 1.94 | ~1.6x |
| 0.7 | 3.00 | ~2.5x |
| 0.9 | 4.10 | ~3.4x |
| 0.95 | 4.55 | ~3.8x |
接受率高度依赖任务类型:
- 模板化文本(代码补全、格式化输出):α ≈ 0.85-0.95,加速显著
- 创意写作(开放式生成):α ≈ 0.5-0.7,加速一般
- 高熵分布(模型非常不确定时):α 较低
Draft Model 的选择#
同系列小模型#
最常见的做法。比如用 Llama-7B 作为 Llama-70B 的 draft model。优势是 tokenizer 一致、分布相似。
Self-Draft(自回归草稿)#
不需要额外模型。方法包括:
- Layer skipping:只跑 target model 的前几层作为 draft
- Medusa heads:在 target model 上接几个轻量 head,并行预测后续 token
- EAGLE:用一个小的 auto-regressive head 在 target model 的 hidden state 上做 draft
# Medusa-style: 在最后一层 hidden state 上接多个预测头
class MedusaModel(nn.Module):
def __init__(self, base_model, num_heads=4):
super().__init__()
self.base = base_model
self.heads = nn.ModuleList([
nn.Linear(base_model.hidden_size, base_model.vocab_size)
for _ in range(num_heads)
])
def forward(self, x):
hidden = self
Self-Draft 方法的优势是不需要维护额外模型,劣势是需要对 target model 做修改或 fine-tune。
Retrieval-based Draft#
从 prompt 或数据库中直接检索可能的 continuation,跳过 draft model 推理。适合 RAG 场景。
工程实践#
在 vLLM 中使用#
vLLM 从 v0.3 开始支持 speculative decoding:
from vllm import LLM, SamplingParams
# 方法1:指定独立 draft model
llm = LLM(
model="meta-llama/Llama-3-70B-Instruct",
speculative_model="meta-llama/Llama-3-8B-Instruct",
num_speculative_tokens=5, # gamma
# 可选:设置 draft model 的 tensor parallel
speculative_model_tensor_parallel_size=1,
)
# 方法2:使用 n-gram match (无需 draft model)
llm = LLM(
model="meta-llama/Llama-3-70B-Instruct",
speculative_model="[ngram]",
num_speculative_tokens=5,
ngram_prompt_lookup_max=4
调参建议#
γ (num_speculative_tokens):
- 太小:每轮生成太少,overhead 占比大
- 太大:后面的 token 越来越难猜中,draft 计算浪费
- 经验值:4-8 对大部分场景效果好
Draft model 大小:
- 太小:接受率低,加速有限
- 太大:draft 本身太慢,吃掉加速收益
- 经验法则:target 参数量的 1/5 ~ 1/10
Batch 场景下的注意事项:
- Speculative decoding 主要优化 latency,不优化 throughput
- 大 batch 下 target model 可能已经 compute bound,并行验证的「免费午餐」消失
- 建议:低并发(batch ≤ 4)时开启,高并发时关闭
与其他加速技术的组合#
Speculative Decoding 可以和其他推理优化叠加:
| 技术 | 优化维度 | 与 SD 的关系 |
|---|---|---|
| KV Cache | 减少重复计算 | 互补,SD 依赖高效 KV Cache |
| Flash Attention | 减少 IO | 互补,加速 verify 阶段 |
| Quantization (GPTQ/AWQ) | 减小模型体积 | 互补,可同时用在 draft 和 target |
| Continuous Batching | 提升 throughput | 需要适配,SD 让 batch 内序列长度不一致 |
| Tensor Parallel | 多卡推理 | 互补,target model 可 TP,draft 可单卡 |
最佳实践:Quantized target + Small draft + Flash Attention + KV Cache = 单请求延迟最低。
局限与展望#
现有局限:
- 高并发场景收益递减:batch 越大,verify 阶段不再「免费」
- Draft model 需要匹配:tokenizer 必须一致,分布差异大则接受率低
- sampling temperature 影响:temperature 越高 → 分布越平 → 接受率越低
- 实现复杂度:需要精心处理 KV Cache 的回滚和拼接
前沿方向:
- Tree-based speculative decoding:draft 生成树状候选而非链式,覆盖更多可能性
- Online draft model adaptation:在推理时动态更新 draft model 的分布
- Hardware-aware γ scheduling:根据实时硬件负载动态调整猜测长度
- Multi-model cascade:多级 draft(tiny → small → medium → target)
总结#
Speculative Decoding 是近年来 LLM 推理优化领域最优雅的思路之一:
- 数学精确:输出分布完全不变,不是近似不是蒸馏
- 模型无关:不需要重新训练或修改架构
- 直觉简单:猜测 + 验证,猜对就赚,猜错不亏
- 实际有效:2-3x 加速在大部分场景下可复现
它的本质是把大模型推理中「闲置的算力」利用起来——通过 draft model 把原本串行的生成变成可并行验证的批量操作。在单用户、低并发、对延迟敏感的场景(比如交互式对话),它几乎是免费的午餐。
参考文献:
- Leviathan et al., "Fast Inference from Transformers via Speculative Decoding" (ICML 2023)
- Chen et al., "Accelerating Large Language Model Decoding with Speculative Sampling" (2023)
- Cai et al., "Medusa: Simple LLM Inference Acceleration Framework with Multiple Decoding Heads" (2024)
- Li et al., "EAGLE: Speculative Sampling Requires Rethinking Feature Uncertainty" (2024)