推测解码:用一个“小模型”骗出 3 倍推理速度

举报
yd_214609086 发表于 2026/10/30 10:28:43 2026/10/30
【摘要】 大模型推理慢,瓶颈不在算力总量,而在自回归的串行依赖:每个 token 都得等上一个算完。推测解码用一个几 B 的小模型先“蒙”一串 token,再让大模型批量验证,猜对的直接采纳,猜错的从错误点重算。猜中率越高,加速比越大。下面说它的数学原理、工程上会踩的坑,以及 vLLM 和 llama.cpp 里的实测数字。

一、慢在哪

你拿一个 70B 的模型做推理,生成 500 个 token,每个 token 大概 30-50ms(取决于硬件),总共 15-25 秒。你觉得慢是因为模型大,参数多,计算量大。

这个直觉对了一半。

真正的瓶颈是自回归。生成第 N 个 token 时,模型需要看到前 N-1 个 token 的 KV Cache,然后做一次 forward pass,输出第 N 个 token。这个过程严格串行:算第 100 个 token 的时候,你没法顺手把第 101 个也算出来,因为第 101 个的输入依赖第 100 个的输出。

结果是:GPU 有 80GB 显存、几千 TFLOPS 算力,生成每个 token 时却只用得上算力的一小部分,大部分时间在等。算力不是不够,是使不上劲。

那能不能让 GPU 一次多算几个 token?推测解码解决的就是这个。

二、猜 + 验

推测解码的思路很朴素,朴素到我第一次看完论文的反应是:“这也行?”

具体分三步:

  1. 小模型猜:用一个参数量小很多的 draft model(比如 1B 或 3B),按正常自回归生成 K 个 token。模型小,每步很快,K 步加起来可能也就跟大模型一步差不多时间。

  2. 大模型验:把这 K 个 token 拼到已有序列后面,一次性喂给大模型做一次 forward pass。这一次 pass 会同时算出 K 个位置的概率分布——大模型本来就要对序列里每个位置算 logits,只是平时我们只取最后一个。

  3. 逐个比对:从左到右检查大模型在每个位置的概率分布和小模型的是否“兼容”。对第 i 个位置,如果大模型给这个 token 的概率 ≥ 小模型给的,直接采纳;如果更小,就以一定概率接受,不接受就按大模型的分布重新采一个,后面的猜测全部丢弃。

第二步是关键:大模型验证 K 个 token 只要一次 forward pass,代价和生成 1 个 token 差不多(多了些 KV Cache 写入,forward 计算本身是并行的)。K 个里猜对 M 个,你就用一次 forward 的代价拿到 M 个 token,加速比是 M:1。

M 当然不会等于 K,小模型不是大模型,猜的不全对。但只要 M > 1,你就赚了。

三、接受概率为什么是对的

这节会绕一点。

对每个位置,小模型(draft)给出一个概率分布 q(x)q(x),大模型(target)给出 p(x)p(x),小模型猜的 token 是 xx。接受规则:

  • 如果 p(x)≥q(x):接受。大模型本来就大概率给这个 token,没理由拒绝。
  • 如果 p(x)<q(x):以 p(x)q(x)q(x)p(x)​ 的概率接受。小模型高估了这个 token,但不一定错,按比例给个机会。

这个规则不是随手定的,它有个重要性质:最终生成的 token 分布,和大模型自己一个个生成时完全一样。

也就是说,推测解码不改变输出质量,只是换了采样方式。你拿到的 token 序列,和让大模型慢慢生成的,在统计上是同一个东西。

证明不复杂:把接受概率和拒绝后的重采样合起来算,边际分布恰好等于 p(x)p(x)。Leviathan 等人在 2023 年的论文里有完整推导。不想看推导,记住结论就行:质量无损,快不快看猜得准不准。

四、三个工程坑

理论清楚了,落地还有几个坑。

坑 1:小模型选不好,白忙活

加速比直接取决于猜中率,猜中率取决于小模型和大模型的“相似度”。

拿一个通用语料的 1B 模型去给代码专用的 70B 当 draft,猜中率可能只有 20-30%,K=4 时平均采纳 1 个左右,基本白干,还多了一份小模型的计算开销。

实际选择时:

  • 同家族优先:Llama-3.2-1B 给 Llama-3-70B 当 draft,比 Qwen-1.5B 好得多。同家族 tokenizer 一致(省掉映射),训练数据有重叠,分布更接近。
  • 领域要对齐:大模型是代码模型,draft 也最好在代码上微调过。Medusa 这类方法干脆在大模型上接几个 extra head 直接做 draft,省得另外找小模型。
  • 别太小:1B 以下的模型在复杂推理任务上猜中率很难看。3B-8B 比较合适,速度够快,猜中率也还过得去。

坑 2:K 不是越大越好

K 是每次猜测的 token 数。直觉上 K 越大,一次验证的 token 越多,越快。

