让 2B 当侦察兵:投机解码的原理、实测数据与失效边界

· 3 minutes read · 595 字 · 系列:技术分享

让 2B 当侦察兵:投机解码的原理、实测数据与失效边界

上一篇我们提到,2B 小模型最"值钱"的用法之一是给大模型当草稿机。这个技术的正式名字叫投机解码(Speculative Decoding)。它的效果相当戏剧化:有人实测把 27B 模型的生成速度从 25 tok/s 提到 45 tok/s,也有人实测把 60 tok/s 掉到 45 tok/s——用的是同一个技术。

本文面向没有推理优化背景的读者,先讲清"为什么能加速",再讲清"为什么有时反而变慢",中间穿插多组真实实测数据。


一、先搞懂一个反直觉的事实:大模型生成慢,不是因为算不过来

这是理解投机解码的唯一前提。

大模型生成文字是一个字一个字往外蹦的(术语叫自回归)。每蹦一个字,都要把整个模型的全部权重从显存里完整读一遍。以 27B 模型 Q4 量化为例,权重约 16 GB——也就是说,每生成一个字,就要搬运 16 GB 数据。

这带来一个关键结论:瓶颈在内存带宽,不在计算能力。显卡的计算单元绝大部分时间在空转等数据。用一张带宽 936 GB/s 的 RTX 3090 举例,理论上限就是 936 ÷ 16 ≈ 58 tok/s,无论这张卡的算力有多强。

所以加速的方向有两条:

  • 减少要搬运的数据量(量化、用小模型)——代价是质量。
  • 让空转的算力干点活——这正是投机解码的思路,且不损失任何质量。

二、核心思路:让便宜的小模型去"猜",让贵的大模型去"批改"

打个比方。大模型是个写文章很慢但水平很高的资深编辑,小模型是个打字飞快但水平一般的实习生。

  • 传统方式:编辑一个字一个字亲自写,写一个字想一下,慢。
  • 投机解码:实习生先一口气猜出接下来 5 个字,编辑拿过来一次性扫一眼——“前 3 个对,第 4 个不对”。于是前 3 个字直接采纳(几乎白赚),第 4 个字由编辑自己改,第 5 个字扔掉重来。

关键在于:编辑一次性检查 5 个字的成本,和检查 1 个字的成本几乎一样。因为权重的搬运量在一次前向传播里是固定的,检查 5 个 token 只是把这条数据多算几遍而已——而算力本来就是空闲的。

这个"猜 → 批量验证 → 采纳正确前缀"的循环,就是投机解码的全部机制。三个关键点:

  1. 小模型(草稿模型)通常比大模型小 5 到 10 倍,猜一个字的速度快得多。
  2. 大模型(目标模型)逐字验证,因此输出结果与它单独生成时完全一致——这是无损的,不是取舍。
  3. 收益完全取决于接受率:猜得越准,白赚的字越多。

关于第 2 点值得强调:投机解码改变的是"每个大模型前向传播能产出几个字",而不是"产出什么字"。所以它不是近似、不是投机取巧的质量妥协——这一点让它成为罕见的"免费午餐",前提是草稿猜得准。


三、决定成败的唯一指标:接受率

接受率(acceptance rate)= 被大模型采纳的草稿 token 数 ÷ 草稿总数。

行业里已经形成较一致的经验阈值:

接受率结论
70% 以上值得开启,收益显著
60% ~ 70%收益有限,需实测权衡
60% 以下通常不划算,建议关掉

接受率由两个因素决定:

因素一:草稿模型与目标模型的"血缘关系"。 两者必须同家族、共用同一个分词器。用 Qwen 系列的草稿去猜 Llama 系列的目标,词表都不一样,token ID 无法对应,验证环节直接失效。这是硬性要求,不是优化建议。

因素二:任务的可预测性。 这是一组实测数据(Gemma 4 31B,draft-max 8)在不同任务上的接受率:

任务类型接受率
数学推理61.7%
代码47.9%
翻译40.9%
创意写作34.7%
科学问答34.6%

规律很清楚:结构化、可预测的内容(代码、JSON、公式、样板文)接受率最高;开放式创意内容最低。原因也很直白——代码的下一个字往往是可以推断的,而小说的下一个字全凭作者心意。

还有一个常被忽略的细节:草稿位置越靠后,接受率越低。实测衰减曲线是这样:

草稿的第 N 个 token接受率
第 1 个95%
第 3 个88%
第 5 个79%
第 8 个72%

这解释了一个重要的调参现象:草稿长度不是越长越好。猜 16 个 token,后面大部分会作废,反而浪费验证算力。


四、真实实测数据(含一个"翻车"案例)

