Administrator
发布于 2026-07-07 / 1 阅读
0
0

推测解码为什么能加速大模型推理

推测解码为什么能加速大模型推理

English Version

大模型生成文本有一个天然限制:它通常是一个 token 一个 token 往外吐。

这叫自回归生成。前一个 token 出来以后,模型才能继续生成下一个 token。结果就是,哪怕 GPU 很强,decode 阶段也容易变成一段很长的串行过程。

推测解码要解决的,就是这个串行瓶颈。

推测解码(Speculative Decoding):让一个更小、更快的草稿模型先猜多个 token,再让目标大模型一次性验证这些 token。猜对的直接接受,猜错的由目标模型修正。它的目标是用更少的大模型前向次数生成更多 token。

先猜,再验证

我通常这样解释推测解码:小模型先做草稿,大模型当审核。

假设目标模型本来要生成“我爱中国”:

Step 1: 输入“我”,输出“爱”
Step 2: 输入“我爱”,输出“中”
Step 3: 输入“我爱中”,输出“国”
Step 4: 输入“我爱中国”,输出 EOS

传统方式需要大模型跑 4 次。

推测解码会让草稿模型先猜:“爱 中国 EOS”。然后目标模型把这几个候选 token 放在一起验证。如果前两个 token 命中,第三个 token 没命中,那也不是失败。系统至少用一次目标模型前向确认了两个 token,还顺手修正了错误位置。

Draft Model(草稿模型):负责快速提出候选 token 的小模型或轻量模块。它不决定最终输出质量,只负责提高“猜中”的概率。

Target Model(目标模型):真正要部署的大模型。最终接受或修正 token 的权力在它手里,所以推测解码可以在数学上保持目标模型的输出分布。

接受率决定收益

推测解码能不能加速,关键看接受率。

接受率(Acceptance Rate):草稿模型提出的候选 token 中,被目标模型接受的比例。比如草稿猜 5 个 token,目标模型接受 3 个,接受率就是 0.6。

接受率越高,一次目标模型验证能“带走”的 token 越多,加速越明显。接受率太低,就会出现小模型白忙活的情况:草稿计算花了时间,但目标模型没接受几个。

这里有一个容易误解的点:草稿模型不是越大越好。草稿模型太小,猜不准;太大,又把节省下来的计算成本吃回去了。真正要找的是“足够便宜,同时足够像目标模型”的平衡点。

Medusa:不额外部署小模型

Medusa 的思路很工程化:既然额外部署一个草稿模型会让系统复杂,那能不能在原模型上加多个预测头?

Medusa:一种给大模型增加多个解码头的推理加速框架。它让模型不仅预测下一个 token,还尝试预测后续几个 token,然后再做验证。

它的优势是部署形态更统一,不一定要维护一个独立 draft model。对很多线上系统来说,这比“再挂一个小模型”更容易管理。

但它也有代价:你要训练或适配这些额外 decoding heads,还要处理 Tree Attention 这类验证结构。也就是说,Medusa 简化的是模型部署数量,不是把工程复杂度完全消灭。

Tree Attention(树状注意力):可以理解为一次性验证多条候选 token 路径时使用的 attention 结构。它不是简单的一条序列,而是要处理候选树上的分支关系。

EAGLE:在特征层做草稿

EAGLE 的路线更进一步。它不是只在 token 层面硬猜,而是利用目标模型的中间特征来预测后续 token。

EAGLE:一种基于特征预测的推测解码方法。它用轻量 draft 模块预测后续特征和 token,再交给目标模型验证,从而提升候选质量。

EAGLE-1 和 EAGLE-2 已经能带来明显加速,但在大 Batch 场景下会遇到一个问题:当 GPU 已经接近 Compute-Bound,草稿阶段带来的额外计算可能抵消收益。

Compute-Bound(计算受限):系统瓶颈在计算能力上,GPU 算力已经接近吃满。继续增加额外计算,不一定能换来更高吞吐。

