Speculative Decoding 实战:让大模型少跑几次前向也能保持输出一致
大模型推理慢,很多时候不是因为每一步计算特别复杂,而是因为生成过程天然是串行的:模型先生成第 1 个 token,再把它放回上下文里生成第 2 个 token,如此循环。即使 GPU 算力再强,输出长文本时也会被一次次前向计算拖慢节奏。
Speculative Decoding(也称 Assisted Decoding)是一种已被主流推理框架广泛采用的加速思路:先让一个更小、更快的 draft model 猜出后面几个 token,再让大的 target model 一次性验证这些候选 token——验证通过的 token 直接进入输出,验证失败的位置再按目标模型的分布重新采样。这样既减少了大模型的串行前向次数,又尽量保持了与原目标模型一致的输出分布。
一、为什么 LLM 解码会慢
训练阶段可以把大量 token 并行送进模型,但生成阶段完全不同。自回归模型必须知道前一个 token,才能预测下一个 token——这个依赖链导致生成阶段很难简单地把所有输出 token 一次算完。
对于在线问答、代码助手、智能客服这类场景,用户最直接感受到的是两个关键指标:
| 指标 | 全称 | 含义 |
|---|---|---|
| TTFT | Time To First Token | 首个 token 的生成延迟 |
| TPOT | Time Per Output Token | 后续每个 token 的平均生成延迟 |
KV Cache 可以减少重复计算历史上下文,PagedAttention 可以改善显存管理,但它们并没有改变「逐 token 解码」的基本形态。Speculative Decoding 解决的是另一个问题:能不能让大模型一次前向验证多个候选 token,从而减少大模型的调用次数?
二、核心流程:draft → verify → accept / reject
Speculative Decoding 的基本流程可以拆成四个阶段。以下用伪代码表示其核心逻辑:
# 伪代码:Speculative Decoding 单轮流程
def speculative_decode(context, target_model, draft_model, K):
# Step 1: Draft - 小模型快速生成 K 个候选 token
draft_tokens = draft_model.generate(context, max_tokens=K)
# Step 2: Verify - 大模型一次前向验证所有候选 token
target_logits = target_model.forward(context + draft_tokens)
# Step 3: Accept / Reject - 按采样校正规则逐个判定
accepted = []
for i, token in enumerate(draft_tokens):
if acceptance_check(token, target_logits[i]):
accepted.append(token)
else:
# 从此位置回退,按 target 分布重新采样
corrected_token = sample_from(target_logits[i])
accepted.append(corrected_token)
break # 后续候选 token 作废
# Step 4: 已接受的 token 成为新上下文,进入下一轮
return context + accepted
分步拆解:
- Draft(草稿生成):轻量 draft model 根据当前上下文快速生成若干候选 token,例如一次猜 4 个或 8 个。
- Verify(并行验证):target model 不再只验证一个 token,而是把 draft model 给出的多个候选 token 放到同一次前向计算里并行验证。
- Accept / Reject(接受或拒绝):如果候选 token 与 target model 的分布一致(满足采样校正规则),就接受;如果某个 token 不通过,则从该位置回退,由 target model 按原始分布重新采样。
- 进入下一轮:已接受的 token 成为新上下文,再继续下一轮 draft 和 verify。
这个流程的关键不是「小模型替代大模型」,而是「小模型提出草稿,大模型集中验收」。大模型仍然是最终裁判,在正确实现时可以保持目标模型的输出分布不变。
三、它为什么能加速
普通解码中,如果要生成 4 个 token,大模型通常要串行跑 4 次前向计算。Speculative Decoding 让小模型先快速生成 4 个候选 token,然后大模型用 1 次前向验证这 4 个 token。
传统解码: [Target → token1] → [Target → token2] → [Target → token3] → [Target → token4]
(4 次大模型前向)
推测解码: [Draft → tok1, tok2, tok3, tok4] → [Target 一次验证全部]
(1 次小模型前向 + 1 次大模型前向)
如果接受率较高(比如 draft model 提出的 4 个 token 中有 3 个经常被接受),系统平均每轮就能推进多个 token,而不是每次只推进一个 token,大模型的昂贵前向次数就会显著下降。
加速收益主要来自三个条件:
- draft model 足够快:额外开销不能吃掉收益;
- 接受率足够高:否则频繁回退会浪费计算;
- 低 batch / 低延迟场景:大模型串行解码瓶颈更明显。
这也是为什么很多推理框架强调:Speculative Decoding 更适合低 batch、长输出、对延迟敏感的场景。在高并发大 batch 场景里,它未必一定比成熟的连续批处理更划算。
四、工程落地要看哪些指标
落地 Speculative Decoding 时,不建议只看平均 tokens/s。更实用的指标组合如下:
| 维度 | 指标 | 说明 |
|---|---|---|
| 延迟 | TTFT | 首 token 延迟是否受影响 |
| 延迟 | TPOT | 每个输出 token 平均延迟是否下降 |
| 效率 | Acceptance Rate | draft token 被 target model 接受的比例 |
| 效率 | Accepted Length | 每轮平均接受多少个 token |
| 成本 | Draft Overhead | draft model 本身带来的额外耗时 |
| 资源 | GPU Utilization | target model 是否真的减少了空转和串行等待 |
| 资源 | Memory Overhead | 同时加载 draft model 是否增加显存压力 |
| 质量 | Quality Parity | 输出质量是否与不启用时保持一致 |
其中最核心的是 Acceptance Rate 和 Draft Overhead:一个很强但不够快的 draft model 可能拖慢整体流程;一个很快但预测太差的 draft model 又会导致大量拒绝。工程上通常要在「快」和「准」之间找平衡。
五、draft model 怎么选
draft model 不一定越大越好。它的目标不是独自生成高质量答案,而是尽可能低成本地猜中 target model 接下来会接受的 token。
选型优先级建议:
| 优先级 | 考量因素 | 原因 |
|---|---|---|
| 🔴 高 | 与 target model 使用相同 tokenizer | 减少 token 对齐和重编码成本 |
| 🔴 高 | 模型结构和训练语料尽量接近 target model | 提升预测准确度 |
| 🟡 中 | 延迟足够低,明显快于 target model | 保证加速收益不被开销吃掉 |
| 🟡 中 | 在目标业务语料上接受率稳定 | 避免频繁回退浪费计算 |
| 🟢 低 | 部署后不显著挤占 target model 显存 | 控制整体资源成本 |
如果 tokenizer 不一致,候选 token 的对齐和重编码成本会增加,接受率也可能明显下降。Hugging Face 的 Universal Assisted Generation 尝试缓解不同 tokenizer 的限制,但常规工程落地中,优先选择 tokenizer 一致的 draft / target 组合仍然更稳妥。
六、常见误区
误区一:Speculative Decoding 一定会提速
实际收益取决于 draft model 延迟、接受率、batch size、输出长度和采样策略。短输出、高随机采样(如 temperature 较高)、高 batch 推理都可能让收益变小甚至为负。
误区二:draft model 越强越好
强模型通常更慢。如果它的前向成本接近 target model,就失去了「低成本草稿」的意义。draft model 追求的是性价比,不是绝对质量。
误区三:它会改变模型能力
Speculative Decoding 本质是推理调度和采样校正方法,不是训练方法。它不会让目标模型变得更聪明,只是让目标模型少做一部分串行工作。输出分布理论上与原始目标模型一致。
误区四:只要 tokens/s 变高就够了
在线服务还要看 P95 / P99 延迟、显存占用、失败回退机制、监控告警和灰度策略。单一的吞吐指标在在线场景中不足以衡量用户体验。
七、适合的使用场景
| 适合 ✅ | 不适合 ❌ |
|---|---|
| 单请求或小 batch 的低延迟生成 | 极短输出(收益不显著) |
| 输出较长的问答、总结、代码生成 | 高 batch 已把 GPU 打满的吞吐型服务 |
| target model 很大,draft model 很小且预测稳定 | draft / target tokenizer 难以对齐的组合 |
| 可以接受额外加载一个 draft model | 强随机采样(temperature 高)导致候选 token 难以被接受 |
| 有能力监控接受率和回退成本 | 显存紧张、无法同时加载两个模型的场景 |
八、上线建议
如果要在生产系统中启用 Speculative Decoding,推荐按以下路径分阶段推进:
第一阶段(离线评估)
├── 选择真实业务 prompt
├── 对比关闭 vs 开启的 TTFT、TPOT、吞吐、接受率
└── 验证输出一致性
第二阶段(小流量灰度)
├── 只对低 batch、长输出、稳定任务类型启用
└── 不要一开始全量打开
第三阶段(动态开关)
├── 按模型、任务类型、输出长度、服务负载决定是否启用
└── 避免在不适合的请求上硬开
第四阶段(持续监控)
├── Acceptance Rate 趋势
├── Draft Overhead 占比
├── P95 / P99 延迟
├── GPU 利用率
└── 错误回退率
参考资料
- Fast Inference from Transformers via Speculative Decoding — 原始论文
- Speculative Decoding: Exploiting Speculative Execution for Accelerating Seq2seq Generation
- Hugging Face Transformers: Assisted Decoding
- Hugging Face: Universal Assisted Generation
- NVIDIA TensorRT-LLM Speculative Decoding
- Decoding Speculative Decoding — 综述论文