你的大模型为啥突然快了,下一代投机解码 DFlash 拆给你看

小岛AI 2026 / 06 / 16

事情是这样的。

这两天刷 AI 动态,刷到 LMSYS 那篇博客,标题平平无奇,叫下一代投机解码 DFlash 和 Spec V2。我本来手指都准备往上划了,结果瞄到正文第一段一个数字,HumanEval 上并发 1 的场景,吞吐做到了原模型的 4.3 倍。

我盯着那个 4.3x 看了好几秒。

要知道这不是换了张更猛的卡,也不是把模型剪小了精度往下掉。同一个 Qwen 3.5 397B 的大模型,答案一个字都不带变的,速度直接翻了四倍多。好家伙。

我平时的活儿,就是给大模型搭那层让它真能干活的工程脚手架,调度、工具链、上下文管理、还有今天要聊的推理这块。所以这种「答案不变、速度起飞」的东西,对我来说不是新闻,是每天上班要操心的命根子。但 4.3x 这个数,还是让我愿意把这篇拆开跟你唠唠。

因为它背后那套思路,真的挺漂亮的。

先说说为啥大模型天生就慢

你有没有发现一件事,同样一个模型,让它写代码、写文章,它是一个字一个字往外蹦的。不是它故意装在打字,是它真的只能这么干。

这事的术语叫自回归解码(autoregressive decoding,意思是模型每生成一个 token,都得把前面已经生成的全部内容重新喂回去,才能算出下一个)。token 你可以粗暴理解成一个字或者半个词。所以一句话一百个 token,模型就得老老实实跑一百遍前向计算,一遍只吐一个。

这就尴尬了。

现代 GPU 是什么脾气?它是个特别能吃并行的猛兽,你一次性喂它一大坨矩阵运算,它眉头都不皱算得飞快。可你现在让它一次只算一个 token,相当于请了个能同时颠十口锅的大厨,结果你让人家一次只煎一个荷包蛋。这里有个词叫算术强度(arithmetic intensity,简单说就是每搬一次数据能顺手做多少计算),自回归解码这玩意算术强度低得可怜,卡的算力大半时间在干等内存搬数据。

我做 harness 这层最常见的吐槽就是这个,明明手里是 B200 这种顶配卡,跑起来 GPU 利用率一看,心凉半截。不是卡不行,是这个一个一个吐字的模式压根喂不饱它。

那怎么办?

投机解码,让一个小弟先猜,大佬批量验

投机解码(speculative decoding)这个思路 2022 年就有了,特别聪明。

它说,既然大模型一个一个吐字太慢,那我额外找个又小又快的草稿模型(draft model),让这个小弟先一口气猜出来接下来好几个 token,再把这一串猜测一次性丢给大模型去并行验证。

关键在最后这步验证。大模型一次性收下小弟猜的五个 token,并排着同时核对,对的就留下,从第一个错的地方截断重来。因为是批量并行核对,正好对上 GPU 的胃口,验五个和验一个花的时间差不多。

最妙的是,这套不掉精度。最终留下的每个 token,都是大模型自己点头认可的,跟它自己一个一个吐出来的结果分布完全一致。换句话讲,你白嫖了速度,没付任何质量的代价。这也是为啥投机解码这几年成了推理加速的标配,几乎所有正经的推理引擎都在用。

听着挺美对吧。但这里有个一直没解决干净的疙瘩。

草稿模型自己,也在一个一个吐字

问题出在那个小弟身上。

你想啊,让小弟猜接下来五个 token,那它自己是怎么猜的?主流的方案,比如名气很大的 EAGLE 系列,还有 Gemma 4、DeepSeek-V4 这些新模型自带的 MTP(multi-token prediction,多 token 预测)模块,它们的小弟在猜的时候,居然还是一个一个 token 自回归地往外蹦。

绕了一圈,慢的根源又回来了。

只不过这次是小弟在一个一个吐字。它吐得是比大佬快,因为它个头小,但那个不适合 GPU 的串行毛病,骨子里一点没改。而且草稿越长,这个串行的成本就越往上线性堆。为了不让小弟拖后腿,大家只能把草稿模型做得特别浅特别小,可模型一小,猜得就不准,猜不准验证时被打回的就多。

这就成了一个左右为难的死结。小弟做厚一点猜得准,但它自己吐字慢拖累整体;做薄一点吐字快,但猜得糙浪费验证。

我第一次理清这层的时候,有点想笑。绕了半天,大家是在用一个慢的东西去加速另一个慢的东西,中间那个慢还没人正面解决。

DFlash 干的,就是把这个死结正面拆了。

DFlash 的第一招,让小弟一口气把整块都猜出来

Z Lab 搞的 DFlash 第一个动作很狠,它直接不让草稿模型一个一个吐了。

它用了一种叫块扩散(block diffusion)的小草稿模型。扩散你大概在 AI 画图那边听过,就是从一团噪声里一次性把整张图糊出来再慢慢清晰。DFlash 把这套搬到了文字草稿上,一次前向计算,啪,整整一块 token 同时蹦出来,不再是排着队一个一个。