Memory-Bound(内存受限):系统瓶颈在显存带宽或内存访问上,计算单元没有完全吃满。推测解码在这种场景下更容易把空闲算力利用起来。

教案里有个判断很关键:Batch 小的时候,decode 阶段更容易 memory-bound,推测解码加速明显;Batch 已经很大时,GPU 接近 compute-bound,推测解码的边际收益会下降。

这也是我会纠正的一个常见说法:推测解码不是任何场景都一定加速。它是否划算,要看 batch size、草稿成本、接受率和目标模型当前瓶颈。

EAGLE-3 解决了误差累积

EAGLE-1 和 EAGLE-2 的一个隐藏问题,是训练和推理不一致。

训练时,draft 模块看到的是目标模型的真实特征;推理时,它看到的可能包含自己上一步预测出来的特征。一步错,后面就会累积误差,接受率逐步下降。

EAGLE-3 的改进点是 Training-time Test。

Training-time Test(训练时测试):在训练阶段模拟推理时的多步生成,让 draft 模块提前适应“自己预测过的中间状态”。这样推理时遇到误差累积,模型不至于马上崩掉。

这个思路很像训练方式从“看标准答案做题”变成“闭卷模拟考试”。模型训练时就见过自己可能犯错的路径,线上推理时稳定性更好。

教案里的结论也很明确:EAGLE-1/2 在 Batch=64 时几乎没有吞吐收益,而 EAGLE-3 仍能保持约 1.38x 的吞吐提升。这说明它不是只在实验室小 batch 里好看,而是更贴近高并发生产场景。

和 vLLM 结合时,难点不只是算法

把推测解码接进 vLLM,不是把论文名字写进启动参数就结束了。

它至少有三个工程冲突。

第一,草稿阶段和 Continuous Batching 的节奏不同。草稿阶段常常更适合小 batch 或 micro-batch,而 vLLM 主流程希望动态 batch 保持 GPU 利用率。

第二,Medusa 或 EAGLE 的验证阶段可能需要 Tree Attention、特殊 mask 或自定义 attention backend。

第三,草稿模型和目标模型都会占显存,也都会产生 KV Cache。这里又回到了第一篇文章讲的 PagedAttention:如果没有统一的 KV Cache 管理,推测解码可能把显存压力放大。

一个简化的 vLLM + EAGLE iteration 可以这样理解:

# 中文注释:从当前 batch 里挑出适合做推测解码的请求
draft_requests = select_for_speculation(current_batch)

# 中文注释:轻量 EAGLE 模型先生成 3 到 5 步候选 token 树
for step in range(max_draft_tokens):
    draft_features = eagle_model.forward(target_features, previous_tokens)
    draft_tokens = sample(draft_features)

# 中文注释:目标模型并行验证候选 token,并返回被接受的长度
verified_tokens, accepted_length = tree_verify(
    draft_tokens,
    target_model_logits,
)

# 中文注释:只保留被接受 token 对应的 KV blocks,释放被拒绝路径占用的 blocks
update_block_table(request, accepted_length)

这段流程里,算法收益和系统调度绑在一起。只要候选选择、验证、显存释放任意一环做得粗糙,加速都可能打折。

用不用呢?

推测解码的本质不是“让模型乱猜”,而是“用便宜计算换掉一部分昂贵计算”。

我会用四个问题判断它是否值得上生产:

  1. 当前 decode 阶段是 memory-bound 还是 compute-bound?
  2. 草稿模型或草稿头的成本有多低?
  3. 接受率是否足够稳定?
  4. 大 batch 下吞吐是否真的提升,而不是只优化了单请求延迟?

如果这些问题回答不清楚,推测解码很容易从加速器变成额外负担。反过来,如果接受率稳定、草稿成本低、KV Cache 管理也跟得上,它确实是大模型推理服务里很有价值的一把刀。


评论