DLoop给投机解码加循环开关:草稿够准就多写一轮再验证
sina qqZone renren ydCloud 0

有个现象可能出乎意料。
眼下大模型推理加速普遍靠投机解码:先让一个小模型打草稿,大模型再一次性核对草稿对不对。草稿越准,大模型越省力,道理不复杂。可草稿模型如今已经练得相当聪明了,聪明到哪一步?
论文作者拿Qwen3-4B配上几种主流草稿模型做了测试,结果是不少草稿片段被大模型百分之百原样接收,一个字都没改。即便这样,系统仍然按规矩停下来,让大模型跑完整的一轮验证,之后草稿模型才被放行去写下一段。
打个比方,你找了个特别靠谱的助理代写邮件,他每写完一段都跑来要你签字,哪怕前十段你全是原封不动通过的。你难免会想:既然写得这么准,何不先多写几段,攒在一起看一遍?
投机解码*:一种加速大模型生成文字的技术。核心思路是让小的、跑得快的"草稿模型"先猜接下来可能出现的几个词,交给大的"目标模型"一次性检查这些猜测对不对,对的直接采用,省去逐字生成的开销。
这篇论文要解决的,正是"该验证时才验证,不该验证时别打扰"的问题。
被验证卡住的效率
投机解码里有两个关键角色。目标模型是你真正想用的大模型,生成质量全靠它;草稿模型个头小、跑得快,专门"预测"大模型接下来大概率会说什么。草稿模型吐出一批候选词,目标模型跑一次前向计算,看这批词哪些能留下。
这里有条硬性规定:草稿模型这次猜得再准,验证完也得停下来等下一轮草稿。论文把草稿模型一次吐出的词称为一个"块",块的大小通常固定,比如7个词或16个词。就算这7个词全部命中,系统也不让草稿模型趁热打铁接着写,而是先验证,再从头开始下一个块。
问题出在哪?
出在验证环节:目标模型的验证是整个流程里最耗时的部分。一次完整的前向计算,只验7个词和验14个词,花的时间差不了多少。瓶颈在于把整个大模型跑一遍这件事本身,跟验几个词关系不大。研究者发现,验证词数往上加,单次验证的耗时增长得很慢。这又意味着什么?
意味着原本要两次验证才能完成的内容,如果合并成一次验证,省下来的几乎就是整整一次目标模型前向计算的时间。
好比工厂质检:检验员查一箱零件和查两箱零件,用时差不多,大头花在搬箱子、启动设备上,逐个看零件反倒很快。要是每次都只搬一箱去查,检验员一趟趟白跑,损失的就是那些没用上的搬运次数。
已有的解决思路为什么不够用
这个浪费,研究者其实早就注意到了,也提过一些办法,统称"自适应草稿长度":生成过程中动态决定写多少草稿词再去验证,而不是死守一个固定的块大小。
但这类方法有个关键限制——基本都是为自回归草稿模型设计的。
自回归草稿模型*:一种逐词生成的草稿模型,写完第一个词,才能根据这个词接着写第二个词,像接龙一样一个接一个来。
自回归模型一个词一个词往外蹦,理论上可以在任意位置喊停,不想写就停,这个词的成本已经花出去了,停下也不浪费。可业界还有一类更快的并行草稿模型,一次前向计算就把整块的多个词全部吐出来,不排队生成。
并行草稿模型*:一种一次性生成整个草稿块的模型,所有词都在同一次前向计算里产出,不像自回归模型那样逐词排队生成。
对并行模型来说,自适应长度方法基本失效:不管你停不停,这次前向计算的成本已经花完了,提前喊停也省不下计算量。更麻烦的是,草稿模型若想在这个块之后接着往下写,得知道前面这些词准确的"隐藏状态"。
隐藏状态*:神经网络内部某一层对输入信息的编码表示,可以理解成模型对一段文字的"理解摘要",后续计算都基于这个摘要展开。
可这些隐藏状态要等大模型验证之后才会产生。还没验证的草稿词,大模型压根没碰过,自然没有这个信息。草稿模型硬要往下写,只能拿自己生成的隐藏状态顶替;它压根没在这种设定下训练过,写出来的质量会直线下降。
DLoop:让草稿模型自己判断要不要继续写
论文提出的DLoop,想法很朴素:草稿模型既然能感知到"这次写得靠不靠谱",就让它自己决定要不要多写一轮,攒够了再统一交给大模型验证。
DLoop这套方案包含两块:推理阶段的置信度门控循环机制,以及训练阶段的循环感知训练。
置信度门控循环怎么运作?草稿模型写完一个块,就把块内每个词的对数概率累加起来得到一个总分,这个总分代表它对刚写内容的把握有多大。总分高过预设门槛,草稿模型接着写下一块;没高过就收手,交给目标模型把此前攒下的所有块一次性验证。
对数概率:这是模型给词打分的一种方式,分数越高(越靠近0)说明模型越笃定这个词没问题,分数为负且绝对值越大则说明越没底。
求和而不是取平均,原因论文讲得很直白:每个词的对数概率不是负数就是零,某个位置一旦特别没把握,这个负数就会非常大,把总和直接压下去,其他位置的高分根本没法靠“平均”把它盖住。这跟验证规则也对得上——只要有一个词被拒,它后面的词全都会被连带丢掉。求和这种“一票否决”的算法,跟实际验证逻辑是吻合的。
打个比方。你让实习生连着处理几批文件,他每批做完自己评个分:“这批有把握,第二批也挺稳,但第三批有一处拿不准。”只要有一个环节他自己都发虚,这批乃至后面连带的工作都得重审,不能因为前两批靠谱就把后面的也放过去。要是改成让他用平均分糊弄,真出了错,后面所有没查过的工作全白干,返工代价更大。
循环感知训练:让草稿模型学会在“虚空”里接着写
只有判断逻辑还不够,草稿模型自己得适应这套新干活方式。
原来的草稿模型只练过一种情形:拿着大模型给的真实隐藏状态,预测下一个块写什么。DLoop却要求它在第一个块之后,继续拿自己生成的隐藏状态当“输入材料”,去写第二块、第三块。这种输入它训练时压根没见过,直接上手,效果打折扣是意料之中的。
EAGLE-3这个草稿模型此前有个叫“训练时测试”的技巧,让草稿模型在训练阶段就模拟“用自己预测的隐藏状态接着写”,但范围只限于一个块内部的深度。DLoop把这个思路往外扩了,让草稿模型训练时体验更长的链条,跨好几个块去模拟整个循环过程。
所谓训练时测试,指的是在训练环节就预先模拟推理时会碰到的情况,让模型提前练熟这类场景。放在这里,就是安排草稿模型练习“拿自己生成的中间结果接着往下写”,而非一味依赖外部喂进来的准确信息。
具体做法是:对每条训练数据,随机抽一个额外草稿轮数(论文里定在1到3轮之间),然后真跑这么多轮——第一轮照旧用大模型给的隐藏状态,后面几轮接上草稿模型自己算出的隐藏状态。损失函数只盯两头:第一轮的预测效果,和最后一轮(最难、离真实信息最远那轮)的预测效果,中间过程只管传递隐藏状态,不直接参与计分。
为什么只盯第一轮和最后一轮?
第一轮是原本的训练目标,不能丢,丢了基础能力会退化。最后一轮则是整条链上信息衰减最厉害、难度最大的部分,把训练精力压在这里,等于专门攻最薄弱的环节。中间几轮只是陪练,负责把“自己生成隐藏状态”这条链搭起来,但不单独计分。
好比培训一个翻译新人,你不会让他每翻一句就打分复盘,那样效率太低。更管用的办法是让他连着翻一整段,然后重点查开头那句(看基本功有没有退步)和结尾那句(看长链条下误差会不会越滚越大),中间部分只是让他熟悉“连续工作不被打断”的状态。反过来,如果每句都精雕细琢,新人反而学不会在长篇任务里保持连贯和自我修正。
实测效果:速度提升5%到41%
论文在EAGLE-3、DFlash、Domino、DSpark这几种主流草稿模型上都跑了测试,目标模型配的是Qwen3-4B和Qwen3-8B,另外还测了Qwen3.5-9B和Gemma-4-12B自带的多词预测模块。
EAGLE-3 属于自回归草稿模型里较有名的一支,它的做法是:让体量较小的草稿模型直接调用大模型已经算出的隐藏状态,一个词一个词地往后预测。
DFlash、Domino、DSpark:三种并行草稿模型,各自用不同方式做到一次前向计算吐出整个草稿块,省掉了自回归逐词生成的排队开销。
结果显示,这些设置下平均每次验证能接受的词数(即“接受长度”)提升了12%到102%,整体实际运行速度提升5%到41%。有意思的是,涨幅最大的是DSpark,而它恰好也是前面说的“百分之百被整块接受”比例最高的草稿模型——说明它确实有最多机会多写几轮而不被打断。
论文还做了拆解实验,分别单测“只开循环不做训练”和“只做训练不开循环”。只开循环不训练,对自回归模型(比如EAGLE-3)仍有提升,因为它本来就习惯自己生成隐藏状态接着写;可对并行模型来说,速度提升有限甚至下降,多写几轮花掉的时间,差不多被接受长度的提升抵消了。只做训练不开循环,两个指标变化都很小。两者同时启用,效果才真正显著,而且提升幅度超过两者单独效果的简单相加。
这说明循环感知训练不是孤立地提升每一轮草稿的质量,而是在专门为“循环”这种新工作模式做适配准备。
和同类自适应长度方法的对比
论文还把DLoop跟一批已有的自适应草稿长度方法做了横向比较,包括BiLD、SVIP、AdaEDL、LLMCad、SpecDec++、DISCO、PACER、AdaEAGLE、DDD等等。这些方法大多靠草稿分布的某个统计量(比如概率、熵)来判断该不该提前停止生成,有的还得专门训练一个决策模块。
实验数据摆在那里:DSpark这类并行模型上,没有一种对比方法能跑赢原始草稿模型,个别还更慢。道理和前面说的一样,并行模型单次前向计算的开销固定,中途叫停也省不掉这笔钱。换到EAGLE-3这种自回归模型,这些方法倒是有提升,可幅度最多0.14倍左右,跟DLoop差得远。两种草稿模型上,DLoop的接受长度和速度提升都排在首位。
提速的来源在哪
论文把解码时间拆得很细,草稿占多少、验证占多少,按每次循环跑了几轮草稿分门别类统计。
数字显示,DLoop把总解码时间压低了4.9%到24.3%,有34%到71%的生成词数出自“多轮草稿共用一次验证”的情形。单次循环里草稿轮数越多,单轮耗时确实跟着涨,但接受词数涨得更快,平均每生成一个词的时间就一路往下走:单轮草稿时是4.6到6.4毫秒,五轮以上草稿时降到0.68到2.97毫秒。验证次数整体减少了7.6%到34.1%。
每验证一次,都要跑一遍完整的大模型前向计算,这是全流程最贵的一笔开销。验证次数降下来省下的钱,远远超过多写几轮草稿多付的成本。
打个比方,快递员原先送一件包裹就得回站点打卡登记一回;如今一次能带5件,就多捎几件再回去,打卡次数少了,路上找包裹多花点时间,可来回跑站点省下的时间远比这多。要是死守一次一件、送完就回,看着每趟都规矩,实际上大量时间扔在了不必要的往返上。
叠加树形验证,收益还能往上走
基础投机解码之外,业界还有“树形验证”这类增强手段:草稿阶段不生成单一路径,而是铺开多个候选分支,大模型一次把整棵树验完,挑出最优那条。
树形验证*:为了让投机解码更高效,草稿阶段不再只走一条直线式的候选序列,改为生成一棵带多个分支的候选树,再由大模型一次把整棵树验完,单次验证能覆盖的候选范围因此变大。
DLoop跟树形验证不打架,还能一起用。论文里DFlash配的是DDTree,Domino和DSpark配的是DARTree。结果是在树形验证之上再加DLoop,DFlash平均速度又多出12%到13%,Domino多7%到8%,DSpark多22%到25%。树形验证管的是“往哪个方向猜”,DLoop管的是“猜多久才去核对”,两个维度各管各的,叠在一起并不冲突。
写在后面
这篇论文读下来,让我记得最牢的不是加速比那个数字,而是“全盘接受率”的统计图。
它点出一件容易漏掉的事:不少工程系统的低效,问题不在某个组件做得差,而在系统的调度节奏没跟上组件实际能力的进步。草稿模型越练越聪明,验证节奏却还守着“它多半会犯错”的老规矩,这种错配本身就是浪费的来源。
还有一点值得琢磨。论文一再说明,DLoop不加额外参数、不改草稿模型结构,动的只是“什么时候停下来核对”的决策方式。这种不碰筋骨、只调节奏的路子,放到很多系统设计里都用得上。有时候拖后腿的不是能力,是流程定得太死。
论文结尾那句话让我多想了想:验证之前该跑几轮草稿,不必交给固定的调度规则,大可以留到运行时再判断。往大了想,我们习以为常的那些“固定流程”,是不是都该重新问一句,这个节奏真有必要,还是只因为大家一直这么干?
Q&A
Q1:DLoop是什么?
A:DLoop是一种改进投机解码的方法。它让草稿模型按自己的置信度决定要不要连着写多轮草稿,写完后统一交给大模型验证一次,目标模型的前向计算次数因此减少。
Q2:DLoop相比普通投机解码能提升多少速度?
A:论文在EAGLE-3、DFlash、Domino、DSpark等多种草稿模型上做了测试,实际运行速度提升5%到41%,生成结果和原来完全一致,准确性没有损失。
Q3:DLoop对并行草稿模型和自回归草稿模型都有效吗?
A:都有效,这也正是它跟以往自适应草稿长度方法最大的不同。以往的方法只对自回归草稿模型有提升,对一次性生成整块草稿的并行模型基本没用,DLoop靠循环感知训练把这个限制解开了。