Speculative Decoding 全家桶:从 n-gram 到 P-EAGLE/DFlash/DSpark
Speculative Decoding 全家桶:从 n-gram 到 P-EAGLE/DFlash/DSpark
前情说明:《训练时代的黄昏》讲了推理时代的到来。当推理成为主战场,如何让每次 forward 吐更多 token就成了核心问题。这一篇专门整理 Speculative Decoding 这个杀手锏——从最朴素的 n-gram,到 SOTA 的 parallel drafting,一次讲透。 素材来自 vLLM Blog《Inside vLLM》(2025-09-05) 里的 speculative decoding 章节 + 《Parallel All the Way Down》(2026-07-28) 这篇最新的 parallel drafting 综述。
起手:Decode 阶段为什么慢?
先回顾一下 《现代 LLM 推理引擎剖析》 里那张表:
| 阶段 | 计算特征 | 瓶颈 |
|---|---|---|
| Prefill | 一次跑 N 个 token | 算力 bound |
| Decode | 每次跑 1 个 token | 带宽 bound |
Decode 阶段的根本痛点是:
每生成 1 个 token,都要把整个模型权重从 HBM 读一遍——B200 也扛不住。
以 Llama 70B 为例(140GB weights)、H100 HBM 带宽 3.35TB/s,理论极限是每秒 24 次 decode。也就是单请求最快 24 token/s——B 卡稍强一点但也是同个数量级。
要突破这个墙有三条路:
- 更大 batch——把多个 request 塞一起,摊薄单次 forward 的开销(continuous batching)
- 更多 KV 复用——减少不必要的 forward(prefix caching)
- 一次 forward 出多个 token——Speculative Decoding
前两条各家都在做,前面已经讲了。这篇专门讲第三条。
一、Speculative Decoding 的核心思想
1.1 一个反直觉的观察
大模型 forward 一次到底在算什么?——给出下一个 token 的概率分布。
但如果 forward 时输入是 [t0, t1, ..., tN-1],它会同时给出每个位置的下一个 token 分布——也就是 [t1|t0], [t2|t0,t1], ..., [tN|t0..tN-1] 全都能算。这是 causal attention 的天然属性。
只是我们平时只用最后一个!中间的都浪费了。
Speculative decoding 的核心洞察:如果能提前猜出接下来 K 个 token,就把它们一起塞进 forward,一次拿回 K+1 个位置的分布进行验证——一次 forward 出多个 token。
1.2 完整算法(有严格数学保证的版本)
标准 Speculative Decoding 算法:
- Draft:小模型跑一次,一口气提出 K 个候选 token
[d1, d2, ..., dK] - Verify:大模型跑一次 forward,输入
[context, d1, d2, ..., dK]→ 拿到 K+1 个位置的分布p_large - Accept/Reject:从左到右扫这 K 个 token:
- 计算
α = min(1, p_large(di) / p_draft(di)) - 以概率 α 接受 di,否则拒绝并停止
- 计算
- 修正采样:如果在位置 i 拒绝了,从修正分布
(p_large - p_draft)+(clamp min 0,归一化)采一个新 token - Bonus:如果 K 个全接受,大模型的第 K+1 个采样是 free 的
关键的数学保证:
这套 accept/reject 规则的期望输出分布严格等于"逐 token 从大模型采样"的分布。
不是近似!是严格等价! 一份形式化证明在原始 speculative decoding paper 里。这是这个算法的灵魂——你可以为速度做设计,但不用担心质量下降一分一毫。
一次 forward 期望能吐 E[tokens] = 1 + Σ acceptance_probs,通常在 3-8 之间。speculative decoding 是 lossless acceleration。
二、Drafter 选型:小模型太慢,大模型 rehash 也不对
朴素方案是用一个独立的小模型做 draft(比如 Llama 7B 给 Llama 70B 打草稿)。但vLLM V1 不支持这种方案。为什么?
几个原因:
- 小模型也有开销——weight loading、kernel launch、scheduling 都要另一套。跑 Llama 7B forward 不便宜
- 小模型和大模型分布差异大——acceptance rate 低(40% 左右),效益差
- 调度复杂度爆炸——两个引擎实例要协调 batch,几乎不可能优雅
所以 vLLM 走了三条**"轻量 drafter"**路线:n-gram、EAGLE、Medusa。
2.1 n-gram —— 零训练成本
思想:从当前 prompt 里搜历史匹配窗口。
具体算法:
def ngram_draft(context, prompt_lookup_max=5, prompt_lookup_min=3, K=3):
for window in range(prompt_lookup_max, prompt_lookup_min - 1, -1):
pattern = context[-window:] # 取末尾 window 个 token
for i in range(len(context) - window):
if context[i:i+window] == pattern:
# 命中!返回该位置之后的 K 个 token 当草稿
return context[i+window : i+window+K]
return None # 未命中
适用场景:
- 代码补全:变量名、函数调用重复率高
- 结构化文档:JSON schema、SQL 语法有大量重复模板
- 对话:"I am"、"The answer is" 之类高频短语
优势:零训练、零显存、零开销 劣势:只对"字面重复"起作用,创造性文本收益低
2.2 EAGLE —— 大模型"外科手术"
思想:不用独立小模型,而是"减配版大模型"。
EAGLE 的做法:
原大模型: Embedding → Transformer × N 层 → LM Head
↓ 换掉
EAGLE: Embedding → Lightweight MLP × 1 层 → LM Head
(共享) (新训练) (共享)
保留大模型的 embedding 层(因为语义表征很强)和 LM Head(因为 vocabulary 映射不能变),只把中间 N 层 transformer 换成轻量 MLP(几层就够)。
关键洞察:EAGLE 直接消费大模型的 hidden state——不是从原始 token embedding 出发,而是从 verify 阶段大模型已经算过的 hidden state 出发。这个 hidden state 已经浓缩了丰富的上下文信息,用轻量网络就能高效预测下一个 token。
训练成本极小(几十亿 token 的微调即可),acceptance rate 高达 70-80%。
2.3 EAGLE-3 —— 递归 drafting 的极致
EAGLE-3 是 EAGLE 的进化版:递归自回归 drafting——
Step 1: 大模型算完 → 拿 hidden state h0
Step 2: EAGLE-3 输入 h0 → 输出 d1 + 新 hidden state h1
Step 3: EAGLE-3 输入 h1 → 输出 d2 + 新 hidden state h2
...
Step K: EAGLE-3 输入 hK-1 → 输出 dK
Step K+1: 大模型 verify [d1, ..., dK]
递归指的是EAGLE-3 用自己上一步的输出作为下一步的输入——本质上是一个"精简版自回归"。
收益:K 变大时(比如 K=7),EAGLE-3 比原始 EAGLE 的 acceptance rate 明显更高,因为递归结构能保持 token 之间的因果关系。
2.4 Medusa —— 加多个头,并行预测
思想:不递归,用并行的多个 LM Head 直接一次预测 K 个未来 token。
┌──→ Head_1 → 位置 t+1 的分布
│
Hidden state ─┼──→ Head_2 → 位置 t+2 的分布
│
├──→ Head_3 → 位置 t+3 的分布
│
└──→ Head_K → 位置 t+K 的分布
每个 head 都是独立训练的线性层。看似简单粗暴,但很有效。
优势:一次 forward 就出 K 个草稿(不像 EAGLE-3 要 K 次 forward) 劣势:远处 token 的预测精度低——因为它不知道近处的 t+1, t+2 是什么,只是各自独立猜
Medusa 是 parallel drafting 的鼻祖——虽然效果不算最好,但思路开了后来 P-EAGLE / DFlash / DSpark 的先河。
三、Autoregressive 的诅咒:为什么 EAGLE-3 也不够
到 EAGLE-3 为止,drafter 都是"更快的 autoregressive 模型"——draft 阶段还是逐 token 生成,只是每个 token 便宜。
看架构就明白瓶颈在哪:
Auto-regressive drafting (EAGLE/EAGLE-3):
Draft 1 forward → t+1
Draft 2 forward → t+2 (需要 t+1)
Draft 3 forward → t+3 (需要 t+1, t+2)
...
Draft K forward → t+K
大模型 verify [t+1, ..., t+K] (1 次)
──────────────────────────
共 K+1 次 forward
问题:Drafter 是 K 次 forward,一次都少不了。
这带来两个生产上的痛点:
- 限制 drafter 容量——drafter 必须极其轻量,否则 K 次 forward 的总开销超过 verify 阶段省的时间
- K 是难调的超参——K 太大 drafter 拖后腿,K 太小 verify 不划算。最优 K 依赖 workload 和硬件负载,运维要不停调
vLLM 团队 2026-07-28 那篇 《Parallel All the Way Down》 直接把这个问题命名为——"the structural ceiling rooted in the way draft tokens are generated"。
四、Parallel Drafting:一次 forward 出 K 个 token
Parallel drafting 的核心动作:让 drafter 一次 forward 直接输出整个 K 个 token 的 block。
Parallel drafting:
Drafter 1 次 forward → [t+1, t+2, ..., t+K] block
大模型 verify 1 次 → 接受/拒绝
─────────────────────
共 2 次 forward
从 K+1 次到 2 次 forward——drafter 开销跟 K 无关!
这解锁两个巨大的架构自由度:
- Drafter 可以更大更强——反正只跑 1 次,容量提升不加成本 → 更高 acceptance rate
- K 不再敏感——想 speculate 多少就多少(受 verify 硬件限制),运维不用调
Medusa 是最早的 parallel drafter,但精度太差没跑起来。真正让 parallel drafting 起飞的是 2026 上半年这三个算法:P-EAGLE、DFlash、DSpark。
4.1 P-EAGLE —— Parallel EAGLE
核心思想:把 EAGLE 的 hidden state 输入方式保留,但输出层改成一次预测多个位置。
输入: verify 模型的 hidden state h_t
↓
Lightweight transformer / MLP
↓
输出: [t+1 分布, t+2 分布, ..., t+K 分布] ← 一次全出
训练技巧:block sparsification
一个致命的训练问题——如果每个训练样本都要预测未来 K 个 token 的完整分布,loss matrix 是 N×K,内存和算力开销都爆炸。
P-EAGLE 的解法:沿 K 维度做衰减采样——近处位置(t+1、t+2)loss 权重高,远处位置(t+K)大部分 dropout 掉。
直觉合理——近处预测本来就重要,远处即使不训练也无所谓(反正 acceptance rate 会自然下降)。
4.2 DFlash —— 把 hidden state 塞进 KV cache
核心思想:更进一步——不把 verify 的 hidden state 作为 input feature,而是直接注入 drafter 的 KV cache。
Standard EAGLE:
input = [verify_hidden_state] → drafter → output
DFlash:
input = [regular tokens] → drafter (KV cache 里被塞了 verify hidden state)
↓
Block Diffusion output
技术细节:
- Verify hidden state 通过投影层进入 drafter 的 attention KV cache
- Drafter 用 block diffusion(借鉴图像扩散)一次生成 K 个 token
- Attention 变成双向——每个 draft token 能看到整个 block
训练技巧:sequence length sparsification
不同于 P-EAGLE 沿 K 维稀疏,DFlash 沿 N 维(序列长度) 稀疏——只在随机 anchor 点计算 block loss。
这是另一种权衡——P-EAGLE 训练所有位置但每位置只训近处 token;DFlash 训所有 K 个位置但只在少数序列位置。各有取舍。
4.3 DSpark —— DFlash + AR 校正 + Confidence Head
DSpark 是 2026 年 SOTA。它建立在 DFlash 的 parallel backbone 上,加了两个创新:
创新 1:Autoregressive 校正头
Parallel drafter (DFlash 主干)
↓
[初始 K 个候选]
↓
Lightweight AR head (逐 token 校正)
↓
[更精细的 K 个候选]
Parallel 生成保证速度,AR 校正保证 token 间的因果一致性。兼得两者优点。
创新 2:Confidence Head
问题:Parallel drafting 生成的 K 个 token 里,有些置信度低的很可能被 verify 拒绝。全部塞给 verify 会浪费 verify 的算力。
DSpark 的解法——加一个 confidence head:
draft tokens → confidence head → 每个 token 的置信度
↓
选择性把高置信度的送 verify
低置信度的 draft token 在到 verify 之前就被过滤——verify 只处理"大概率会被接受"的候选,verify 侧算力开销显著下降。
这是端到端优化——不只优化 drafter,还优化 verify 的算力分配。
五、Benchmarks:跑起来有多快?
vLLM 2026-07-28 那篇 blog 给了实际数据(相比 EAGLE-3 的对比):
| Model | 算法 | 场景 | 硬件 |
|---|---|---|---|
| Qwen3-8B | P-EAGLE | 数学推理 (GSM8k) | 1×A100 |
| Qwen3-30B-A3B | DFlash | 代码 (HumanEval) | 2×A100 |
| gemma-4-31B-it | DSpark | 代码 (HumanEval) | 2×A100 |
结果(相比 EAGLE-3 baseline):
- P-EAGLE:在小模型 + reasoning 场景明显提升
- DFlash:在 MoE + coding 场景明显提升
- DSpark:几乎所有场景都是当前 SOTA
blog 里的具体数字有过一次 errata(07-29 更新,环境配置错了修正),但结论没变——parallel drafting > autoregressive drafting。
5.1 在 vLLM 中启用
启用 parallel drafting 就一个 config:
vllm serve Qwen/Qwen3-30B-A3B \
--tensor-parallel-size 2 \
--reasoning-parser qwen3 \
--speculative-config '{
"model": "RedHatAI/Qwen3-30B-A3B-speculator.dflash",
"num_speculative_tokens": 7,
"method": "dflash"
}'
用户几乎无感——OpenAI-compatible API 保持不变,底层多了个 parallel drafter 在偷偷加速。
六、Speculators 项目:不只是算法,是生态
vLLM 联合 RedHat AI 发布 Speculators 项目——统一的 speculative decoding 生态:
- 训练 pipeline:用相同 API 训 EAGLE / P-EAGLE / DFlash / DSpark
- HuggingFace Hub:所有预训练 speculator 可以直接下载
- vLLM 集成:与 vLLM 深度耦合,config 一行搞定
这是 vLLM 从"引擎"到"参考实现 + 生态"演进的又一步(详见 《vLLM 三年演进史》)。
为什么这个生态很重要? 因为 speculative decoding 有个致命的训练成本问题——每一个大模型都要配一个专门训练的 speculator。市面上有 100 个开源模型,就要 100 个 speculator。散着放没人管,用户想用就得自己训。
Speculators 项目把这个碎片化生态统一起来——每个 SOTA 模型发布时都同时发布对应的 speculator,训练 pipeline 标准化。这跟 vLLM Day-0 支持新模型的策略完全一致。
七、还有哪些没讲到?
Speculative decoding 是个活跃研究领域,本文覆盖的只是主线。还有几条支线可以了解:
MTP (Multi-Token Prediction)——DeepSeek V3 用的方案,把 speculative 集成到模型 pretrain 里。模型直接学会一次预测多 token,不需要额外 drafter。Kimi K3 也用了这个思路(详见 vLLM Kimi K3 blog)。
PARD——早期 parallel drafting 方案,DFlash 前身之一
Lookahead Decoding——不需要 drafter,用启发式规则从生成历史里找模式。开销极小,但 acceptance rate 也不高。
Retrieval-based Drafting——从外部知识库检索候选 token(比如代码补全场景),适合特定 domain。
Sampling-based (Blockwise Parallel)——Google 的方案,训练时就让模型学会多 head 预测
这个方向 2026 年会继续爆发——因为它是唯一能突破 decode 带宽墙的通用工具,任何 workload、任何硬件都能吃到收益。
八、把 speculative decoding 放回大图景
回到 fin 那三篇文章的宿命论:
- Token throughput = HBM size × HBM 带宽(HBM 是宿命)
- 但 speculative decoding 让 每次读一遍 HBM = 吐 5-8 个 token 而不是 1 个
- 相当于在同样的硬件上把 throughput 拉高 5-8 倍
这是软件优化的极限吗?是——除非 attention 机制被颠覆(fin 说不太可能),否则 speculative decoding 就是 decode 阶段的最后一公里优化。
未来看点:
- Drafter 会越来越大——parallel drafting 解锁了 drafter 容量
- Verify 会越来越智能——DSpark 的 confidence head 只是第一步
- 训练侧集成会成为标配——MTP 这种"pretrain 时就学多 token 预测"会普及
- 异构硬件配合——drafter 在小 GPU / CPU 上跑,verify 在大 GPU 上跑(跟 AFD Plugin 类似思路)
Speculative decoding 是"token 时代"的最后一个宏观突破。它把 fin 讲的那个 memory-bandwidth 天花板软软地穿透了几倍——不是靠新硬件,是靠算法的智慧。
这就是软件的美——它总能在物理的天花板下面,再找出一些新的空间。
附:素材来源
主线
- vLLM Blog · Parallel All the Way Down: Beyond Single-Token Generation with Speculative Decoding(2026-07-28)
- vLLM Blog · Inside vLLM: Anatomy(2025-09-05,speculative decoding 章节)
论文
- Speculative Decoding 原论文 · Fast Inference from Transformers via Speculative Decoding
- Speculative Sampling · Accelerating Large Language Model Decoding with Speculative Sampling
- EAGLE · Speculative Sampling Requires Rethinking Feature Uncertainty
- Medusa · arxiv 2401.10774
- EAGLE-3 · arxiv 2503.01840
- PARD · arxiv 2504.18583
- P-EAGLE · arxiv 2602.01469
- DFlash · arxiv 2602.06036
- DSpark · arxiv 2607.05147
代码 & 生态
- Speculators - 统一训练/评估平台
- RedHatAI HuggingFace Collection - 预训练模型
姊妹篇
整理于 2026-07-31。原文技术细节归属 vLLM 团队和相关论文作者。中文表达可能有解读偏差,请以原文为准。

Written by
Zoe
AI Infra Engineer · LLM Serving · GPU/RDMA · 造工具的偏执狂