自回归统治了 NLP 整整八年。它有一个无法绕开的物理缺陷:必须一个 token 一个 token 地蹦。
扩散语言模型(Diffusion LLM,dLLM)说:为什么要一个一个来?
但理想很丰满------开源 dLLM 跑起来,速度还不如同尺寸的 LLaMA。直到 ICLR 2026 上一篇论文把这个死结解开了。这篇文章,我们从数学原理讲到工程 trick,把这条路彻底拆清楚。
一、自回归的"串行原罪"
先说清楚我们要解决什么问题。
自回归(AR)模型生成 L 个 token,需要 L 次前向传播。每一次前向,模型要把全部参数从显存搬到计算单元,算完再等下一次。这意味着:
yaml
生成 1000 个 token
= 1000 次完整的前向传播
= 1000 次把几十 GB 权重从 HBM 搬到 SM
这里有个根本矛盾:解码是 memory-bound 的,不是 compute-bound 的。 GPU 的算力大部分时间在空转,等待权重搬运。你加大 batch,能把这个空闲算力利用起来;但 batch 已经打满之后,免费午餐就结束了。
于是单请求的低延迟生成,被死死卡在了"串行的次数"上。

扩散语言模型换了个思路:能不能一次前向就定下多个 token?
二、换个思路:从"加噪"到"掩码"
图像扩散是往像素上加高斯噪声。文本是离散的,没法加连续噪声------所以 dLLM 用的是离散扩散 ,主流做法是吸收态(absorbing state)掩码扩散。
2.1 前向过程:随机挖空
给定一个干净序列 x0,定义一个单调调度 αt∈0,1,其中 α0=1、 αT=0。前向过程对每个 token 独立地:
- 以概率 αt 保留原 token;
- 以概率 1−αt 替换成特殊的
[MASK]。
css
t=0 The quick brown fox jumps over the lazy dog ← 干净
t=0.3 The [M] brown fox [M] over the [M] dog
t=0.6 The [M] [M] fox [M] [M] [M] [M] [M]
t=1.0 [M] [M] [M] [M] [M] [M] [M] [M] [M] ← 全掩码
[MASK] 就是"吸收态"------一旦被掩码,就不会再变成别的 token,只等着被模型填回来。这个性质极其重要,它让模型简化成了一道完形填空题。
常用的调度有两种:
- 线性调度 : αt=1−t,掩码率随时间均匀增长,等价于对所有噪声水平等权;
- 余弦调度 (借鉴 DDPM):在轻度掩码阶段花更多步,因为大多数 token 的信息集中在轻噪区。
2.2 训练:其实就是加权版 BERT
反向过程是一个 Transformer,输入部分掩码的序列 xt 和时间步 t,输出每个掩码位置上对原始 token 的预测分布。
损失函数是掩码位置上的加权交叉熵:
L=∫011−α1 ECE(x0mask, x\^0)dα
这个闭式形式是 Sahoo 等人和 Shi 等人给出的连续时间 ELBO 化简结果。它揭示了一个关键事实:
dLLM 的训练目标,本质上就是一个"重加权"的掩码语言建模(MLM)损失------和 BERT 是同一个东西。
与 BERT 的三点差异:
| BERT | dLLM(MDLM / MD4) | |
|---|---|---|
| 掩码率 | 固定 15% | 从噪声调度中采样(10%~100%) |
| 损失权重 | 均匀 | 按调度导数加权,轻噪步权重高 |
| 注意力 | 双向(编码器) | 双向(可用 decoder-only 架构,去掉因果掩码) |
LLaDA 和 Mercury 用的都是 decoder-only + 非因果注意力。
2.3 推理:K 步,而不是 L 步
从全掩码的 xT 开始,跑 K 步去噪:
ini
while 还有 [MASK]:
logits = model(x_t, t) # 一次前向,预测所有掩码位
conf = softmax(logits).max(-1) # 每个位置的置信度
挑选一部分高置信度位置 → 提交(unmask)
其余位置保持 [MASK],下一轮再来
核心收益写在这里:
生成 L 个 token 的 wall-clock 成本是 K 次前向传播,与 L 无关(在显存允许范围内)。
AR 需要 L 次,dLLM 需要 K 次,而 K 可以远小于 L。这就是并行性的全部来源。
三、dLLM 的三张王牌
除了快,扩散范式还有两个自回归给不了的能力。
王牌 1:双向上下文,破解"逆转诅咒"
自回归模型被因果掩码锁死,只能看到左边。这导致著名的逆转诅咒(Reversal Curse):模型知道 "A 的父亲是 B",却答不出 "B 的儿子是谁"。
LLaDA 论文里的诗句补全实验是最干净的证据:
| 模型 | 正序 | 倒序 | 落差 |
|---|---|---|---|
| GPT-4o(2024-08 快照) | 82.7 | 34.3 | -48.4 |
| LLaDA-8B-Instruct | 51.8 | 45.6 | -6.2 |
注意读法:GPT-4o 正序远强于 LLaDA,但倒序崩了 48 分;LLaDA 只掉 6 分。dLLM 赢在对称性,不是赢在绝对能力。 这是因果掩码的代价第一次被量化得这么清楚。
王牌 2:编辑和填充是原生能力,不是特例
在文档中间补一段话、在函数签名和 return 之间填函数体------这正是掩码扩散的训练目标本身。
自回归模型要做到同样的事,必须把训练数据重排成 FIM(Fill-In-the-Middle)格式,然后祈祷这种重排能泛化。这是扩散范式唯一"不需要付出任何代价"的能力。
王牌 3:可迭代修正
LLaDA 官方采样器支持 remasking:已经解出来的位置如果置信度掉下来,可以在后续步骤被重新掩码、重新预测。这给了模型"后悔"的能力------自回归吐出去的 token 是收不回来的。
四、理想丰满,现实骨感:两个致命工程问题
理论上的并行,到了开源实现上却翻车了。跑过 LLaDA 或 Dream 的同学都知道一个尴尬的事实:它们的实际吞吐量往往还不如同尺寸的 LLaMA。
原始 LLaDA 在 GSM8K 5-shot 上精度 79.3%,但吞吐量只有 6.7 tokens/s。LLaMA-3-8B 精度略低,速度快得多。
ICLR 2026 上,港大、NVIDIA 和 MIT 的联合团队给出了诊断------扩散 LLM 缺了两样东西。
4.1 问题一:KV Cache 直接失效
自回归里,KV Cache 是推理加速的标配:每生成一个新 token,只需算当前的 K/V,之前的直接复用。
但 dLLM 用双向注意力------每个去噪步都要看到完整序列。传统 KV Cache 根本无从谈起:
css
AR: [已缓存 KV] + 新 token → 只算 1 个 token 的注意力
dLLM:每步全序列重算 → 计算量随长度线性爆炸
这意味着你虽然把 L 次前向降到了 K 次,但每一次前向的代价却涨了。并行省下的时间,被重复计算吃回去了。
4.2 问题二:并行解码的"条件独立假设"崩塌
如果说缓存问题是"每一步算太多",这个问题是"并行本身会毁掉质量"。
τ-leaping 策略允许单步内从多个掩码位置同时采样,数学上它把联合概率近似成了边际概率的乘积:
p(xsi,xsj∣xt)≈p(xsi∣xt)⋅p(xsj∣xt)
这个近似在 token 之间没有强依赖时问题不大,一旦存在结构化共现关系就出洋相。论文给的经典例子:
sql
"The list of poker hands: high card, ..., full house"
位置 A 候选:high / full
位置 B 候选:card / house
独立采样 → 可能拼出 "high house" ← 语义灾难
所以实验显示:LLaDA 在每步只生成 1 个 token 时表现最好,一旦并行解码多个 token,质量迅速劣化。
尴尬的结论:理论上能并行,实际上不敢并行。
五、Fast-dLLM:两把钥匙解开死结
Fast-dLLM 的优雅之处在于------不需要重新训练,不需要改架构,即插即用。只用两个洞察,拿到了数量级加速。
5.1 钥匙一:块级近似 KV Cache + DualCache
洞察 :虽然每个去噪步的 KV 严格来说都不同,但相邻步骤之间 KV 激活的余弦相似度极高 (论文的热图显示 i≈j 时接近 1.0)。既然变化小到可以忽略,那就足以支撑缓存复用。
做法:块级解码(Block-Wise Decoding)。
scss
序列切块: [Prompt][Block 0][Block 1][Block 2]
解码 Block 1 时:
├─ 先算好并缓存 Prompt / Block 0 / Block 2 的 KV
├─ 在 Block 1 的多个去噪步中反复复用这些缓存
└─ Block 1 解码完成后,统一更新全序列 KV(可与解码步合并,无额外开销)
为什么不全局缓存?因为步间隔拉大后相似度会下降(比如 step 16 vs step 64 时深层相似度明显衰减)。只在"足够相似"的范围内复用,这是块级而非全局的原因。
DualCache 更进一步 :自回归只缓存左侧前缀就够了,但扩散是双向的------右侧还处于掩码状态的 token 同样参与注意力计算。而这些 mask token 的 KV 表示在块解码过程中同样高度稳定,完全可以提前算好存下来。
所以 DualCache = 前缀缓存 + 后缀缓存。
5.2 钥匙二:置信度感知的并行解码
洞察 :与其强行建模 token 间的依赖(要引入辅助模型),不如只对那些"不太需要依赖"的 token 并行解码。
如果一个 token 模型已经很有把握,它受其他位置的影响本来就有限,并行采样的风险极低。作者把这个直觉形式化成一个定理:
定理 1(高置信度并行解码) :若待解码的 n 个位置中,每个位置的最优 token 概率都大于 1−ε,且满足 (n+1)ε≤1,则贪心并行解码与贪心顺序解码的结果完全一致。
也就是说:在足够确信的区域,并行不会改变输出。定理还给出了不完全满足严格条件时,联合分布与边际乘积之间的总变分距离和 KL 散度上界------偏差严格可控。
做法:每一步,对所有仍处于掩码状态的位置计算置信度(softmax 最大概率)。只有超过阈值的才并行解码;其余保持掩码,留给后续步骤。如果都没超阈值,就至少解置信度最高的那一个,防死循环。
这和 LLaDA 原来的 top-K 策略有本质区别:
| 策略 | 行为 | 问题 |
|---|---|---|
| Top-K | 固定每步解 K 个,不管靠不靠谱 | 简单处浪费、困难处出错 |
| 阈值法 | 动态的:简单处一步解几十个,困难处一步只解一个 | --- |
阈值选择的消融(GSM8K):
| 阈值 | 每步平均解码 token 数 | 精度 |
|---|---|---|
| 0.5(激进) | 7.01 | 77.01% |
| 0.9(采用) | 3.25 | 78.5% |
| 1.0(退化) | 1.00 | 最高但最慢 |
| 基线(非并行) | --- | 79.3% |
0.9 是精度-速度的最佳平衡点。
论文还有进阶版 Factor-Based Decoding :不用固定阈值,而是根据定理 1 的边界自适应决定并行度------给定 n 个候选 token 的置信度排序,找到最大的 n 使得 (n+1)(1−c(n))≤1 成立。
5.3 实测:27.6 倍
在 1024 长度、8-shot GSM8K 设置下,端到端拆解非常直观:
scss
原始 LLaDA 266.0 秒 (77.3%)
+ 并行解码 20.0 秒 (13.3x)
+ PrefixCache 12.0 秒 (18.6x)
+ DualCache 9.6 秒 (27.6x, 76.0%)
其他结果:
| 模型 / 任务 | 基线吞吐 | Fast-dLLM | 加速 | 精度变化 |
|---|---|---|---|---|
| LLaDA-Instruct / GSM8K 256 | 6.7 tok/s | 54.4 tok/s | 8.1x | 79.3% → 78.5% |
| LLaDA-Instruct / GSM8K 512 | --- | 35.3 tok/s | 11.0x | ≈ -1pt |
| LLaDA-Instruct / HumanEval | --- | 114.1 tok/s | 3.7x | 43.3% |
| Dream-Base / GSM8K 256 | 7.7 tok/s | 50.1 tok/s | 6.5x | 75.0% → 74.0% |
| LLaDA-V / MathVista | --- | 28.2 tok/s | 9.9x | 59.7% → 56.6% |
所有任务精度损失控制在 1--2 个百分点以内,个别任务甚至微涨。
关键规律:序列越长,加速比越高(256 长度 9.4x → 1024 长度 27.6x),因为更长的序列意味着更多的缓存复用机会。
而且这两个组件与其他加速方法正交兼容:与 dParallel(蒸馏少步扩散)结合时,PrefixCache 还能再带来 1.84 倍吞吐提升,GSM8K 精度反而从 76.5% 涨到 77.1%。
六、生产现实:真正跑起来的是"块扩散"
讲到这里,必须泼一盆冷水:在 1000 token 的画布上做纯扩散,几乎不是生产系统真正在跑的东西。
实际上线的形态是块扩散(Block Diffusion):
块间:从左到右,自回归推进(保证 KV Cache 精确、误差不扩散)
块内:并行去噪(吃扩散的并行红利)
- Mercury 和 DiffusionGemma 都按块去噪,DiffusionGemma 的块大小是 256 token;
- LLaDA 支持同样的方案,叫 semi-autoregressive remasking,无需重新训练。
这个折中同时拿到三样东西:块之前的 KV Cache 是精确的、单次错误并行提交的传播范围被限定在块内、模型在构造上是半自回归的。
所以真正的问题不是"扩散能不能替代自回归",而是"一次能安全提交多大的块"。今天的答案是:几个 token。
什么场景赚,什么场景亏
Google 自己公布的 Gemini Diffusion 数据最有说服力------同一对模型,两个相反的结论:
| 基准 | Gemini Diffusion | Gemini 2.0 Flash-Lite | 结果 |
|---|---|---|---|
| LiveCodeBench v6 | 30.9 | 28.5 | ✅ 扩散赢 |
| GPQA Diamond | 40.4 | 56.5 | ❌ 扩散输 |
差异的根源是:一个 token 的含义有多依赖同时被决定的其他 token。
紧约束的代码 → 大赚;多步科学推理 → 血亏。
为什么代码是 dLLM 的最佳战场? 因为一段补全里,很大一部分是缩进、闭合括号、重复标识符和样板代码------这些 token 的值被上下文钉死了,彼此之间几乎不互相约束,正是"可以安全一起提交"的那类 token。
Inception Labs 的 Mercury Coder Mini 在 H100 上被 Artificial Analysis 实测到 1109 输出 token/秒,比同质量的自回归模型快约一个数量级。
不适合的场景也很明确:需要流式输出的对话 UI (扩散天然不会像 AR 那样流式吐字)、复杂工具调用 (生态不成熟)、顶级推理任务(榜首仍是自回归)。
七、给你的选型决策树
如果你在评估要不要上 dLLM,按这个顺序问:
markdown
Q1. 你的任务是高吞吐的长文本/代码生成吗?
├── 是 → Q2
└── 否 → Q3
Q2. 输出 token 之间依赖强吗?(数学证明 / 多步推理)
├── 弱(代码、样板、结构化填充)→ ✅ 试扩散
└── 强 → ⚠️ 自回归,别折腾
Q3. 需要流式输出到 UI 吗?
├── 是 → ❌ 自回归
└── 否 → Q4
Q4. 需要中间编辑 / 完形填空吗?
├── 是 → ✅ 扩散是原生能力
└── 否 → 自回归更稳妥(生态成熟度差距明显)
三条实践建议:
- 在自己的任务上测,不要看公开基准。 公开榜的分差远小于你的真实业务分差;
- 测端到端延迟,包括流水线差异。 没有流式输出这一条,会改变整个前端交互设计;
- 保留自回归兜底。 2026 年的现实是分层部署,不是二选一。
八、我的判断:不是替代,是分层
写到这里,可以给个结论了。
Fast-dLLM 这类工作最重要的意义,不是那个 27.6 倍的数字,而是它证明了:扩散 LLM 的效率瓶颈是工程性的,不是结构性的。
当 27.6 倍加速不再需要重新训练模型,扩散路线离真正可用的部署就近了一大步。
但"可用"不等于"通吃"。我倾向于这样看 2026--2027 的格局:
┌─────────────────────────────────────────────────┐
│ 需要顶级推理 + 工具调用 + 流式交互 │
│ → 自回归(默认选择) │
├─────────────────────────────────────────────────┤
│ 高吞吐代码补全 / 批量结构化生成 / 文档生成 │
│ → 扩散(吞吐优势明确) │
├─────────────────────────────────────────────────┤
│ 中间编辑 / 完形填空 / 需要迭代修正 │
│ → 扩散(唯一不付代价的能力) │
└─────────────────────────────────────────────────┘
还有一个更值得关注的信号:端侧。2026 年推理需求预计达到训练需求的 4--5 倍,端侧设备对低延迟、高能效的渴求,正是扩散模型并行性的天然舞台。近期已有扩散语言模型团队与端侧计算平台合作,报告在 AI PC 等场景把端侧 Agent 提速约 5 倍、部分场景达到自回归模型的 10 倍。如果这个数字站稳,扩散路线最大的落地机会可能不在云端,而在你我手上的设备里。
自回归不会死,但它不再是唯一答案。这对所有人都是好事。
参考
- Fast-dLLM(ICLR 2026, 港大 / NVIDIA / MIT):论文 · GitHub
- LLaDA: Large Language Diffusion Models(人大 / 清华)
- MDLM / MD4:离散扩散的形式化基础(Sahoo et al., Shi et al.)
- Inception Labs Mercury Coder、Google DiffusionGemma / Gemini Diffusion 官方模型页
- 文中基准数据来自 Artificial Analysis 与各家官方公布结果
如果这篇文章对你有帮助,欢迎点赞收藏。有不同看法也欢迎评论区讨论------特别是正在生产环境跑 dLLM 的同学,很想听听真实数据。