投机解码
投机解码(speculative decoding)是一种推理期优化技术,它能在不降低输出质量的前提下加速 LLM 的 token 生成。它通过配对两个模型来工作:
- 草稿模型(draft model):一个更小、更快的模型,提前提出若干草稿 token。
- 目标模型(target model):一个更大的模型,并行验证这些被提出的 token,并接受与其自身预测一致的 token。
这种"先草稿、后验证"的模式保证了最终输出与原始目标模型独自生成的结果完全一致。因此,它不会牺牲输出质量。
为什么要用投机解码
基于 Transformer 的 LLM 以自回归方式生成文本:一次生成一个 token,每个 token 都依赖于之前的 token。每个新 token 都需要一次完整的前向传播、采样,然后将该 token 追加到输入中,才能进入下一步。
这种串行过程有两个主要问题:
- 较高的 token 间延迟(ITL): token 之间的延迟会让生成显得缓慢。
- GPU 利用率低:即使 GPU 空闲,模型也无法提前计算未来的 token。
如果能并行化生成过程的一部分,哪怕不是全部,会怎样?
投机解码受投机执行(speculative execution)的启发(提前计算操作,若不需要则丢弃),它允许 token 生成的某些部分并行运行。当目标模型一次验证多个草稿 token 时,它能更好地利用 GPU 资源并降低 ITL。这对于聊天机器人和代码补全工具等对延迟敏感的应用尤其有用。
该技术建立在关于 LLM 推理的两个关键观察之上:
- LLM 推理受内存带宽限制。GPU 拥有巨大的计算能力,但内存带宽有限。在等待内存访问时,它们的许多计算能力处于闲置状态。
- 某些 token 比其他 token 更容易预测。许多下一个 token 从上下文中显而易见,可以由更小的模型提出。
"先草稿、后验证"的思想最早由 Stern 等人(2018) 提出,后来 DeepMind 将其扩展为一种有统计学依据的方法,称为投机采样(Speculative Sampling)。投机解码就是将投机采样应用于自回归模型(如 Transformer)的推理。
投机解码是如何工作的
从宏观层面看,投机解码在一个循环中运行:
- 草稿模型预测输入序列之后的接下来 K 个 token。
- 目标模型然后并行验证这 K 个 token,看它是否也会预测出同样的 token。
- 目标模型接受这 K 个 token 中它认同的最长前缀。
- 如果它接受了 h 个 token,它自己会生成第 (h+1) 个 token(这样生成仍然保持正轨)。
- 过程重复:草稿模型基于这个新扩展的序列提出接下来的 K 个 token。
理解投机解码的性能
投机解码可以加速 LLM 推理,但前提是草稿模型与目标模型配合良好。在生产环境中启用它之前,一定要在你的工作负载下进行基准测试。对于快速测试,你可以选择 vLLM、SGLang 和 MAX 等推理框架,它们内置了对这种推理优化技术的支持。
关键指标
在评估投机解码时,三个指标最为重要:
-
接受率(α):目标模型接受草稿 token 的概率。这个数值会因多种因素而变化,例如解码策略(如核采样与随机采样)和应用领域。
α 值高意味着每轮接受的 token 更多,目标模型的前向传播次数更少。这会带来更低的延迟、更高的吞吐量和更好的 GPU 利用率。相反,α 值低说明大量 token 被拒绝,意味着你在草稿生成和验证上浪费了计算,并且更频繁地退回到串行解码。
-
投机 token 数量(γ):草稿模型每步提出的 token 数量。在大多数推理框架中是可配置的。
-
接受长度(τ):每轮解码平均接受的 token 数量。根据论文 Fast Inference from Transformers via Speculative Decoding,可以用理论公式计算:
接受率如何影响性能
理论上,投机解码的效果在很大程度上取决于接受率。为了隔离这个变量,你可以模拟投机:按预设概率接受每个草稿 token,而不是运行真实的草稿模型。例如,一个 BentoML 基准测试使用了打过补丁的 vLLM 配置来做这件事;Modular MAX 支持投机解码,并暴露了 --synthetic-acceptance-rate 参数,用于同样的受控测试。
模拟基准测试显示了四种规律:
- α 越高,加速越大。
- 只有在 τ 较高时,增大 γ 才有帮助;否则,性能可能会受到负面影响。
- 延迟随 α 近似线性下降,吞吐量随 α 近似线性上升。
- 当 α ≥ 0.6 且 γ ≥ 5 时,投机解码比基线解码实现了 2–3 倍的加速。
然而在实践中,加速幅度低于预期。
不同工作负载下性能如何变化
合成接受率测试隔离了 α 和 γ 的影响,但真实部署还必须应对并发和并行度。为了观察这些因素的相互作用,另一组基准测试在不同的并发水平和张量并行(TP)配置下测量了投机解码,使用 vLLM 在 H100 GPU 上服务 Llama-3.3-70B-Instruct。