实际有个拐点。猜中率随位置递减:第 1 个 token 猜中的概率高于第 2 个,第 2 个高于第 3 个,中间任何一个被拒,后面的全部丢弃。K 大到一定程度,后面几个 token 基本白猜,小模型白算,大模型的 forward 也多了无用计算。

实测下来,K=4 到 8 是常见的甜点。也有实现做动态 K:按最近几轮的猜中率自适应,高就加大,低就缩小。vLLM 里就有这个机制。

坑 3:KV Cache 管理变复杂

正常自回归的 KV Cache 线性增长,每个 token 追加一行就完了。

推测解码里,小模型猜的 K 个 token 先写进 KV Cache,大模型验证时也要写。如果中间第 3 个 token 被拒,第 3 个之后的 KV Cache 都得回滚,再从大模型重采样的 token 重新开始。

KV Cache 的管理于是从“只追加”变成“可回滚”,实现复杂度上了一个台阶。分布式推理(tensor parallel)下更麻烦,Cache 要跨卡同步。

这不是不能做,vLLM 和 TGI 都做了。但自己撸推理引擎的话,这块是主要工作量。

五、实际跑分

下面有公开基准,也有我自己环境里跑出来的数字。

vLLM(A100 80G,Llama-3-70B + Llama-3.2-1B draft)

场景 无推测解码 开推测解码 (K=5) 加速比
代码生成 (HumanEval) 42 tok/s 118 tok/s 2.8x
通用对话 (MT-Bench) 38 tok/s 95 tok/s 2.5x
数学推理 (GSM8K) 35 tok/s 72 tok/s 2.1x

数学推理的加速比最低,因为推理链路长、分支多,小模型猜中率掉得明显。

llama.cpp(M2 Max 64G,Qwen2.5-7B + Qwen2.5-0.5B draft)

端侧场景更有意思,因为显存有限,大模型本身就跑不快,推测解码的相对收益反而更大。

场景 无推测解码 开推测解码 加速比
通用对话 22 tok/s 48 tok/s 2.2x
代码补全 25 tok/s 61 tok/s 2.4x

0.5B 的 draft 在端侧几乎不占资源,额外开销可以忽略。这可能是推测解码最实用的场景:端侧本来就慢,加速比又高,draft 又小。

一个不太直觉的发现

batch size 很大的场景(比如同时服务几十个请求),推测解码的收益会缩水。原因在于 batch 推理时 GPU 本来就比较忙,自回归阶段不再是算力闲置等待,并行验证的优势就弱了。

所以它最适合的场景是低 batch、对延迟敏感的交互式推理,也就是你平时跟 ChatGPT 聊天那种,而不是后台批量处理。

六、和其他加速方法的关系

推测解码不是唯一的推理加速方案,放在大盘里看更清楚:

  • Flash Attention / PagedAttention:优化 attention 的计算和显存,减少访存瓶颈。和推测解码正交,可以叠加。
  • 量化(AWQ / GPTQ / FP8):减少模型本身的计算量。也和推测解码正交。
  • 连续批处理(Continuous Batching):提高吞吐,不改善单请求延迟。推测解码改善的正是单请求延迟。
  • Medusa / EAGLE:推测解码的变体。Medusa 不要单独的 draft model,在大模型上接多个 extra head,每个 head 预测未来第 i 个位置的 token,省掉了小模型的独立 forward,代价是训练这些 head 需要额外步骤。EAGLE 进一步改了 draft 的特征利用方式,猜中率更高。

实际部署里,量化、PagedAttention、推测解码三样一起上是常见做法。

七、什么时候用,什么时候别用

不是所有场景都值得开。

适合开的:

  • 交互式对话,延迟敏感,batch size 低
  • 端侧推理,算力受限,draft model 开销可忽略
  • 有合适的同家族小模型当 draft
  • 生成任务为主(而非纯 prefill 的分类/抽取)

不建议开的:

  • 高 batch 吞吐场景,收益缩水,还增加调度复杂度
  • 找不到合适的 draft model,猜中率低于 30% 就是负优化
  • prefill 阶段(处理 prompt),推测解码只加速 decode
  • 对首 token 延迟(TTFT)敏感的场景:推测解码改善的是后续 token 的生成速度,第一个 token 该等多久还是等多久

写在最后

推测解码让我觉得精妙的地方在于,它没改模型,没牺牲输出质量,只换了推理的调度方式,就拿到了 2-3 倍加速。这种绕开瓶颈的思路,比堆算力优雅。

当然,工程上该踩的坑一个不少:选 draft model、调 K、处理 KV Cache 回滚,每样都有细节。好在主流推理框架已经把这些封装好了,大部分人不需要从零实现,知道原理和调参方向就够用。

如果只记一句话:推测解码用算力换延迟,低 batch 交互场景下性价比极高,前提是有一个“够像”的小模型。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。