年份与会议
2023 · ICML
通过“草稿模型先猜、大模型再批量验证”的两阶段解码,把自回归推理中的串行瓶颈部分摊薄,是现代低延迟推理的重要方向之一。
年份与会议
2023 · ICML
作者
Yaniv Leviathan、Matan Kalman、Yossi Matias
主题
推理优化
阅读时长
约 3 分钟
收录时间
2022/11/30
大模型推理的一个基本痛点,是 decoder-only 模型生成文本时往往必须逐 token 前进:
即便有 KV Cache 与推理性能优化 这类技术,减少了历史前缀的重复计算,生成流程本身仍然带着很强的串行性。这就意味着:
Speculative Decoding 之所以重要,是因为它没有试图改变模型本体,而是重新思考了解码过程:
能不能让一个更小、更快的模型先替大模型“打草稿”,再让大模型批量验证,而不是每一步都从零开始慢慢算?
Speculative Decoding 的核心流程可以概括成两阶段:
如果候选 token 符合目标模型分布要求,就直接批量接受;如果不符合,就在某个位置回退,由大模型接管并重新生成。
这个想法的精妙之处在于:
因此,它试图把“严格串行”的一部分,转化成“草稿并行 + 验证批量化”的流程。
如果把这条解码协议画出来,Speculative Decoding 和普通逐 token 解码的差别会非常明显:
<g>
<rect x="42" y="120" width="148" height="68" rx="18" fill="#e8f1ff" stroke="#98b7e1" />
<text x="116" y="149" text-anchor="middle" font-size="18" font-weight="700">当前前缀</text>
<text x="116" y="171" text-anchor="middle" font-size="13" fill="#4b5563">已有上下文</text>
</g>
<g>
<rect x="236" y="92" width="196" height="124" rx="22" fill="#eef6e8" stroke="#a8c48e" />
<text x="334" y="124" text-anchor="middle" font-size="20" font-weight="700">Draft Model</text>
<text x="334" y="149" text-anchor="middle" font-size="13" fill="#4b5563">小模型快速连续猜测</text>
<rect x="266" y="170" width="42" height="28" rx="8" fill="#ffffff" stroke="#a8c48e" />
<rect x="318" y="170" width="42" height="28" rx="8" fill="#ffffff" stroke="#a8c48e" />
<rect x="370" y="170" width="42" height="28" rx="8" fill="#ffffff" stroke="#a8c48e" />
<text x="287" y="189" text-anchor="middle" font-size="12" fill="#4b5563">t1</text>
<text x="339" y="189" text-anchor="middle" font-size="12" fill="#4b5563">t2</text>
<text x="391" y="189" text-anchor="middle" font-size="12" fill="#4b5563">t3</text>
</g>
<g>
<rect x="478" y="92" width="210" height="124" rx="22" fill="#fff4dc" stroke="#e2c36f" />
<text x="583" y="124" text-anchor="middle" font-size="20" font-weight="700">Target Model</text>
<text x="583" y="149" text-anchor="middle" font-size="13" fill="#4b5563">一次性验证多个候选位置</text>
<text x="583" y="178" text-anchor="middle" font-size="14" fill="#4b5563">接受前缀里高概率 token</text>
<text x="583" y="199" text-anchor="middle" font-size="14" fill="#4b5563">在被拒位置重新接管生成</text>
</g>
<g>
<rect x="734" y="98" width="192" height="52" rx="16" fill="#dff4f0" stroke="#8dc7bd" />
<text x="830" y="129" text-anchor="middle" font-size="18" font-weight="700">接受的 token</text>
<rect x="734" y="168" width="192" height="52" rx="16" fill="#fce7ef" stroke="#e2a8bd" />
<text x="830" y="199" text-anchor="middle" font-size="18" font-weight="700">被拒后由大模型续写</text>
</g>
<g>
<rect x="772" y="262" width="120" height="54" rx="16" fill="#ece8ff" stroke="#b5abef" />
<text x="832" y="294" text-anchor="middle" font-size="18" font-weight="700">最终输出</text>
</g>
<line x1="190" y1="154" x2="236" y2="154" stroke="#5b6b7f" stroke-width="3" marker-end="url(#spec-arrow)" />
<line x1="432" y1="154" x2="478" y2="154" stroke="#5b6b7f" stroke-width="3" marker-end="url(#spec-arrow)" />
<line x1="688" y1="124" x2="734" y2="124" stroke="#5b6b7f" stroke-width="3" marker-end="url(#spec-arrow)" />
<line x1="688" y1="194" x2="734" y2="194" stroke="#5b6b7f" stroke-width="3" marker-end="url(#spec-arrow)" />
<line x1="830" y1="220" x2="832" y2="262" stroke="#5b6b7f" stroke-width="3" marker-end="url(#spec-arrow)" />
<text x="490" y="318" text-anchor="middle" font-size="15" fill="#4b5563">核心变化:让“小模型先走几步,大模型集中裁决”,从而削弱纯串行解码</text>
</g>
很多加速方法一旦引入近似,大家最担心的就是:模型会不会变味?Speculative Decoding 最漂亮的地方之一,是它在设计上追求分布等价,也就是:
在满足算法条件的前提下,最终生成结果仍然对应目标大模型原本的采样分布,而不是随便为了速度做粗暴近似。
这点非常重要,因为生产环境并不欢迎“快了很多,但回答风格和质量明显变了”的优化。Speculative Decoding 的吸引力就在于,它努力把加速建立在“正确性不明显牺牲”的前提上。
直觉上看,草稿模型之所以有价值,是因为语言生成其实并不是每个 token 都同样难预测:
因此,让小模型先生成一串“高概率候选”,大模型再负责把关,就很像一个层级协作系统:
这和现实工程里“先粗筛、再精判”的思路非常一致。
Speculative Decoding 经常和其他推理优化一起被提到,但它解决的问题层级并不相同:
也就是说,它不是在算子级、省显存级做优化,而是在“生成过程怎么组织”这一级动手。正因为切入点不同,它常常能和其他优化叠加使用。
论文最有说服力的地方,是它证明了解码速度可以在保持输出分布一致性的前提下获得显著提升。对读者最值得记住的不是某个倍数,而是下面这件事:
这让推理优化从“更快 kernel、更快缓存”进一步扩展到“更聪明的生成协议”。
Speculative Decoding 通常更适合以下场景:
在这些情况下,草稿模型的额外开销往往能被主模型验证时节省下来的成本覆盖。
虽然这个想法很好,但工程上并不简单。主要难点包括:
如果草稿模型和目标模型差异太大,候选 token 被拒绝的比例高,那么验证节省下来的收益会被反复回退抵消。
你不再只维护一个模型,而是要协调两个模型、候选缓存和验证逻辑。
有些场景输出模式稳定、预测容易,speculative 非常有效;有些场景不确定性高,收益就没那么明显。
在线 serving 时,请求混跑、batch 组织和多租户策略都会影响 speculative 的实际增益。
因此,Speculative Decoding 是很强的方向,但它更像系统工程工具箱里的高级选项,而不是无脑默认开启的开关。
它的重要性不只在于具体算法,而在于它证明了一件此前很多人默认不太好动的事:
自回归解码虽然天然串行,但仍然可以通过“代理生成 + 主模型验证”的方式被重构。
一旦这件事成立,后续就自然会出现更多变体:
所以 Speculative Decoding 真正打开的是一整片解码协议设计空间。
如果你只想抓住三点,请记住:
理解这三点,再去看各类推理框架中的 speculative 功能时,就不会把它和 KV Cache 或 FlashAttention 混为一谈。
沿着相近主题继续阅读,加深对方法边界与实践场景的理解。