这正好是 GPU 最喜欢的姿势。

效果有多直接呢?博客里给了个特别戳人的对比,一个 5 层的 DFlash 草稿模型,哪怕一口气猜 4 个、8 个甚至 16 个 token,它的草稿延迟,都比 EAGLE-3 那种只猜 4 个 token 的单层草稿模型还要低。

你品一下这句话。又厚(5 层,猜得更准)又快(一次猜 16 个还更省时间)。原本那个二选一的死结,它一把给你都占了。小米新出的 MiMo v2.5-Pro-UltraSpeed 就是吃了这套,把输出速度干到了 每秒一千个 token 以上。一千 tok/s 什么概念?人正常阅读也就每秒五到七个字,这速度你眼睛根本追不上,屏幕上的字是整段整段往外刷的。

不过光快还不够。猜得快但猜得不准,验证时一顿打回,照样白搭。所以 DFlash 还有第二招,专门管猜得准。

DFlash 的第二招,把大佬的脑子借给小弟用

这一招我个人觉得是整篇里最漂亮的地方,叫 KV 注入(KV injection)。

先解释下 KV cache。大模型在生成的时候,会把前面读过的每个 token 算出来的一组中间状态缓存下来,省得后面重复算,这个缓存就叫 KV cache(你可以理解成模型的短期工作记忆,记着「我前面都读到了啥」)。这玩意是推理里最金贵的显存,我平时调度最头疼的就是它,一不留神就爆。

那 DFlash 的洞察是啥呢?它说,论上下文谁最懂,当然是大佬本人啊。小弟那么小一个,凭自己那点脑容量去重新理解一整段上下文,太吃力了。

所以 DFlash 干脆把大模型算出来的那些上下文中间状态,直接注射进草稿模型每一层的 KV cache 里。这一下,小弟就不用费劲从头消化上下文了,它直接借用了大佬现成的、最高质量的理解,把全部精力都砸在「接下来这一块该填啥」上面。

之前的 EAGLE 也想借大佬的脑子,但它只在草稿模型的入口喂了一次,越往草稿模型深层走,这点信号就越淡。DFlash 是每一层都给你注一遍,让小弟从头到尾都牢牢贴着大佬的理解在猜。

我读到这段的时候,脑子里冒出来的画面是,一个新来的实习生要写需求文档,方案一是让他自己从零读完所有背景资料,方案二是让最懂业务的架构师坐他旁边,每写一段就在他耳边补一句上下文。哪个写得又快又对,不用想。

数据也实在。同样给 Qwen 3-4B 配草稿模型,单独看 KV 注入这一招的威力,在 GSM8K 数学题上接受长度从 EAGLE-3 的 4.2 拔到了 4.8,HumanEval 写代码从 4.3 到 4.6。接受长度(acceptance length)就是小弟一轮平均能蒙对几个 token,这个数越高,大佬批量验一次就能往前多走几步,速度自然就上去了。

两招合体,省成本的同时还猜得更准

把这两招摆一块看,DFlash 的逻辑就特别清楚了。

投机解码到底快多少,就盯两个变量。一个是一轮能蒙对几个(接受长度),越高越好;另一个是小弟猜这一下额外花了多少成本,越低越好。过去的方案总是按下葫芦浮起瓢,想猜得准就得做厚,做厚成本就高。

DFlash 是两头一起摁。块扩散把猜的成本摁下去,KV 注入把猜的准头提上来。

合在一起,Qwen 3-4B 上的端到端数据是这样,数学题 GSM8K 提速 3.3 倍,写代码 HumanEval 提速 3.2 倍,综合对话 MT-Bench 提速 2.2 倍。而同样条件下传统的 EAGLE-3 只能做到 2.1 倍、2.2 倍、1.4 倍。

到了文章开头那个旗舰级的 Qwen 3.5 397B-A17B(A17B 是说这个模型虽然总参数三千九百多亿,但每次推理只激活其中一百七十亿,是现在主流的 MoE 稀疏架构),DFlash 在所有测的场景里都赢过了模型自带的 MTP,并发 1 的代码场景直接 4.3 倍起步,比 MTP 还快 1.5 倍。

这就是开头那个让我愣住的数字的来历。

但研究跑通,离你能用还隔着一条河

聊到这我得说句公道话。上面这些惊艳的数字,全是 Z Lab 在研究阶段自己实现里跑出来的。研究能跑通,和你我能在生产环境里真用上,中间隔着一条又深又宽的河。

这条河,做工程的人都懂。一个再漂亮的算法,从论文搬进一个高性能推理引擎,再把从主机调度到 GPU 执行的全链路性能榨干,每一步都是脏活累活。这次接力的是 SGLang 和 Modal 两边的团队,他们跟 Z Lab 一起,把 DFlash 真正塞进了 SGLang 这个开源推理引擎。

我看这部分看得格外仔细,因为这就是我日常在啃的那层。

