让模型说话更快:投机解码与 DSpark

先给结论: 模型回答时是一个词一个词往外吐的,每个词都要走一遍完整的大模型计算——这是推理慢的根本原因。DSpark 的思路是:先让一个"小助手"一口气猜出好几个词,再让大模型一次性批改。 批改可以并行,猜对了就白赚。

一、先说清楚"慢"在哪里

上一篇讲的是"知道什么",这一篇讲的是"说得快不快"。

模型生成文字的方式是自回归——一次只产出下一个词,产出了就拼到后面,再产下一个。 这个循环里有个致命的地方:

每一个词,都要把整个大模型完整跑一遍。

模型有几百亿参数,跑一遍就是一次大计算。所以回答一段话就是"把大计算串行重复几十次"。计算卡在这种串行循环里,大部分时间在等——这就是推理慢的根源。

关键观察:词与词之间必须串行,是因为第 3 个词要依赖第 2 个词。但如果我能保证猜对所有词,那就不用等,一次算完。

二、投机解码:先猜后批

投机解码:先猜后批,只快不笨小助手快的模型(草稿)一口气猜 k 个词它不负责最终正确大模型并行批改一次验证全部候选接受前缀第一个错处就截断把已接受的接到末尾错的丢掉,从那里重来循环为什么无损:最终每个词都经过大模型认可,草稿只是「提议」DSpark 的两个改进 + 调度状态① 用大模型的内部状态给小助手当参考,猜得更准② 预算调度器决定这一轮该猜多长低并发:猜长一些预算扩到 4–6 个高并发:收缩预算别让单个用户占满卡关键约束:做决定时不许偷看未来,否则「无损」就不成立

投机解码循环与 DSpark 的调度状态;1 + p 决定每轮期望产出

这个想法叫投机解码,用一个办公室比喻最好懂:

  • 大模型 = 总编:水平最高,但很忙、很慢,每做一个决定要很久。
  • 小助手 = 实习生:水平差一些,但快得多。
  • 流程:实习生先一口气写好 5 个词 → 总编拿着这 5 个词一次性校对(因为校对是并行的,很快)→ 前面几个对了就全部采纳,错了就从错的地方重来。

为什么这是"无损"的? 因为最终每个词都是总编认可过的。实习生的草稿不会降低输出质量——他猜得准就赚,猜不准就退回总编自己写。这是这套方法最漂亮的性质:它只可能让你更快,不可能让你变笨。

用公式说,每一轮的开销是:

(写草稿的时间 + 校对的时间)÷ 平均被采纳的词数

所以提速有三个杠杆:草稿更快、猜得更准、校对更聪明。

三、一个小数字游戏:为什么值得做

假设助手一次猜 5 个词,平均有 85% 的猜中率(这是论文里 MTP 模块报告过的水平)。

  • 猜中 1 个的概率:0.85
  • 连中 2 个:0.85 × 0.85 ≈ 0.72
  • 连中 3 个:≈ 0.61
  • ……

平均能采纳几个? 注意"至少产出 1 个"(大模型自己写的那个总是算数),再加上被采纳的草稿。草稿猜 k 个时,期望采纳数是:

1 + p + p² + … + pᵏ

  • 只猜 1 个:1 + 0.85 = 1.85 个
  • 猜 5 个:1 + 0.85 + 0.72 + 0.61 + 0.52 + 0.44 ≈ 4.15 个

这就是论文里反复出现的 “1 + p” 公式(p 是猜中率):猜 1 个时每轮产出 1.85 个词,猜 5 个时约 4.15 个。

但注意这个数列收敛得很快——无限猜下去的总和也只有 1 ÷ (1 − 0.85) ≈ 6.67 个,而且后面每个草稿的"边际贡献"(0.85、0.72、0.61……)越来越小。这就是第四节要讲的难题:猜得越往后越不值钱。

四、猜得越往后越不准:这是核心难题

上面的算法有个隐藏问题:猜第 2 个词比猜第 1 个难,猜第 5 个比猜第 2 个难得多。

原因是:猜第 5 个词时,要假设前面 4 个词都猜对了。前面任何一个错了,后面全废。

论文里有张图展示这个"衰减":某些设置下,第 1 个位置的猜中率是 0.88,到后面掉到 0.78;更难的任务(开放聊天)从 0.72 掉到 0.63。

所以"猜得更长"不是免费的——后面那截基本是浪费计算。DSpark 的核心工作就是解决"怎么猜得更准、更久"。

五、DSpark 的两个关键改进

改进一:用大模型自己的"内部状态"帮小助手

小助手不是凭空猜的。关键技巧是:把大模型中间几层的"内部状态"(可以理解为它读到当前内容时的理解)喂给小助手当参考。

打个比方:实习生写稿之前,先看一眼总编刚才在草稿纸上画的思路图——他猜起来就准多了。