以下数据来自 2026 年公开的多组实测,涵盖不同硬件与方案。

成功案例:

配置结果
Qwopus3.6-27B-MTP(Q4_K_M),双 RTX 2080 Ti 22GB34.03 tok/s,接受率 63.03%(574/897)
Qwen3.6-27B + MTP,单张 A10G 24GB25 → 45 tok/s(+78%)
Qwen3.6-27B + MTP,Apple Silicon,接受率 82%7 → 16 tok/s(约 2.3 倍)
Llama 3.1 8B + 1B 草稿(草稿长度 5)1.83 倍
Gemma 4 31B,Strix Halo,草稿长度 4+103%(该硬件上最优)

翻车案例(务必记住这个):

配置结果
Gemma 4 + 不匹配的 int4 草稿,接受率仅 41%60 → 45 tok/s(−25%)

同一个技术,一头是 2.3 倍,另一头是负 25%。分水岭就是接受率:41% 的接受率下,草稿模型本身的运行开销和验证浪费超过了收益。

还有一个容易被误读的现象,值得单独说明:

草稿长度Strix Halo(共享内存)RTX 5090(独立显存)
2+71%—
4+103%(最优)—
8+47%(反而变差)最优
16+65%数学任务达 99 tok/s

同一个草稿长度,在两种硬件上结论相反。 原因在于验证批次的成本随草稿长度增长:在带宽紧张的共享内存设备上,为了验证 9 个 token 而多搬的权重,把收益吃掉了;而在带宽充裕的独立显卡上,验证成本微不足道,草稿越长越是纯赚。

结论:草稿长度必须针对自己的硬件实测调优,没有通用最优值。


五、2026 年的重大变化:命令参数已改名

如果你照着 2024–2025 年的博客或教程抄命令,现在会直接报错。 llama.cpp 在 2026 年重命名了这一组参数,统一到 --spec- 前缀下:

旧参数(已移除)新参数含义
--draft-max--spec-draft-n-max N每轮最多草稿多少 token(默认 3)
--draft-min--spec-draft-n-min N低于此数量则放弃该轮草稿
--draft-p-min--spec-draft-p-min P草稿置信度低于此值即停止
-ngld--spec-draft-ngl N草稿模型放到 GPU 的层数
(新增)--spec-type <类型>选择投机方式

其中 -md / --model-draft(指定草稿模型文件)没有改名,仍然可用。

最容易踩的坑:--spec-type 默认值是 none。 这意味着如果你只写了 -md draft.gguf 而没有指定 --spec-type,llama.cpp 会老老实实把草稿模型加载进内存、占用显存,然后什么也不做。你付出了内存代价,却拿到零收益,而且不会报错。

普通双模型方案用 draft-simple。--spec-type 还支持多种方案,可逗号分隔叠加:

draft-simple | draft-mtp | draft-eagle3 | draft-dflash | draft-dspark
ngram-cache | ngram-simple | ngram-map-k | ngram-map-k4v | ngram-mod

5.1 完整可运行示例

# 目标模型 8B + 草稿模型 0.5B,均同属一个家族
./llama-server \
  -m   models/target-8b-Q4_K_M.gguf \
  -md  models/draft-0.5b-Q4_K_M.gguf \
  --spec-type draft-simple \
  --spec-draft-n-max 5 \
  --spec-draft-p-min 0.75 \
  -ngl all --spec-draft-ngl all \
  -c 8192 --port 8080 --metrics

参数逐个解释:

  • -m:目标模型(要加速的那个)。
  • -md:草稿模型(小得快跑的那个)。
  • --spec-type draft-simple:启用经典双模型投机——漏了它整个功能不生效。
  • --spec-draft-n-max 5:每轮最多猜 5 个。起步建议 5,再按接受率上下调。
  • --spec-draft-p-min 0.75:草稿模型对下一个字的把握低于 75% 就停手,避免硬猜。
  • -ngl all --spec-draft-ngl all:两个模型都尽量放进 GPU。注意这两个是独立参数,草稿模型不会自动跟随目标模型。

5.2 如何验证"到底有没有变快"

不要凭感觉。llama.cpp 会直接给出接受率统计。用 OpenAI 兼容接口调用后,响应体会附带:

"timings": {
  "predicted_per_second": 34.03,
  "draft_n": 897,
  "draft_n_accepted": 574
}

draft_n_accepted ÷ draft_n 就是接受率(上例为 63.03%)。同一模型内部还提供更细的按位置接受率,可用 --perf 或 Prometheus 指标(--metrics)查看。

正确的工作流是:先用真实业务 prompt 记录基线 tok/s → 开启投机 → 记录新 tok/s 与接受率 → 接受率低于 60% 就果断关掉。


六、优势与局限(如实列出)