当 TP = 1 时,与基线相比,总吞吐量更早达到平台期(大约在 20–30 个并发请求时)。这表明在高负载下,草稿模型与目标模型之间的协调可能带来额外开销。不过,单输出 token 时间(TPOT)仍提升了大约 2 倍。

当 TP = 2 时,投机解码的性能得到改善,相比基线展现出明显的吞吐量优势。然而,更高的投机 token 数量(γ = 5)在高并发(40+ 请求)下出现了更大的延迟尖峰。
总体而言,结果表明投机解码在不同工作负载下都降低了 TPOT。增加并行度(TP = 2)可以提升吞吐量,但你需要调整 γ,以避免高负载下的延迟尖峰。
这些结果来自非正式测试,仅供参考。性能会因你的模型、硬件、工作负载和框架选择而异。在生产采用之前,一定要在你自己的条件下对投机解码进行基准测试。
使用投机解码的技巧
投机解码可以带来真实的收益,但前提是配置得当。关键在于知道它在哪些场景下最有帮助,以及在哪些场景下可能适得其反。
留意内存开销
你需要将草稿模型和目标模型都加载到 GPU 内存中。在单块 GPU 上,这会很快挤占其他任务(例如批处理)的空间,并在高负载或更大模型下损害性能。
对于多 GPU 配置(例如 TP > 1),情况则不同。将模型拆分到多块 GPU 上可以缓解这一瓶颈。在上述测试中,即使达到 50 个并发请求,γ = 3 或 γ = 5 的投机解码也一直优于基线。
不要忽视被浪费的计算
当目标模型拒绝过多草稿 token 时,GPU 仍然会花费时间生成并验证它们。这些工作没有得到回报,而且违背了投机加速的初衷。这也是接受率如此重要的原因。
选择合适的草稿模型
你的草稿模型分布与目标模型的契合程度决定了接受率。开箱即用的草稿模型在某些情况下可能表现良好,但它们往往难以应对领域特定任务或非常长的上下文。
如果你的工作负载有自己的特点,在数据上微调一个草稿模型通常会得到更好的结果。这样,它就能学会更贴近地模仿目标模型,从而提高接受率和加速幅度。反之,如果你已经看到不错的接受率,可以跳过训练并仍然受益。
投机解码方法
上面描述的"先草稿、后验证"模式是经典配置,即由一个独立的、更小的模型负责草稿。然而,这只是生成草稿 token 的一种方式。随着时间的推移,研究人员开发出了多种方法,它们的主要区别在于草稿 token 的提出方式。
总体而言,这些方法可分为四类:
- 独立的草稿模型。一个独立的更小模型提出 token(即上面描述的经典方式)。
- 针对目标的辅助草稿器。一个专门为目标模型训练的轻量模型提出 token 或隐藏特征。EAGLE 属于这一类,通常使用单独的检查点。
- 模型集成的草稿器。预测头或模块直接包含在目标检查点中,例如 Medusa 或原生 MTP 模型。
- 免训练或基于检索的方法。候选 token 以算法方式生成,或从提示词和先前生成的上下文中检索,无需训练草稿组件。
让我们更详细地看看这些方法。
Medusa
Medusa 去掉了独立的草稿模型。它在目标模型最终隐藏状态之上附加多个轻量解码头(decoding heads)。每个头预测未来位置(t+2、t+3、t+4……)的 token,而模型的原始 LM 头仍负责紧邻的下一个 token(t+1)。
这些头的候选输出被组合成一棵可能的延续树。目标模型随后使用树注意力(tree attention)在一次前向传播中评估这棵树,树注意力应用一种注意力掩码,以保持每个候选分支内部的因果关系。与经典投机解码方法类似,接受的最长候选前缀将用于下一个解码阶段。
Medusa 有两种形式:
- Medusa-1 仅在冻结的主干 LLM 上训练新的解码头,保持主干权重不变。论文报告在不牺牲生成质量的情况下实现了超过 2.2 倍的加速。
- Medusa-2 联合微调解码头和主干。这提高了草稿准确率,但会修改原始目标模型。论文报告,通过使用保留主干 LLM 能力的训练方案,可实现大约 2.3–3.6 倍的加速。
多 token 预测(MTP)
多 token 预测最初是一种训练目标:模型不再只预测下一个 token,而是被训练成同时预测未来的多个 token。这为模型提供了更密集的训练信号,并且作为附带收益,还内置了用于草稿生成的机制。
DeepSeek-V3 大规模推广了 MTP,它使用顺序的 MTP 模块,在每个预测深度保持完整的因果链。在推理时,这些 MTP 模块可以被重新用作投机解码的原生草稿头,因此模型无需独立的草稿模型、也无需外挂解码头,就能推测自己的下一个 token。由于 MTP 模块与主模型联合训练,它们的预测与目标分布高度一致,这往往能带来较高的接受率。
N-gram 投机
N-gram 投机无需运行独立的草稿模型,也无需添加训练好的预测头,就能生成草稿 token。它会在现有上下文中搜索重复的 token 序列,并复用早前匹配之后的延续部分。
一个典型的实现遵循四个步骤:
- 取当前序列的一个后缀,例如最近的两、三或四个 token。
- 在提示词或先前生成的文本中搜索该后缀的早前出现。
- 复制早前出现之后的 token,将其用作草稿。
- 请目标模型验证这些提出的 token。
当期望的输出重复或紧密遵循提示词中已有的语言时,N-gram 投机很有用。常见示例包括:
- 总结或改写提供的文本
- 编辑代码或配置文件
- 填充预定义的模板
- 回答来自检索文档的问题
- 复现输入中的名称、日期、标识符或技术术语
- 从提示词中已包含的 schema 或示例生成结构化输出
EAGLE
EAGLE(Extrapolation Algorithm for Greater Language-model Efficiency,更高效语言模型的外推算法) 有一个关键观察:自回归在特征层面(倒数第二层的隐藏状态)比在 token 层面更容易建模。因此,轻量的 EAGLE 草稿模型不是预测下一个 token,而是预测下一个特征,然后复用目标模型的 LM 头,将该特征转换为 token 概率。
在随机采样下,当前特征并不能揭示从相应分布中采样到了哪个 token。例如,如果生成文本当前以 I 结尾,采样可能得到 am、always 或 think。下一个特征取决于实际抽取的 token:I am 与 I always 会通向不同的隐藏状态。
EAGLE 的解决办法很简单:告诉模型。除了特征之外,再喂入实际采样到的 token,偏移一个位置,使每个特征与紧随其后的 token 配对。这样,在每一步,草稿头都会看到"这里是隐藏状态,这里是采样器实际从中选取的 token",而这正是判断序列走向所需的缺失信息。
EAGLE 经历了三个版本的演进:
- EAGLE-1:使用小草稿模型进行特征层面的自回归。
- EAGLE-2:增加了上下文感知的动态草稿树。它利用草稿模型的置信度分数,将候选分支分配到更可能被接受的位置。论文报告在评测中实现了大约 3.05–4.26 倍的加速。
- EAGLE-3:放弃了特征预测约束,直接预测 token。它融合了目标模型的低层、中层和高层特征。论文报告,在评测的模型和任务上,相对普通自回归生成实现了大约 3.0–6.5 倍的加速。
EAGLE 被广泛采用,并在 vLLM、MAX 和 SGLang 等框架中原生支持。EAGLE 论文报告了可观的加速,但实际收益取决于目标模型、草稿检查点、工作负载、硬件和服务实现。
如何选择方法
没有普遍最佳的方法。正确的选择取决于你的需求:
| 方法 | 额外的草稿模型 | 是否需要训练 | 说明 |
|---|---|---|---|
| 经典投机解码 | 是 | 否(可选微调) | 匹配一个好的草稿模型可能比较棘手 |
| Medusa | 否(额外解码头) | 是(解码头) | 中等加速 |
| MTP | 否 | 是(预训练时联合训练) | 使用 MTP 训练的模型(例如 DeepSeek-V3) |
| N-gram | 否 | 否 | 零配置收益,面向输入相关任务 |
| EAGLE | 是 | 是(草稿模型) | 报告加速可观,框架支持广泛 |
vLLM、MAX 和 SGLang 等推理框架实现了其中多种方法,因此你可以在投入之前针对自己的工作负载对它们进行基准测试。
自适应投机解码
大多数投机解码部署使用固定的投机 token 数量或草稿步数(γ)。它在基准测试中可能可行,但在生产环境中很少对每个请求都最优。
真实的工作负载是动态的。下一个 token 的可预测性在生成过程中不断变化,批大小也会随着请求进入和离开系统而波动。当草稿模型非常准确且批大小较小时,较大的投机窗口可能效果很好。当接受率下降或批大小增大时,同一个窗口可能变得低效,因为每个不必要的草稿步骤都会在更多序列上消耗额外计算。
因此,固定的 γ 是一种折衷。当 GPU 有空闲算力、可以采用更激进的草稿策略时,它可能过于保守;而当系统繁忙、被拒绝的草稿 token 变成浪费的工作时,它又可能过于激进。
自适应投机解码(adaptive speculative decoding)通过运行时调整投机解码参数来解决这个问题,而不是依赖单一配置。其目标是让投机与当前条件保持一致。
哪些可以自适应?
自适应投机解码可以修改投机过程的一个或多个方面。
- 投机长度。草稿模型在交给目标模型验证之前提出多少个 token。调整这一点是最常见、风险最低的自适应形式。它只改变速度,输出仍与目标模型本应产生的结果完全一致(无损)。例如,当接受率高且资源可用时,系统可以增加投机长度;当接受率下降或系统饱和时,则减少投机长度。
- 接受准则。目标模型验证每个草稿 token 的严格程度。放宽验证会让更多"足够接近"的 token 通过,从而加速生成,但允许输出偏离目标模型的精确分布(有损)。这是用少量质量换取额外速度,应当谨慎使用。
现有的解决方案
自适应投机解码是一个活跃的研究领域,目前的解决方案从生产级特性到研究原型都有。
SGLang 自适应投机解码
SGLang 提供了一个内置的自适应投机解码机制,可在推理期间动态调整投机长度。
每轮验证之后,SGLang 都会测量接受的草稿 token 数量,并维护接受长度的指数移动平均(EMA)。基于该值,它在一小组预定义的投机长度档位之间切换(例如,默认是 [1, 3, 7])。
每个档位都有自己的预捕获 CUDA graph,因此在档位之间切换开销很小,不需要重新捕获图。该方法是被动式的、按批次进行的,并且是无损的,因为它只调整投机长度,并保留原始的验证算法。
AdaSpec
AdaSpec 是一个基于 vLLM 的研究型 LLM 推理系统,它采用更复杂的预测式方法。它在草稿开始之前就尝试预测不同投机长度的效率。
AdaSpec 使用草稿模型的置信度分数来估计接受率,并将这些估计与一个考虑批大小、上下文长度等因素的性能模型相结合。然后它选择一个在满足服务等级目标(SLO)(例如 TPOT 目标)的同时最大化性能的投机配置。
作者报告,在真实服务轨迹上,AdaSpec 持续实现了较高的 SLO 达成率,并相比此前的投机服务系统提供了高达 66% 的加速。
AdaSD
AdaSD 是一种研究型解码算法,主要面向开箱即用的草稿模型与目标模型配对。与大多数自适应方法不同,AdaSD 同时自适应投机长度和接受准则。它引入了两个由运行时统计量派生的动态调整阈值:
- 草稿 token 熵决定草稿模型应何时停止生成额外的投机 token。
- 草稿分布与目标分布之间的 Jensen–Shannon(JS)距离决定一个草稿 token 是否足够接近目标分布、可以被接受。
由于 AdaSD 可以接受不严格满足原始投机解码接受规则的 token,它是一种有损方法。作者报告,在将准确率下降限制在 1.8% 以内的同时,相比经典投机解码实现了高达 1.46 倍的加速。
AdaSD 要求草稿模型和目标模型共享相同的词表。这是因为熵和 JS 距离的计算直接作用于两个模型产生的 token 概率分布。如果词表不同,这些分布就无法一致地比较。
何时值得使用自适应投机解码?
当服务条件随时间显著变化时,自适应投机解码最为有用。示例包括突发流量模式、快速变化的批大小、混合工作负载,或接受率大幅波动的应用。
在这些情况下,动态适应当前条件通常优于任何单一的固定投机长度。另一方面,如果你的工作负载稳定,并且已经针对你的模型和硬件调整好了静态 γ,自适应机制可能只会带来边际收益。
与一般的投机解码一样,唯一可靠的做法是在投入生产前,在你自己模型、硬件和工作负载下进行基准测试。
其他资源
- Looking back at speculative decoding
- Adaptive Speculative Decoding in SGLang
- AdaSpec: Adaptive Speculative Decoding for Fast, SLO-Aware Large Language Model Serving
- AdaSD: Adaptive Speculative Decoding for Efficient Language Model Inference
- EAGLE: Speculative Sampling Requires Rethinking Feature Uncertainty
- Fast Inference from Transformers via Speculative Decoding
- Accelerating Large Language Model Decoding with Speculative Sampling