DSpark 在这一步做了改进,让草稿模型的第 1 个位置就猜得更准(论文图 2 显示,它的起点猜中率比对比方案高)。开头准了,整串的连锁就都受益,这正好打在第四节的痛点上。

改进二:不猜固定长度,而是"看情况猜"

这是 DSpark 最有意思的地方。

传统做法是:每次都让助手猜固定的几个词(比如每次 5 个)。但内容有难易:写代码、做数学题时,套路明显,助手能猜得很远;闲聊时每一句都难以预测,猜长了纯属浪费。

DSpark 加了一个**“最长的产出预算"的调度器**:它先预估这一轮"我应该生成多少个词”,然后从最有把握的候选开始挑,挑到预算用完为止。

为什么要"从最有把握的开始挑"? 因为越靠后的位置越不准,而"先挑最有把握的"正好和"位置越靠后越不准"这个自然顺序对上了。论文证明了:在这个前提下,这个"贪心挑"的做法是最优的。

结论:不是猜得越长越好,而是猜得"刚刚好"最好。 论文的实验也支持这点——在不同难度的任务上,收益随"块长度"变化的曲线不一样,说明没有一种固定长度对所有场景都最优。

六、一个关键约束:不许"作弊"

这套方法有个隐藏的技术要求:做决定时不能偷看未来。

听起来奇怪,但这是保证"无损"的必要条件:如果调度器在决定"这个位置要不要采纳"时,偷看了后面还没验证的内容,那输出分布就可能被改变——无损性就没了。

论文把这个要求叫"不预测未来",并在附录里给了一个反例:如果允许全局搜索(可以偷看全局信息),结果就不再无损。

这是很典型的研究诚实:他们不仅说"我的方法是对的",还说清了"在什么条件下它才成立"——去掉这个约束,结论就崩了。

七、他们的成绩,以及必须说清的边界

论文报告了两组结果:

离线实验(标准基准、可复现):在三种不同大小的模型上对比已有方案,“每轮平均采纳长度"提升 26%–31%(对比鹰派方案)(相对另一方案 16%–18%)。而且提到一个重要发现:用 2 层的小助手就超过了对方 5 层的方案——说明"猜得准"靠的是信息质量(拿到大模型的内部状态),而不是助手本身堆得大。

同时给出了领域差异:数学题 5.57 个词、代码 5.12 个词、开放聊天只有 3.49 个词(同一个模型)。同一个方法,在不同任务上效果差一倍——这就是为什么值得加调度器。

生产环境(真实用户流量):在 V4-Flash 上,吞吐提升约 51%(在某个延迟服务水平下),每个用户的生成速度提升 60%–85%;V4-Pro 上是 +52% 和 57%–78%。

⚠️ 这里必须标注边界:这些是内部遥测数据——论文没有给出流量构成、时间窗口、基线复现协议。论文自己也把某些数字(如"661%/406%“这类)限定为"前沿扩展"的表述。本系列引用时只取有明确前提的部分,不做进一步推算。

八、一个容易搞混的归属问题

论文的代码发布在一个开源仓库里,里面有若干个不同的方案(DFlash、EAGLE3 等)。

但仓库里"有"不等于"是 DeepSeek 发明的”。 该仓库的 README 致谢部分明确标注了这些方案来自第三方——它们被实现,不代表归属。

这个坑很常见:看到某公司仓库里有某项技术,就以为"这项技术是他们的”。判断归属要看论文正文和引用,不能看仓库文件列表。

九、这条线的完整闭环

回头看,这是一条漂亮的演进链:

  1. V3 训练时:加了一个 MTP 模块(多词元预测),目标是让训练更省数据——一次预测多个词,学习信号更密。当时它有个副作用:这个模块可以拿来当"小助手"做投机解码(猜中率 85%–90%)。
  2. DSpark:把这个副作用变成了主产品——专门为推理服务设计,加了置信度调度和更聪明的验证。

但两篇的算术同源(都是 1 + p),它们的性能数字绝对不能互相引用。 一个是训练指标的副产品,一个是真实用户流量下的服务指标——分母、场景、测量方式都不同(第十二篇的"分母结构"那一关再次适用)。

这也是一条更普遍的规律:很多技术突破不是"发明了新东西",而是"把旧东西的副作用变成了主角"。


一句话总结: 投机解码让快而差的小助手先猜、慢而准的大模型并行批改,猜对就白赚;DSpark 用大模型的内部状态提高猜中率、用预算调度器决定该猜多长,在真实流量下把生成速度提升 60%–85%(内部遥测口径)。

记住这个数字: 1 + p ——猜中率 85% 时,每一轮平均产出约 1.85 个词;这个公式同时出现在训练侧的 MTP 和推理侧的 DSpark 里,但两边的性能数字不可互引。

回到系列第一篇: 为什么值得花时间读 DeepSeek 的论文——十五篇走完,你可以用这套方法自己去读任何一篇了。