从一次在线推理延迟说起
运营一个面向企业客户的代码生成服务时,你可能会遇到这样的场景:模型是 70B 量级的开源底座,单次请求的生成长度动辄数百 token,用户对首 token 延迟和总延迟都敏感。基线方案是标准的自回归解码,每生成一个 token 都要把全部模型参数从高带宽内存搬到计算单元,串行执行 K 次前向传播。当并发请求增多,GPU 的算力利用率却不高,因为每一步都在等待前一步的输出。
投机解码(speculative decoding)试图打破这种串行瓶颈。它引入一个更小的草稿模型(draft model)先快速生成若干候选 token,再用大模型并行验证这些候选,一次前向传播可以接受多个 token,从而减少大模型的串行步数。Leviathan 等人 2022 年提出的投机解码算法在 T5-XXL 上取得了 2~3 倍加速,且不改变输出分布。但草稿模型从哪里来?这成了工程上第一个要做的决策。
草稿模型的三种构建路线
在线服务中,草稿模型的选择通常有三条路线:独立小模型、自推测架构(如 Medusa 和 EAGLE)、以及多模型投机。独立小模型指从同一模型家族中选一个参数量更小的版本,例如用 LLaMA2-7B 作为 LLaMA2-70B 的草稿模型。自推测架构则是在大模型本体上附加额外的解码头或特征预测模块,让大模型自己生成草稿。多模型投机指同时运行多个不同规模的模型,按某种策略选择草稿。
三条路线的核心差异在于:草稿模型的训练成本、与大模型输出分布的匹配程度、以及推理时的额外开销。独立小模型几乎不需要额外训练,但小模型与大模型的分布差异可能较大,接受率不高;自推测架构需要针对性微调,但草稿质量更高;多模型投机则介于两者之间,但显存和调度复杂度更高。
独立小模型:简单但受限于分布匹配
独立小模型是最直接的方案。以 LLaMA2 系列为例,7B 模型可以作为 70B 模型的草稿,因为两者共享相似的 tokenizer 和训练数据,分布相对接近。但工程上很快会遇到两个问题。
第一个问题是小模型的开销。EAGLE 论文指出,用 7B 模型作为 13B 模型的草稿,由于 7B 模型本身的前向传播开销过高,整体速度反而比原始自回归解码更慢。这意味着草稿模型必须足够小,才能让草稿阶段的延迟低于大模型验证阶段的收益。第二个问题是分布偏移。小模型是在通用语料上训练的,当目标任务是代码生成或数学推理时,小模型对特定领域的分布预测往往不准确,导致接受率下降。
接受率直接决定加速比。在投机解码中,大模型验证草稿 token 时,如果某个 token 的概率低于采样阈值,就会拒绝该 token 及其后续所有候选,回退到该位置重新生成。接受率低意味着大模型经常只接受一两个 token,串行步数减少有限,加速比自然上不去。
独立小模型的另一个隐患是维护成本。如果大模型升级了版本,小模型可能不再匹配,需要重新训练或选择新的草稿模型。对于在线服务团队来说,这意味着每次模型更新都要重新评估草稿模型的适用性。
自推测架构:Medusa 与 EAGLE 的机制
自推测架构试图解决独立小模型的分布匹配问题。Medusa 由 Cai 等人 2024 年提出,其核心是在大模型的倒数第二层特征之上添加多个并行的解码头(MLP),每个头预测后续第 k 个 token 的分布。这些头共享大模型的隐藏层,因此草稿生成的开销远小于独立小模型。Medusa 使用树状注意力机制构建多个候选延续,并在一次前向传播中并行验证。
Medusa 提供了两种微调级别。Medusa-1 在冻结主干模型的情况下微调解码头,不改变大模型的输出分布,论文报告在多个模型上取得超过 2.2 倍加速;Medusa-2 则联合微调主干和解码头,预测精度更高,加速比提升到 2.3~3.6 倍,但需要特殊的训练配方来保持主干模型的能力。
EAGLE 则从另一个角度切入。它观察到在特征层面(倒数第二层)做自回归比在 token 层面更容易,因为特征序列比 token 序列更规则。但特征层面的自回归存在不确定性,EAGLE 通过将 token 序列向前移动一个时间步作为额外输入来解决这种不确定性,从而更精确地预测下一个特征。EAGLE 在 LLaMA2-Chat 70B 上取得了 2.7~3.5 倍的延迟加速比,吞吐量翻倍,且保持输出分布不变。
自推测架构的代价是训练。Medusa 需要针对每个大模型训练解码头,EAGLE 也需要训练一个轻量的特征预测模块。虽然训练数据量远小于从头训练一个小模型(EAGLE 论文提到其训练仅需 2~4B token,而 TinyLLaMA 训练了 3000B token),但工程上仍然需要准备训练数据、GPU 资源和微调流程。
多模型投机:并行与调度的复杂度
多模型投机是第三种路线,它同时运行多个草稿模型,根据输入或上下文动态选择最合适的草稿。这种做法的动机是:不同领域的输入可能适合不同的草稿模型,例如代码生成任务用代码小模型,对话任务用通用小模型。
但多模型投机引入了额外的调度复杂度。在线服务需要决定何时切换草稿模型,如何同步多个模型的 KV 缓存,以及如何分配 GPU 显存。多个草稿模型同时驻留显存,会挤占大模型本体的空间,可能降低批处理大小,反而损害整体吞吐。
从工程角度看,多模型投机更适合那些输入分布高度异构、且单个草稿模型无法覆盖的场景。如果输入以代码为主,一个专门训练的代码小模型可能就足够了,不需要多模型。
对比表格:三条路线的工程权衡
下表从训练成本、接受率、显存开销、加速比和适用场景五个维度对比三种方案。数值均来自资料中报告的定性或定量结果,未提供数字的用定性描述。
| 维度 | 独立小模型 | Medusa 自推测 | EAGLE 自推测 | 多模型投机 |
|---|---|---|---|---|
| 训练成本 | 低(通常无需训练) | 中(微调解码头,2~4B token 量级) | 中(训练特征预测模块,2~4B token 量级) | 高(需训练多个草稿模型) |
| 接受率 | 低~中(受分布偏移影响) | 中(Medusa 约 0.6) | 高(EAGLE 约 0.8) | 中~高(取决于选择策略) |
| 显存开销 | 低(小模型本身较小) | 低(仅增加少量解码头) | 低(仅增加特征预测模块) | 高(多个模型同时驻留) |
| 加速比 | 受小模型开销限制,可能为负 | 2.2x(Medusa-1),2.3~3.6x(Medusa-2) | 2.7~3.5x(LLaMA2-Chat 70B) | 视选择策略,可能接近最佳单模型 |
| 适用场景 | 大模型与小模型同系列且分布接近 | 需要无损加速、可接受微调 | 需要高接受率、可接受微调 | 输入分布高度异构 |
表格中的接受率数据来自 EAGLE 论文的对比,Medusa 的接受率约为 0.6,EAGLE 约为 0.8。注意这些数字是在特定模型和任务上测得的,不同场景下会有波动。
失效边界:低接受率与长序列
投机解码并非在所有情况下都有效。最明显的失效场景是低接受率。如果草稿模型的预测与大模型差异很大,大模型频繁拒绝 token,那么草稿阶段的开销就变成了纯浪费。EAGLE 论文指出,当草稿模型与大模型不匹配时(例如用 7B 草稿加速 13B 模型),加速比可能低于 1,即比原始解码更慢。
长序列是另一个失效边界。投机解码的草稿长度通常是固定的(例如 4 或 5 个 token),当生成序列很长时,草稿阶段的累计开销会放大。此外,长序列下 KV 缓存占用增加,如果草稿模型也有自己的 KV 缓存,显存压力会更大。对于自推测架构,解码头是在固定上下文长度下训练的,当输入序列超过训练长度时,特征分布可能偏移,接受率下降。
另一个容易被忽略的问题是采样温度。EAGLE 论文提到,Medusa 的非贪婪生成不保证无损,而 EAGLE 在温度 1 下仍保持分布一致。如果服务需要支持随机采样(温度大于 0),自推测架构的验证机制必须正确实现拒绝采样,否则会改变输出分布。
工程调优方法
在实践中,选择草稿模型后还需要调优几个关键参数。第一个是草稿长度(draft length)。草稿越长,单次验证能接受的 token 数上限越高,但草稿阶段的开销也越大。通常需要根据接受率和模型延迟做实验,找到一个平衡点。
第二个是接受阈值。投机解码的验证阶段使用拒绝采样,接受概率与草稿 token 在大模型下的概率成正比。如果阈值设置不当,可能过度拒绝或过度接受,影响输出分布。对于贪婪解码(温度 0),接受条件简化为草稿 token 是否是大模型的最优 token,此时接受率更容易预测。
第三个是批处理与并发。在线服务通常使用连续批处理(continuous batching)来提高吞吐,投机解码需要与批处理调度器集成。当多个请求同时到达时,草稿模型的推理可以与大模型的验证重叠,从而隐藏草稿延迟。EAGLE 论文提到其方法在批处理下吞吐量翻倍,说明调度策略对最终加速比有显著影响。
此外,监控指标也很重要。生产环境应跟踪草稿接受率、平均接受 token 数、草稿阶段延迟、验证阶段延迟以及端到端加速比。如果接受率突然下降,可能是输入分布偏移或模型更新导致,需要重新评估草稿模型。
一个贯穿场景的流程图
以代码生成服务为例,展示投机解码的完整流程。假设我们选择了 EAGLE 自推测架构,草稿模型是特征预测模块,大模型是 70B 底座。
flowchart TD
A[接收代码生成请求] --> B[初始化 KV 缓存]
B --> C[EAGLE 草稿模块预测下一个特征]
C --> D[使用大模型 LM Head 生成草稿 token 序列]
D --> E[大模型并行验证草稿 token]
E --> F{接受率是否足够?}
F -- 是 --> G[接受多个 token,更新 KV 缓存]
F -- 否 --> H[拒绝部分 token,回退到第一个被拒位置]
G --> I{是否生成结束?}
H --> I
I -- 否 --> C
I -- 是 --> J[返回生成结果]
在这个流程中,关键转折点是验证阶段。EAGLE 草稿模块基于当前上下文预测下一个特征,再用大模型的 LM Head 将其转换为 token 分布,采样得到草稿 token。大模型并行验证这些 token,如果接受率高,一次验证可以推进多个 token,大幅减少串行步数。如果接受率低,则回退到被拒位置,草稿模块重新预测。
工程上,草稿模块的推理延迟必须远小于大模型验证的延迟,否则整体加速比会被拖累。EAGLE 的特征预测模块非常轻量,通常只有几亿参数,因此草稿阶段的开销很小。
替代方案与权衡
除了上述三种草稿模型构建路线,还有一种不依赖草稿模型的方法:Lookahead 解码。它使用 n-gram 和 Jacobi 迭代来生成草稿,无需训练,但接受率更低(EAGLE 论文提到 Lookahead 的接受率低于 Medusa)。Lookahead 的优势是零训练成本,适合快速部署,但加速比有限,且只支持贪婪解码。
选择哪种方案取决于服务的具体约束。如果团队没有训练资源,独立小模型或 Lookahead 是可行的起点,但需要接受较低的加速比。如果追求最高加速比且能承担微调成本,EAGLE 或 Medusa-2 是更好的选择。如果输入分布高度异构,多模型投机可能值得尝试,但要注意显存和调度开销。
最终,投机解码的收益取决于草稿模型的接受率与开销之间的平衡。接受率越高,草稿阶段开销越低,加速比越大。但接受率受限于草稿模型与大模型的分布匹配程度,而分布匹配又受限于训练数据和任务类型。在线服务需要持续监控这些指标,并在模型更新或流量变化时重新调优。
尚未解决的问题
投机解码仍有一些开放问题。例如,如何自动选择最优的草稿长度和接受阈值?目前主要靠经验调参。如何让自推测架构适应更长的上下文?EAGLE 和 Medusa 的训练长度有限,长序列下的性能尚未充分验证。此外,多模型投机中的动态选择策略仍缺乏理论指导,更多是工程试探。
对于在线服务团队,一个务实的建议是:先用独立小模型或 Lookahead 快速验证投机解码的收益,再根据瓶颈决定是否投入训练资源升级到自推测架构。加速比不是唯一的指标,训练成本、显存开销和维护复杂度同样重要。