vLLM 投机解码:MTP/Eagle3 生产级加速实践
vLLM 投机解码(Speculative Decoding)三种方案深度对比:MTP(GLM-5.2 内置)、Eagle3(Kimi-K2.6)、Draft Model,含 Ascend NPU 真实生产配置、吞吐提升实测和排坑指南。
一、为什么需要投机解码
问题:自回归推理的瓶颈
标准自回归(每步生成 1 token):
Step 1: Forward → token_1 ████████░░░░░░ GPU 空闲 50%+
Step 2: Forward → token_2 ████████░░░░░░
Step 3: Forward → token_3 ████████░░░░░░
...
Step N: Forward → token_N ████████░░░░░░
Decode 阶段是 memory-bound(受限于显存带宽,而非算力)。每次 forward 只算一个新 token,GPU 大部分时间在等数据从 HBM 搬到计算单元。
投机解码的思路
投机解码(一次猜测 3 个 token):
Step 1: Draft → [guess_1, guess_2, guess_3] ████████████████ GPU 吃饱
Step 2: Target Model 验证 3 个猜测 ████████████████
接受 2 个,拒绝 1 个 → 实际产出 3 tokens(含拒绝后重新生成的 1 个)
核心思想:用一个轻量级模型(Draft Model)快速猜几个 token,再用大模型(Target Model)一次性验证。猜对的 token 直接接受,猜错的丢弃后重来。因为验证可以批量做(一次 forward 处理多个 token),显存带宽利用率大幅提升。
理论加速比:接受率 × 猜测数 / (1 + 猜测数 × 草稿开销比)
典型生产环境中,接受率 70-85%,猜测 3-5 个 token,实测吞吐提升 1.5-2.5×。
二、vLLM 支持的三类方案
| 方案 | vLLM method | 需要额外模型? | 适用模型 | 典型吞吐提升 |
|---|---|---|---|---|
| Draft Model | draft_model | 是(小模型) | 通用(需配对 draft model) | 1.5-2.0× |
| Eagle3 | eagle3 | 是(eagle 权重) | GLM / Kimi / Mistral / MiniMax | 1.8-2.5× |
| MTP | deepseek_mtp / mtp | 否(内置 head) | GLM-5 / DeepSeek-V3/V4 | 1.3-1.8× |
| N-Gram | ngram | 否 | 通用(模式匹配) | 1.1-1.3× |
| Medusa | medusa | 否(需 medusa head) | 特定模型 | 1.3-1.7× |
| MLP Speculator | mlp_speculator | 否 | 通用 | 1.2-1.5× |
2.1 MTP (Multi-Token Prediction) — 推荐
原理:模型训练时就在 Transformer 顶层加了额外的预测头(MTP Head),可以直接输出下一个 token 的多个候选。推理时不需要额外模型。
# GLM-5.2 内置 MTP — 无需额外权重
# vLLM 配置:
--speculative-config '{"num_speculative_tokens": 3, "method": "deepseek_mtp"}'
优点:
- 不需要额外模型文件,没有额外显存开销
- 训练阶段就优化好了,接受率高(80-90%)
- GLM-5.2 / DeepSeek-V4 原生支持
局限:
- 只有训练时加了 MTP Head 的模型能用
- 猜测 token 数有限(通常是 1-5,受 MTP Head 数量限制)
2.2 Eagle3 — 最激进的方案
原理:训练一个轻量级的 Draft 模型,输入 Target Model 的 hidden states,输出猜测的 token。Eagle3 是第三代,支持 Tree Attention 同时猜测多条路径。
# Kimi-K2.6 + Eagle3
# 需要 eagle3 权重作为额外模型
EAGLE_PATH="/models/kimi-k2.6-eagle3"
--speculative-config '{"method":"eagle3","model":"'$EAGLE_PATH'","num_speculative_tokens":3}'
优点:
- 接受率高(75-85%),比纯 draft model 好
- Tree Attention 支持多分支猜测,提高命中率
局限:
- 需要额外的 Eagle 权重文件(通常 1-5GB)
- 额外显存开销(Eagle 模型也要加载到 NPU/GPU)
- 不是所有模型都有训练好的 Eagle 权重
2.3 Draft Model — 通用方案
# 用 Qwen3-0.6B 给 Qwen3-72B 做 draft
vllm serve Qwen/Qwen3-72B \
--speculative-config '{"method":"draft_model","model":"Qwen/Qwen3-0.6B","num_speculative_tokens":5}'
优点:通用,任何模型都能用。局限:需要维护两个模型,接受率通常低于 MTP/Eagle。
三、关键参数详解
| 参数 | 含义 | 建议值 |
|---|---|---|
num_speculative_tokens | 每次猜测的 token 数 | 3-5。越大 GPU 利用率越高,但拒绝成本也越高 |
method | 方案选择 | deepseek_mtp / eagle3 / draft_model / ngram |
model | Draft/Eagle 模型路径 | 仅 eagle3 和 draft_model 需要 |
enforce_eager | 禁用 CUDA Graph | MTP + Ascend 必须设为 true(见下文坑) |
enforce_eager 与 MTP 的关系
在 Ascend NPU 上使用 MTP 投机解码时,CUDA Graph 和 MTP 不兼容,必须设 enforce_eager: true:
{
"num_speculative_tokens": 3,
"method": "deepseek_mtp",
"enforce_eager": true
}
如果不设,vLLM 会报错:
CUDA graph does not support speculative decoding with MTP(Ascend 上等价的 CANN 错误)。Eagle3 通常不需要这个。
Prefill vs Decode 的差异化配置
PD 分离场景下,Prefill 和 Decode 可以设不同的投机参数:
Prefill:num_speculative_tokens=1(保守,保证 KV 质量)
Decode: num_speculative_tokens=3(激进,榨吞吐)
GLM-5.2 的生产配置正是如此。
四、Ascend NPU 生产配置(真实案例)
4.1 GLM-5.2 MTP
# Prefill — 保守猜测,num_speculative_tokens=1
vllm serve /workspace/GLM-5.2-w8a8 \
--speculative-config '{"num_speculative_tokens": 1, "method":"deepseek_mtp", "enforce_eager": true}'
# Decode — 激进猜测,num_speculative_tokens=3
vllm serve /workspace/GLM-5.2-w8a8 \
--speculative-config '{"num_speculative_tokens": 3, "method":"deepseek_mtp", "enforce_eager": true}'
为什么 Prefill 用 1、Decode 用 3?
- Prefill 阶段输出 token 数少(
max_tokens=1做 KV 传输),投机解码收益有限,猜测太多反而增加延迟 - Decode 阶段是真正的 token 生成主力,猜测 3 个 token 可显著提升吞吐
4.2 Kimi-K2.6 Eagle3
# Prefill 和 Decode 共用 eagle3 权重
EAGLE_PATH="/models/kimi-k2.6-eagle3"
# Prefill
vllm serve /workspace/Kimi-K2.6-w8a8 \
--speculative-config '{"method":"eagle3","model":"'"$EAGLE_PATH"'","num_speculative_tokens":3}'
# Decode(相同)
vllm serve /workspace/Kimi-K2.6-w8a8 \
--speculative-config '{"method":"eagle3","model":"'"$EAGLE_PATH"'","num_speculative_tokens":3}'
Eagle3 的 Eagle 权重需要挂载进容器:
# docker-compose.yml
volumes:
- /data/models/Kimi-K2.6/kimi-k2.6-eagle3:/models/kimi-k2.6-eagle3
4.3 DeepSeek-V4-Flash MTP
# DeepSeek-V4 内置 MTP Head
vllm serve /workspace/DeepSeek-V4-Flash-w8a8-mtp \
--speculative-config '{"num_speculative_tokens": 5, "method": "deepseek_mtp"}'
DS-V4 的 MTP Head 支持最多 5 个 token 猜测。
五、验证投机解码是否生效
5.1 启动日志
正常启动后在日志中能看到(因模型而异):
INFO: Enabling speculative decoding with method deepseek_mtp, num_speculative_tokens=3
5.2 吞吐对比
# 关闭投机解码
vllm serve /model --max-num-seqs 256 # 不加 speculative-config
# 压测
python3 -m vllm.benchmarks.benchmark_serving \
--backend vllm --model model-name \
--dataset-name sharegpt --num-prompts 100
# 对比开启后的 QPS
# 期望:开启后 QPS 提升 1.5-2.5×
5.3 看 Prometheus 指标
投机解码生效后,以下指标应有明显变化:
| 指标 | 预期变化 |
|---|---|
vllm:time_per_output_token_seconds | P50 降低 30-50% |
vllm:request_rate | 提升 1.5-2.5× |
vllm:gpu_cache_usage_perc | 可能略升(更充分利用显存) |
六、常见坑
| 现象 | 根因 | 解决 |
|---|---|---|
| 开启后反而变慢 | num_speculative_tokens 太大,接受率低 | 降到 1 或 2 |
| MTP 报 CUDA Graph 错误 | Ascend 上 MTP 不支持 CUDA Graph | 加 "enforce_eager": true |
| Eagle3 加载失败 | Eagle 权重路径不存在或损坏 | 检查 docker-compose.yml 的挂载路径和文件完整性 |
| 吞吐没有提升 | Prefill 节点设了投机但 max_tokens=1 | Prefill PD 分离场景下降 num_speculative_tokens 为 1 或不启用 |
| Eagle3 启动慢 | Eagle 模型也要加载到显存 | 首次启动多等 30-60s(Eagle 模型 ~1-5GB) |
| 接受率突然下降 | 上下文太长,draft 模型覆盖不到 | 缩短上下文或换用 MTP(内置 head 更稳定) |
| Eagle3 + PD 分离权重加载失败 | P 和 D 都需要 eagle 权重 | 确认两个 Deployment 的 volumes 都挂载了 eagle 路径 |
6.1 接受率(Acceptance Rate)调优
接受率是投机解码最重要的健康指标。查看方式:
# vLLM 日志中搜索
grep "speculative" /workspace/logs/decode_rank0.log
# 典型输出:accepted 2340 / drafted 3000 = 78.0%
- > 80%:健康,可以尝试增大
num_speculative_tokens - 60-80%:正常范围
- < 60%:接受率偏低,降
num_speculative_tokens或检查 draft 模型
七、选择决策树
你的模型有内置 MTP Head?
├─ 是 → 用 MTP (deepseek_mtp),最省事
│ ├─ GLM-5.x → num_speculative_tokens=3, enforce_eager=true
│ └─ DeepSeek-V3/V4 → num_speculative_tokens=5
│
└─ 否 → 有训练好的 Eagle3 权重?
├─ 是 → 用 Eagle3,接受率最高
│ ├─ Kimi-K2.x → num_speculative_tokens=3
│ └─ Mistral → num_speculative_tokens=3-5
│
└─ 否 → 用 Draft Model (小模型)
└─ 选同系列的 0.5B/1.5B 小模型做 draft