上一篇我们聊了模型量化,把模型从"巨无霸"压成了"小钢炮"。但即便模型压缩了,推理时还是一个字一个字地生成------每次生成都要跑一遍完整的70B参数,一个字都跑不掉。有没有办法让大模型"少干点活"?
这就是我们今天要聊的------投机解码(Speculative Decoding),一种"让小模型打草稿、大模型批改"的加速方案,能在不损失任何质量的前提下,把推理速度提升2~3倍。
一、投机解码到底在干嘛?
一句话概括:投机解码用一个便宜的小模型快速生成多个"候选字",再让大模型一次性并行验证这些候选字,接受正确的、拒绝错误的,从而大幅减少大模型的推理次数。
先回忆一下大模型正常的推理过程:
正常自回归生成:
大模型生成第1个字 → 大模型生成第2个字 → 大模型生成第3个字 → ...
每个字都要跑一遍完整的70B模型,串行执行,一个字都跑不掉
投机解码的做法完全不同:
投机解码:
小模型快速生成5个候选字(草稿)
→ 大模型一次性并行验证这5个字
→ 前3个对了,接受!第4个错了,拒绝!
→ 从第4个位置重新开始下一轮
打个比方:你是一个公司的CEO(大模型),每天要签发大量文件。如果每份文件都亲自从头写,效率很低。现在你招了一个实习生(小模型),让他先起草文件。你只需要"批改"------对的直接签字,错的改掉重写。批改的速度远快于从头写,所以你的整体效率大幅提升。
关键点是:最终输出的质量完全由大模型决定 ------小模型只是"打草稿",大模型负责"批改"。如果小模型猜错了,大模型会拒绝并从错误点重新开始。所以投机解码是无损加速,输出质量和不用投机解码完全一致。
二、核心原理:大模型天生能"一次看多个字"
投机解码之所以能工作,依赖一个关键特性:大模型在验证阶段可以并行处理多个Token。
回忆一下KV Cache那篇的内容:大模型推理分为Prefill(预填充)和Decode(解码)两个阶段。
- Prefill阶段:一次性处理一整段输入,计算所有Token的KV,是并行计算,速度很快。
- Decode阶段:一个字一个字生成,每次只处理一个新Token,是串行计算,速度很慢。
投机解码的巧妙之处在于:把小模型生成的多个候选字拼在一起,当作一段"输入"喂给大模型,让大模型用Prefill的方式并行验证它们。
具体来说:
小模型生成了候选序列:["我", "喜欢", "人工", "智能", "技术"]
拼接成输入:prompt + ["我", "喜欢", "人工", "智能", "技术"]
大模型一次性处理这段输入(Prefill模式),并行输出每个位置的概率分布:
位置1:大模型认为应该是"我" → 和候选一致 → 接受 ✅
位置2:大模型认为应该是"喜欢" → 和候选一致 → 接受 ✅
位置3:大模型认为应该是"人工" → 和候选一致 → 接受 ✅
位置4:大模型认为应该是"技术" → 候选是"智能" → 不匹配 → 拒绝 ❌
位置5:大模型从自己的分布中采样一个新字 → 作为新的起点
一次验证操作,大模型同时检查了5个候选字。如果其中3个正确,就相当于大模型"免费"生成了3个字------这3个字本来需要大模型串行推理3次,现在只用了1次Prefill就搞定了。
三、接受与拒绝:怎么保证质量无损?
投机解码最核心的问题是:怎么保证最终输出和大模型自己生成的完全一样?
答案是使用一种基于概率的**接受-拒绝采样(Accept-Reject Sampling)**机制。
大模型和小模型对每个位置都会输出一个概率分布。比如对于下一个字,小模型认为"猫"的概率是60%、"狗"的概率是40%;大模型认为"猫"的概率是80%、"狗"的概率是20%。
接受规则:
接受概率 = min(1, 大模型概率 / 小模型概率)
如果小模型选了"猫":
接受概率 = min(1, 80% / 60%) = min(1, 1.33) = 1 → 一定接受
如果小模型选了"狗":
接受概率 = min(1, 20% / 40%) = min(1, 0.5) = 0.5 → 50%概率接受
这个规则保证了:经过接受-拒绝采样后,最终输出的概率分布和大模型自己生成的分布完全一致。数学上可以严格证明,这是投机解码"无损"的理论基础。
如果某个候选字被拒绝了,就从拒绝位置开始,丢弃后面所有候选,大模型自己采样一个新字,然后开始下一轮投机。
四、草稿模型怎么选?
投机解码的效果高度依赖草稿模型(Draft Model)的选择。核心要求:
要求一:足够小,生成足够快
草稿模型的速度必须远快于大模型,否则"打草稿"的开销会抵消"批改"节省的时间。经验法则是:草稿模型的参数量不超过大模型的1/10。
| 大模型(目标模型) | 草稿模型 | 参数量比例 |
|---|---|---|
| Llama 3 70B | Llama 3 8B | 1/9 |
| GPT-4级别 | GPT-2 / 1.3B | 1/100+ |
| CodeLlama 34B | CodeLlama 7B | 1/5 |
要求二:和大模型"想法接近"
草稿模型猜得越准,大模型接受率越高,加速效果越好。所以最好选择和大模型同系列、同架构的小模型。比如用Llama 3 8B给Llama 3 70B打草稿,两者训练数据相似、架构相同,"想法"自然接近。
如果用完全不同的模型(比如用BERT给GPT打草稿),接受率会很低,加速效果大打折扣。
要求三:特定场景可以用"投机目标"
在代码生成、翻译等场景中,输出有很强的规律性。比如代码中大量的缩进、括号、关键字是可以预测的。这时可以设计专门的"投机目标"(Speculative Target),甚至不需要一个完整的语言模型,用简单的规则或n-gram模型就能达到很高的接受率。
五、实际加速效果:能快多少?
投机解码的加速比取决于接受率------小模型生成的候选字中,有多少比例被大模型接受了。
接受率越高,加速越明显。实测数据表明:
- 文本生成场景:接受率通常在50%~80%,加速比约1.5~2.5倍
- 代码生成场景:由于代码规律性强,接受率可达80%~90%,加速比约2~3倍
- 翻译场景:接受率较高,加速比约1.5~2倍
影响接受率的关键因素:
- 草稿模型和大模型的相似度:同系列模型接受率更高
- 任务类型:规律性强的任务(代码、翻译)接受率更高
- 温度参数:Temperature越低(输出越确定性),接受率越高
- 候选长度:每轮投机生成的候选字数量。太少则加速不够,太多则后面的候选字准确率下降,反而浪费验证开销。通常5~10个候选字是比较好的平衡点
需要注意,加速比不是一个固定数字,它高度依赖于上述因素的组合。在最佳条件下(高接受率+合适的候选长度),加速效果最为显著。
六、投机解码的变体方案
自2023年投机解码提出以来,业界发展出了多种变体:
自投机(Self-Speculative Decoding)
不需要额外的草稿模型------用大模型自身的浅层来"打草稿"。
大模型通常有几十层Transformer,浅层(比如前8层)的计算量远小于完整模型,但也能生成"大概对"的输出。用浅层生成候选,完整模型验证,省去了单独部署草稿模型的开销。
缺点是浅层的能力有限,接受率通常低于独立草稿模型。
草稿外推(Draft Extrapolation)
连草稿模型都不用------直接利用大模型自身在上一轮推理时的中间计算结果来"外推"候选字。
原理是:大模型在生成第N个字时,中间层已经"隐约知道"后面几个字可能是什么。把这些中间状态利用起来,就能免费获得候选字。
这种方式零额外开销,但接受率最低,适合对延迟极度敏感的场景。
Medusa:多头并行预测
2024年提出的Medusa方案,在大模型顶部加多个简单的预测头(MLP),每个头负责预测未来不同位置的Token。比如头1预测下一个字,头2预测下两个字,头3预测下三个字。
推理时所有头并行工作,一次性输出多个候选字,然后用树状注意力验证。这种方式不需要独立的草稿模型,加速比可达2~3倍,但对模型结构有侵入性,需要重新训练或微调预测头。
EAGLE-2:上下文感知的草稿生成
EAGLE-2在草稿阶段引入了注意力机制,让草稿模型能"看到"大模型中间层的特征,从而生成更准确的候选。相比标准投机解码,接受率提升10%~15%,加速比进一步提升。
七、投机解码的局限与适用场景
投机解码不是万能的,它有明确的适用边界:
适合的场景
- 高并发服务端部署:GPU计算资源充裕但内存带宽受限的场景,投机解码能把"内存带宽瓶颈"转化为"计算瓶颈",充分利用GPU算力
- 代码生成、翻译等规律性任务:接受率高,加速效果显著
- 长文本生成:生成的Token越多,投机解码的加速收益越大
不太适合的场景
- GPU计算已经是瓶颈:如果大模型本身已经跑满了GPU算力,投机解码增加的验证计算反而会拖慢速度
- 低延迟场景:投机解码引入了额外的"打草稿"开销,如果小模型猜错太多,总延迟可能反而增加
- 小模型(7B以下):小模型本身推理就很快,投机解码的加速收益有限,不值得引入额外复杂度
八、投机解码在整个大模型生态中的位置
最后,咱们把投机解码放回整个知识体系里:
预训练 → SFT → RLHF/DPO(对齐)
↓ 模型学会了语言能力和价值观
RAG → Agent → MCP → Multi-Agent → Orchestrator
↓ 模型获得了各种应用能力
↓
推理优化(让模型跑得快、跑得省)
├── KV Cache:避免重复计算,加速生成
├── 模型量化:压缩模型权重,减少显存
├── 投机解码:小模型打草稿,大模型验证
└── PagedAttention:精细化管理显存
投机解码处于推理优化的"第三块拼图"------KV Cache解决了"重复计算的浪费",量化解决了"模型体积太大",投机解码解决了"大模型每个字都要自己算"。三者可以叠加使用:量化后的模型可以用投机解码加速,投机解码过程中的KV Cache也可以用量化存储。
总结
投机解码(Speculative Decoding)是一种无损推理加速技术,核心思路是用一个轻量级草稿模型快速生成多个候选Token,再由大模型通过Prefill方式一次性并行验证,接受正确的、拒绝错误的。由于最终输出经过接受-拒绝采样,其概率分布与大模型独立生成完全一致,因此加速过程不损失任何质量。实测在文本生成场景下可实现1.5~2.5倍加速,代码生成场景可达2~3倍,实际加速比取决于草稿模型质量、任务规律性和候选长度等因素。变体方案包括自投机、Medusa多头预测、EAGLE-2等,进一步降低了对独立草稿模型的依赖。理解投机解码,我们就能明白为什么"大模型+小模型"的组合拳能在不牺牲质量的前提下大幅提升推理速度------不是大模型变快了,而是它"少干了很多活"。
投机解码让小模型帮大模型"打草稿",但显存管理本身也能优化。下一篇聊聊PagedAttention------像操作系统管理内存一样管理显存,vLLM的核心黑科技。