一个在线聊天服务最容易暴露大模型推理的矛盾:GPU 上已经放着完整模型,请求也源源不断,但单个回答仍然要一个 Token 接一个 Token 地向前生成。模型参数规模当然影响每次计算的成本,更难绕开的约束却来自自回归解码本身——第 (t+1) 个 Token 的概率分布依赖前面已经确定的序列,因此生成阶段存在天然的串行依赖。
假设一个目标模型正在回答一段较长的问题。传统解码每完成一步,只能把新得到的一个 Token 追加到序列,再进入下一轮前向计算。即使 KV Cache 已经避免重复计算历史 Token 的 Key 和 Value,模型权重仍需要参与每一轮新 Token 的计算。于是,单次前向已经很快时,串行轮数仍会成为端到端延迟的主要组成部分。Speculative Decoding,也就是推测解码,试图减少的正是这些必须等待上一轮结束后才能开始的目标模型解码轮次。
自回归解码为什么难以直接“一次生成多个 Token”
直觉上,可以让目标模型一次输出四个或八个 Token,从而把四次计算压缩成一次。但标准自回归模型并没有同时知道未来多个位置的最终输入。生成第一个新 Token 时,第二个位置还不知道第一个位置最终会选什么;第三个位置又依赖前两个位置。训练时可以并行处理一整段已知序列,是因为每个位置的真实前缀已经给定,而在线生成时,未来前缀尚未产生。
这也是 KV Cache 只能解决一部分问题的原因。它缓存历史序列的中间状态,让新一轮解码不必重新处理全部上下文,却不能消除“先确定 Token A,才能把 A 作为前缀继续决定 Token B”的依赖链。对于长回答,目标模型仍需要执行大量串行的小步解码。
Speculative Decoding 引入了一个关键变化:未来前缀虽然还没有被目标模型确认,但可以先由更便宜的机制提出候选。候选可能来自一个较小的 Draft Model,也可能来自附加预测头或特征预测模块。目标模型随后拿到一段已经具体化的候选序列,因此能够像训练阶段处理已知序列那样,在一次前向过程中并行计算多个候选位置对应的概率分布。
这里的“并行验证”不等于让大模型简单判断一句话“对不对”。目标模型仍然计算自己的 Token 分布,只是候选序列提前提供了多个位置的输入。对于贪心解码,可以逐位置比较候选是否与目标模型会选择的 Token 一致;对于采样解码,标准 speculative sampling 会根据 Draft 分布与目标分布执行接受和拒绝校正,使最终采样结果保持目标模型要求的分布性质。只要验证规则正确,Draft 负责的是提议,不是替代目标模型决定最终输出。
一轮推测解码内部到底发生了什么
继续看在线聊天服务。目标模型负责最终回答,旁边部署一个成本更低的 Draft Model。某个请求已经生成了前缀“推测解码的核心是”,系统希望接着向前生成。
Draft Model 先自回归地产生一小段候选,例如连续提出若干 Token。因为 Draft 更小或计算路径更轻,这几步的总成本可能低于让目标模型逐个生成同样数量 Token 的成本。系统随后把“原始前缀 + 候选序列”一次送给目标模型。目标模型并行得到候选各位置对应的概率信息,验证逻辑从第一个候选开始向后检查,连续接受满足条件的 Token;一旦某个位置被拒绝,就停止继续接受其后的候选,因为后续候选建立在已经失效的前缀上。
被接受的部分直接追加到输出序列。发生拒绝时,系统根据目标模型的结果为拒绝位置产生修正 Token,并丢弃依赖错误前缀的剩余候选。下一轮推测再从新的已确认前缀开始。若一轮中的多个候选连续通过,目标模型就用一次验证前向推动了多个 Token 的有效进展;若第一个候选就失败,这一轮几乎没有减少串行轮次,反而增加了 Draft 与验证协调成本。
flowchart TD
A[聊天请求进入解码] --> B[读取已确认前缀]
B --> C[Draft 生成候选 Token]
C --> D[目标模型并行计算候选位置]
D --> E{候选能否连续接受}
E -->|连续接受| F[追加多个已确认 Token]
E -->|中途拒绝| G[保留已接受前缀]
G --> H[目标模型生成修正 Token]
H --> I[丢弃失效后缀]
F --> J{是否生成结束}
I --> J
J -->|否| B
J -->|是| K[返回完整回答]
这个流程里有两个容易被忽略的状态边界。第一,只有“已确认前缀”能够成为下一轮稳定输入,未经验证的 Draft 候选不能提前对外返回。第二,KV Cache 也必须与接受结果保持一致:已接受 Token 对应的缓存状态可以继续使用,被拒绝候选之后产生的状态必须回收或覆盖,否则下一轮解码会建立在错误历史上。
Acceptance Rate 很重要,但它不是最终优化目标
Acceptance Rate 通常用来描述 Draft 候选有多大比例能被目标模型接受。假设每轮 Draft 提议四个 Token,一类请求经常能连续接受三个或四个,目标模型的一次验证就能推进较长距离;另一类请求常在第一个位置失败,系统仍需要频繁回到目标模型主导的逐步生成。前者更容易从推测解码获益。
但只盯着接受率会产生错误的工程决策。假设团队为了让 Draft 更接近目标模型,把一个很轻的小模型替换成接近目标模型规模的模型。接受率可能提高,Draft 阶段本身却变慢,同时还占用更多显存。最终每个有效 Token 的平均成本未必下降,甚至可能高于直接运行目标模型。
更接近实际服务目标的指标是“为了产出一个最终确认 Token,系统总共付出了多少时间和资源”。它至少包含 Draft 生成时间、目标模型验证时间、拒绝后的修正成本、KV Cache 管理成本、调度等待以及两套计算路径带来的显存占用。在高并发服务中,还要考虑 Draft 占用的 GPU 计算是否挤压了目标模型原本可以处理的其他请求。
因此,接受率需要与每轮平均接受 Token 数、Draft 延迟、验证批次大小、端到端首 Token 延迟、每输出 Token 延迟和整体吞吐一起观察。一个接受率略低但极轻量的 Draft,可能比高接受率的大型 Draft 更适合生产。反过来,如果请求分布稳定、候选高度可预测,投入更多 Draft 计算也可能得到更好的整体收益。
一个简单的假设例子可以说明这种关系。若传统方式需要目标模型串行执行四轮才能确认四个 Token,而推测方式用较低成本生成四个候选,再通过一次目标模型验证接受其中大部分,那么串行等待会减少。但如果四个候选大多被拒绝,系统既支付了 Draft 成本,又没有减少多少目标模型轮次。推测解码的收益来自“低成本提出多个高概率候选”和“目标模型能高效批量验证”同时成立,而不是来自候选数量本身。
Draft Model、Medusa 与 EAGLE 的路线差异
推测解码不是单一实现。最直观的路线是部署独立 Draft Model,让它生成候选;Medusa 把多个预测头接到原模型体系中,尝试在不维护完整第二模型的情况下提出多个候选;EAGLE 则把候选预测推进到特征表示层面,希望利用更丰富的中间信息改善推测质量。它们都在减少目标模型串行解码轮数,但成本落在不同位置。
| 路线 | 候选从哪里来 | 主要优势 | 主要成本与风险 | 更适合的判断条件 |
|---|---|---|---|---|
| 独立 Draft Model | 更小、更快的自回归模型 | 思路直接,可独立选择 Draft 容量 | 需要加载和调度第二套模型,存在额外显存与部署复杂度 | 已有兼容小模型,且 Draft 明显快于目标模型 |
| Medusa | 原模型上的多个轻量预测头 | 不必维护完整独立 Draft 模型,候选生成路径更紧凑 | 需要额外训练或适配预测头,并处理多候选验证 | 能控制模型训练或适配流程,希望降低双模型运维成本 |
| EAGLE | 基于中间特征预测后续候选 | 利用特征信息改善候选质量,目标仍是提高有效接受长度 | 特征预测、缓存和推理引擎集成更复杂 | 愿意承担更高实现复杂度来换取更好的候选效率 |
输入材料所列 Medusa 与 EAGLE 论文都报告了相对传统自回归解码的明显加速结果,但这些数字来自各自实验设置,不能直接当作任意生产环境的固定收益。模型结构、硬件、batch 大小、输出长度、采样参数和请求分布都会改变 Draft 成本与接受行为。对线上系统而言,论文结果更适合证明“路线具有加速潜力”,而不是替代本地基准测试。
独立 Draft Model 的优点是边界清晰:可以直接测量 Draft 每秒生成能力、目标模型验证成本以及接受率。但它也最容易暴露资源冲突。当目标模型本身已经占满 GPU 显存时,再放一个 Draft 可能迫使系统降低 batch、缩短 KV Cache 容量或改用额外设备。此时单请求延迟可能下降,整机吞吐却未必增加。
Medusa 和 EAGLE 试图缩短或改变候选生成路径,本质上是在重新分配“猜测成本”。它们不是免除成本,而是希望候选生成与目标模型已有表示共享更多计算或信息。选择哪条路线,应从现有模型是否可训练、推理引擎是否支持、显存余量、请求类型和维护成本出发,而不是只比较论文中的峰值加速比。
接入推理引擎时,KV Cache 与批处理比算法名字更棘手
在单请求示例中,推测解码看起来只是“Draft 猜一段,Target 验一段”。真实在线服务还同时维护数十甚至更多不同进度的请求,每个请求都有自己的 KV Cache、停止条件、采样状态和输出流。推测解码引入后,每个请求又多出“未验证候选”这一临时状态。
KV Cache 的处理必须区分已确认和未确认区域。Draft 可能为候选 Token 建立自己的缓存,目标模型验证候选时也会产生对应状态。若候选全部接受,这些状态可以自然推进;若在中间位置拒绝,拒绝点之后的状态不再属于有效序列,需要被正确截断。缓存管理如果只追加不回滚,会浪费显存;如果索引处理错误,则可能让后续生成读取到已经失效的上下文。
连续批处理又增加一层调度问题。普通解码中,每个活跃请求通常每轮推进一个 Token,调度器容易把多个请求组成批次。加入推测解码后,不同请求每轮可能提出不同数量候选,也可能接受不同长度。有的请求一次前进多个 Token,有的请求立即拒绝,还有的请求已经触发结束条件。调度器需要在保持 GPU 利用率的同时处理这些不规则进度。
这意味着单请求 benchmark 与线上吞吐可能出现方向不同的结果。单请求环境没有排队竞争,减少目标模型串行轮次往往容易体现收益;高并发环境中,目标模型验证一段候选会改变每轮计算形状,Draft 也会消耗计算资源。如果原本的 continuous batching 已经让 GPU 长时间处于高利用率,推测解码减少“轮数”并不必然等价于整机完成更多请求。
工程上更稳妥的做法,是把推测解码当作调度器的一种执行模式,而不是一个全局开关。系统可以依据输出长度预测、请求优先级、当前 batch 压力、Draft 可用性和近期接受表现决定是否启用。短回答或高峰期请求可能直接走普通解码,长生成且候选稳定的请求再进入推测路径。是否值得动态切换,需要通过实际流量验证,不能只凭理论判断。
哪些请求会让加速效果快速退化
短输出是最直观的反例。如果请求只需要生成几个 Token,Draft 初始化、候选生成和验证协调本身就占据可观比例的时间。还没来得及通过多轮高接受率摊薄成本,请求已经结束。对于分类标签、极短结构化字段或只补全少量字符的任务,普通解码可能更简单。
Draft 与目标模型分布不匹配也会降低收益。在线聊天服务的 Draft 若主要适应通用对话,而流量突然转向专业代码、数学符号或冷门领域,候选更容易在早期被拒绝。此时 Acceptance Rate 下降只是表面现象,更直接的信号是每轮平均有效推进 Token 数减少,而 Draft 计算仍然照常发生。
高随机性的采样设置也会改变接受行为。温度、top-p 等策略会影响候选与目标分布的重合程度。推测采样算法可以保持正确的目标分布,但正确不代表一定高效:当 Draft 与目标模型给出的概率质量差异较大时,更多候选会进入拒绝与修正路径。
复杂代码和多步推理任务也不能简单归类为“必然不适合”。更准确的说法是,这类任务中局部 Token 选择可能更敏感,Draft 与 Target 的差异可能增大,从而降低连续接受长度;但最终表现仍取决于具体模型对、提示分布和解码配置。生产系统应按真实请求类别分桶测量,而不是给整个任务类型贴固定标签。
另一个风险来自资源占用。独立 Draft 模型需要额外显存,如果它挤压了目标模型 KV Cache 可用空间,系统可能不得不降低最大并发或更频繁地调度缓存。结果可能是单请求每 Token 延迟变好,但等待队列变长。只看单条请求的 speedup 会遗漏这种系统级退化。
生产环境应该观察什么,而不是只看“快了几倍”
验证推测解码是否有效,至少要把指标分成请求级、解码级和资源级。请求级关注首 Token 延迟、完整响应延迟以及不同输出长度分位数;解码级关注每轮 Draft 长度、连续接受长度、拒绝位置分布和每个最终 Token 需要多少次 Target 验证;资源级则观察 GPU 利用率、显存占用、KV Cache 使用率、batch 大小和等待队列。
Acceptance Rate 可以保留,但更建议同时记录“平均每次 Target 验证确认多少 Token”。两个系统都可能有相似接受率,却因为候选长度不同而得到完全不同的有效推进量。还要记录 Draft 阶段占总延迟的比例:当 Draft 耗时持续升高时,继续提升候选准确率可能已经没有意义。
上线前的基准测试应至少覆盖三种负载:单请求长生成、固定并发长生成,以及接近真实线上长度分布的混合请求。单请求测试回答“理论上能否降低一条请求的串行延迟”;固定并发测试观察批处理兼容性;混合流量测试才能暴露短请求、高峰排队和缓存竞争带来的系统级影响。
回滚路径同样重要。推测解码通常不应成为请求成功的必要条件。Draft 模型不可用、缓存资源不足或接受表现异常时,系统应能够退回标准目标模型解码,而不是让整个生成服务失败。这样做也便于灰度:先让少量请求启用推测路径,与普通解码对照端到端延迟和吞吐,再逐步扩大范围。
如何判断一个在线服务值得启用推测解码
对于一个已经使用 KV Cache 和连续批处理的聊天服务,可以先问三个问题。第一,当前瓶颈是否真的来自目标模型串行解码,而不是请求排队、网络传输、预填充阶段或外部工具调用。第二,是否存在一个足够便宜且与目标分布足够接近的候选生成机制。第三,推理引擎能否正确处理候选验证、缓存回滚和不规则 batch,而不会破坏现有吞吐。
如果答案都偏向肯定,推测解码值得进入基准测试。长文本生成、持续对话、代码补全等需要较多解码步的场景通常更有机会摊薄额外开销;但具体收益仍要由真实流量决定。RAG 问答也不能因为带有“RAG”标签就默认适合:如果答案通常很短,检索耗时才是主导瓶颈,优化解码阶段的收益可能有限。
Speculative Decoding 最值得记住的不是“用小模型替大模型生成”,而是把一部分串行决策转换成“低成本提出候选 + 高成本模型批量确认”。它没有消除目标模型,也没有改变自回归模型对已确认前缀的依赖。它真正减少的是目标模型必须串行等待的解码轮次。
因此,部署决策不应停在“是否支持 Speculative Decoding”。更有价值的问题是:在当前请求分布下,一次目标模型验证平均能换来多少个最终 Token,这些 Token 为系统节省的时间,是否大于 Draft、验证、缓存和调度新增的全部成本。只有这个账在真实负载下成立,推测解码才从一个漂亮的算法思路变成有效的生产优化。