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 Modeldraft_model是(小模型)通用(需配对 draft model)1.5-2.0×
Eagle3eagle3是(eagle 权重)GLM / Kimi / Mistral / MiniMax1.8-2.5×
MTPdeepseek_mtp / mtp否(内置 head)GLM-5 / DeepSeek-V3/V41.3-1.8×
N-Gramngram通用(模式匹配)1.1-1.3×
Medusamedusa否(需 medusa head)特定模型1.3-1.7×
MLP Speculatormlp_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
modelDraft/Eagle 模型路径eagle3draft_model 需要
enforce_eager禁用 CUDA GraphMTP + 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_secondsP50 降低 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=1Prefill 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