优势

优势说明
输出无损结果与直接跑大模型完全一致,不是近似
不增加显存中的目标模型精度损失只加一个草稿模型的开销
首字延迟不变只优化生成(decode)阶段,输入处理(prefill)不受影响
接受率高时收益可观代码/结构化输出常见 1.5–3 倍
与量化正交可以和 Q4、KV cache 量化叠加使用

局限

局限说明
接受率低时是负收益实测出现 −25%;这是最需要警惕的一条
必须同家族同分词器跨家族基本不可用,选型自由度受限
多占显存草稿模型自己的权重 + 自己的 KV cache;Q8 级草稿可能吃掉数 GB
显存紧张时更糟若草稿要挤出目标模型的层或上下文长度,得不偿失
无法与多模态共用llama.cpp 明确在加载 --mmproj 时禁用投机解码
强制单并发需 --parallel 1;草稿模型的 KV cache 会随并发槽位膨胀
对并行吞吐无帮助优化的是单请求延迟,高并发服务场景收益有限

最后两条尤其值得注意:投机解码是一个降低单条请求延迟的技术,不是提升整体吞吐的技术。如果你的场景是大批量并发推理,它不但帮不上忙,还会因为强制单并发而拖累吞吐。


七、2026 年的新路径:不必再找第二个模型

上面讲的都是"两个模型"的方案。2026 年出现了一条更省事的路:MTP(Multi-Token Prediction,多 token 预测)——把草稿能力直接训练进模型本身,模型自己给自己当草稿。

好处非常实际:不需要再挑选、对齐、加载第二个模型,也就没有显存翻倍和家族匹配的问题。代价是必须使用带 MTP 结构的模型文件。

配置方式和普通方案几乎一样,只是换个类型:

./llama-server \
  -m models/qwen3.6-27b-MTP-Q4_K_M.gguf \
  --spec-type draft-mtp \
  --spec-draft-n-max 2 \
  --spec-draft-ngl all \
  -c 32768 --parallel 1 --perf

注意 MTP 场景下草稿长度建议调小(实测用 2 效果稳),因为这是模型内部的预测结构,不是独立的小模型。

生态跟进也很快:Gemma 4 在 MLX 推理器上默认启用了投机解码,Ollama 也已在 Mac 上为 Gemma 4 加入 MTP 支持——也就是说,你可能已经在不知不觉中用它了。

除 MTP 外,--spec-type 还支持更激进的方案:

  • EAGLE-3(draft-eagle3):训练专门的草稿头,在有利条件下可达 2–4 倍。
  • n-gram 系列(ngram-simple / ngram-mod 等):完全不需要草稿模型,改用哈希表匹配历史 token 序列来预测。特别适合"改写源码"“批量重构"这类大量重复片段的场景。--spec-default 可以一键启用默认的 ngram-mod 配置。
  • DFlash / DSpark:扩散式与稀疏式草案,属于较新的实验路线。

八、给 2B 小模型的定位

结合本系列的主题,2B 级小模型在投机解码中的定位非常明确:

  1. 它是天然的草稿模型候选。与目标模型 1:5 到 1:10 的尺寸比正是推荐区间,而 0.5B–2B 的 Q8 量化文件只占 0.5–1.9 GB 显存,成本很低。
  2. 它不适合当目标模型被加速。一个 2B 模型本身的生成速度已经受带宽限制不多,加草稿的收益微乎其微,反而多占内存。要加速就加速 8B 以上的模型。
  3. 要注意它的有效上下文。小模型标称上下文往往远大于实际有效上下文,草稿场景下尤其如此——拼接上下文过长会让接受率进一步下降。

九、一句话决策清单

在动手之前,问自己五个问题:

  1. 我的模型是否完全跑在 GPU 上?——否,则先解决显存不足,投机解码会雪上加霜。
  2. 我的任务是结构化/可预测的吗?——代码、JSON、公式适合;创意写作不适合。
  3. 我能接受单并发吗?——需要高并发吞吐的场景请放弃。
  4. 我有没有同家族的小模型?——没有则考虑 MTP 或 n-gram 方案。
  5. 我实测过接受率吗?——没有实测就下结论,是这类优化最常见的错误来源。

最后一条建议:投机解码是"调参型"优化,同一个命令在不同机器上可能一个是加速 2 倍、一个是减速 25%。先花十分钟记录基线,再决定是否保留它——这十分钟的投入,比任何推荐参数都值钱。


延伸阅读:别把 2B 当小号 GPT-4:llama.cpp + Qwen 2B 的六种实战玩法 | curl 不止是下载工具:AI 与 Agent 开发中的十二类实战场景

© 2026 CAO ZUOHUA. All rights reserved.