最有意思的一个细节,SGLang 跑投机解码的时候,居然是那个草稿模型的 worker 在跟调度器对话,它反过来把大模型的 worker 包在里头,等草稿凑齐了再喊大佬来验。这个设计第一眼看反直觉,但你顺着 KV 注入那条线想就通了,是草稿这边主导整个节奏。博客特意提醒,你要是去翻代码或者看 trace,记着这层包裹关系,不然准看懵。

再就是 KV 注入落地时那个抠细节的劲儿。大佬那些中间状态如果老老实实存下来,会白白吃掉本就金贵的 KV cache 显存,而且相同前缀的请求还没法共享缓存。于是他们的做法是,在草稿正式开跑前先把这步投影抢着算完(叫即时物化),还为此专门写了层批量的线性投影,又拿 Triton 手搓了个融合算子去处理后面的归一化和位置编码。

这些东西外行看着枯燥,但我看着是真上头。漂亮的算法谁都想要,可愿意为了省那一点显存、快那几微秒,去手搓一个底层算子的团队,才是真把东西做到能上线的人。

真正卡脖子的,常常不是 GPU 不够快

SGLang 这次还顺手把一个更隐蔽的瓶颈给端了,这块我必须展开讲讲,因为太多人忽略它了。

大家一提推理慢,第一反应都是卡不够猛、算子不够快。但实际上有个杀手藏在你看不见的地方,叫主机和设备的同步开销(host-device synchronization)。

啥意思呢。一次推理不是 GPU 在那闷头算就完了,CPU 这边的调度器得不停地配合它,比如给下一批请求分配 KV 缓存、检查这一批有没有生成结束的停止符、更新各种元数据。问题在于,每当 CPU 停下来等 GPU 把上一批算完、或者 GPU 反过来干等 CPU 把活派下来,这一等,再快的卡再神的算子都白搭

这种你来我往的干等,特别像两个人抬一根木头上楼,本来该一起使劲,结果变成你抬一下我看一眼、我抬一下你歇一下,木头是上去了,但全程一大半时间俩人都在互相等。

SGLang 新的 V2 投机解码引擎,核心就一件事,把这种干等给重叠掉。它叫重叠调度器(overlap scheduler)。具体抓了两个机会,GPU 还在算第 N 批的时候,CPU 把第 N 减 1 批的收尾清理顺手干了;同时 CPU 给第 N 批分配缓存这事,也挪到 GPU 算第 N 减 1 批的空档里偷偷做完。

就这么个把空隙填满的操作,效果实打实。Qwen 3-8B 单张 B200、并发 32 的场景,吞吐从大约每秒 1.14 万 token 涨到了 1.53 万,提升超过 33%。卡没换,算子没改,纯粹是把以前浪费在互相等待上的时间抠了回来。

我做这行越久越觉得,性能优化到后面,比拼的根本不是谁堆的算力多,而是谁更舍得趴下去把那些藏在缝里的浪费一寸一寸抠干净。这事没什么性感的,但它是真的。

这事最让我舒服的,是它就摊在那给你用

写到这,我其实最想夸的不是那个 4.3x,而是这帮人的姿态。

模型他们一口气在三个 Hugging Face 组织下都发了一份,z-lab、modal-labs、lmsys 各放一份,你随便挑。代码全在 SGLang 的开源仓库里摊着,PR 链接就在博客里,你想看它到底怎么写的,点进去就行。启动命令也直接贴出来了,长是长了点,但每个参数都明明白白。

python -m sglang.launch_server \
  --model-path Qwen/Qwen3.5-397B-A17B \
  --speculative-algorithm DFLASH \
  --speculative-draft-model-path modal-labs/Qwen3.5-397B-A17B-DFlash \
  --speculative-dflash-block-size 8 \
  --tp-size 8 \
  --max-running-requests 32

你甚至能拿自己的数据,给自己的目标模型训一个专属的 DFlash 草稿模型,那套块扩散加 KV 注入的法子,对大部分主流大模型都通用。

我盯着这种东西的时候,常常会想到屏幕另一头那几个具体的人。博客末尾的致谢里就六个名字,Z Lab 三个,Modal 两个,SGLang 三个。一个能让全世界的大模型推理快上几倍的东西,落到实处,就是这么几个人,大概率也是在某个深夜,对着 trace 里一段怎么都对不齐的时间线,反复改那个融合算子。然后他们把成果原原本本摊在开源仓库里,不藏着掖着,谁都能拿走。

「小岛 AI」这个号名带着点航海的意思。我一直觉得,开源社区最动人的地方,就是它真的是一片公海。Z Lab 把投机解码这条航路又往前探了一段,Modal 和 SGLang 把这段新航路标进了所有人都能看的海图。下一个出海的人,不必再从零开始摸礁石,踩着前人插好的浮标,就能往更远的地方开。

是谁来自山川湖海,却把自己手里最快的那张海图,免费摊给了所有还在海上的人。

回到那个 4.3x。

它当然是个漂亮的工程成就。但我合上博客之后,留在脑子里的反倒不是这个数。是那种感觉,你以为速度已经到顶了,结果总有人愿意俯下身,去抠你压根没注意到的那条缝,然后告诉你,喏,这儿还能再快一截,拿去用吧。

这玩意儿,有点子牛逼。