Speculative Decoding:用「猜」加速「算」的推理黑魔法

深入 LLM 推理中的投机解码技术——为什么让小模型猜、大模型验,能实现 2-3x 无损加速,以及它暴露的 LLM 推理瓶颈本质。

做 LLM serving 的人迟早会撞上一个反直觉的问题:为什么生成 1 个 token 和验证 10 个 token,延迟几乎一样?

这不合理。直觉上 10 个肯定比 1 个慢。但这个「不合理」的背后,藏着 LLM 推理优化里最有趣的 trick 之一——Speculative Decoding(投机解码)

先理解核心矛盾

LLM 的推理延迟主要卡在哪里?很多人第一反应是「计算量太大」。其实不对。

拆成第一性原理来看:一个标准的自回归推理步骤,流程是这样的——

  1. 把输入序列搬到 GPU 显存
  2. 跑一次 Transformer 前向传播(计算)
  3. 从输出 logits 采样一个 token(生成)

这里的关键是第 1 步。现在主流 LLM 参数量在 7B 到 70B,每个参数是 2 字节(FP16),光是加载参数就需要传输 14GB 到 140GB 的数据。GPU 的显存带宽(比如 A100 是 2 TB/s)决定了这一步的速度。

而第 2 步的计算,在 batch size = 1 的在线推理场景下,GPU 的计算单元大部分时间是闲着的。推理过程实际上是 memory bandwidth bound,而不是 compute bound。

这就意味着:生成 1 个 token 的成本 ≈ 把模型参数从显存搬到计算核心一次。而验证 10 个 token,只需搬一次参数(batch 起来做一次前向就够了)。

Speculative Decoding 的核心思路

如果瓶颈是把参数搬来搬去,那「每次多干点活」就是最自然的优化方向。

Speculative Decoding 的做法分两步:

  1. Draft(草拟):用一个小模型(draft model),快速生成 K 个候选 token。小模型参数少,带宽开销低,速度很快。
  2. Verify(验证):把 K 个候选 token 拼起来,喂给大模型(target model)做一次前向传播。大模型一口气输出这 K 个位置上的概率分布,然后用拒绝采样策略决定接受哪些。

关键细节是拒绝采样。它不是简单地把小模型的输出直接扔掉或全收,而是用一个数学上保证「分布无损」的方式:

  • 对于每个 draft token,检查大模型给它的概率和 draft 模型给它的概率
  • 如果大模型认可(概率更高或相当),接受
  • 如果大模型不认可,根据概率比进行随机拒绝,然后从大模型的修正分布中重新采样

这个拒绝机制保证了最终输出分布和大模型自回归生成的分布完全一致——无损加速,不是近似。

「猜」的边界在哪

Draft 模型不是随便选的。它需要满足两个条件:

  1. 足够快:生成 K 个 token 的耗时,要小于大模型生成 1 个 token 的耗时。否则得不偿失。
  2. 和 target 模型的对齐度足够高:如果 draft 模型猜的和大模型想说的偏差太大,K 个 token 被拒绝大半,提速效果归零。

实际部署中最常见的组合是:用同一个模型的小版本(比如 7B)做 draft,大版本(比如 70B)做 target。这叫 self-speculative decoding。另一种做法是训练一个专门的轻量 draft head,但维护成本更高。

K 值的选取也很微妙。K 太小,并行验证的红利没吃满;K 太大,draft 模型后期越猜越偏,拒绝率飙升。实践中 3-5 是一个常见区间,有些方案会根据实时 acceptance rate 动态调整 K。

那些「看起来很美」的真相

Speculative Decoding 不是银弹。

第一,它只对 memory bandwidth bound 的场景有效。如果你的 batch size 很大(比如离线批处理几十条请求同时推理),GPU 已经处于 compute bound 状态,再加 draft 模型反而拖慢。

第二,小模型的质量是天花板。某些领域(比如代码生成、数学推理)中,小模型和大模型的能力差距巨大,draft 的 acceptance rate 很低,加速效果大打折扣。

第三,部署复杂度增加了。需要同时维护两个模型,draft 模型的预热、更新和 target 模型的同步都需要额外工程投入。

从架构设计的角度怎么看

如果把 Speculative Decoding 抽象一下,它其实是一个通用的 speculative execution 模式——先低成本猜测结果,再并行验证。这个思路在 CPU 架构里早就有了(分支预测),在分布式系统里也有(乐观锁),在 LLM 推理里只是换了个马甲。

从更高维度看,它回答的是 LLM serving 中最本质的问题:当硬件瓶颈不是计算而是搬运,你愿意为「猜」付出多少代价?

这个问题的答案在持续变化。随着推理芯片架构演进(比如存算一体、更大的片上缓存),可能有一天 memory bandwidth 不再是瓶颈,届时 speculative decoding 的价值会打折扣。但在今天,它是成本最低、效果最稳的推理加速方案之一,值得每个做 LLM serving 的人理解。

评论

此博客中的热门博文

我写了半年 prompt,最后发现最好的技巧就三个