DFlash 块扩散解码:以并行扩散替代自回归草稿,实现无损 6 倍推理加速

7754 字
39 分钟
DFlash 块扩散解码:以并行扩散替代自回归草稿,实现无损 6 倍推理加速

AI 生成内容声明

背景与问题定义#

大语言模型的推理有一个根本性矛盾:transformer 的并行计算能力在预填充阶段可以充分利用,但在解码阶段却几乎完全被浪费

自回归解码的本质决定了每个 token 的生成都依赖前一个 token。对于 batch size 为 1 的交互式场景,每次前向传播只产生一个 token,GPU 的数千个计算核心大部分时间在等待数据搬运。以一台搭载 H100 的推理服务器为例,解码阶段的 MFU(Model FLOPs Utilization)通常不到 5%——95% 以上的算力在闲置。

这个问题催生了投机解码:用一个小型草稿模型快速预测多个候选 token,然后让目标模型一次性验证整个候选块。被接受的 token 直接使用,被拒绝的从分歧点重新采样。理想情况下,“草稿+验证”的耗时远小于逐个生成,就能实现显著的端到端加速。

投机解码已有三代代表性工作:

  • 第一代——独立草稿头(Medusa):在目标模型上附加多个独立分类头,每个头直接预测未来第 k 个 token。不需要单独的草稿模型,但因为各头之间没有条件依赖,预测质量差,接受率低。
  • 第二代——自回归草稿模型(EAGLE 系列,含 EAGLE-3):用一个轻量级自回归 transformer 作为草稿模型,每次预测一个 token,逐步构建候选序列。EAGLE-3 能达到 2-3 倍加速,但草稿过程仍然是逐 token 的:预测 8 个草稿 token 需要 8 次前向传播。
  • 第三代——DSpark 半自回归草稿:之前文章已经详细讲过。DSpark 把草稿生成做成”一次并行预测 + 置信度校验”,在半自回归框架下实现了最高 85% 的生成加速。但 DSpark 的草稿仍然是在序列维度上的一次性预测,缺乏迭代纠错机制。

一个自然的追问是:能不能让草稿模型也像图像的扩散模型那样,一次性并行生成整个候选块?

这就是 DFlash 要回答的问题。

核心思想#

DFlash(Block Diffusion for Flash Speculative Decoding)的核心思路只有一句话:

用轻量级块扩散模型替代自回归草稿模型,将整个草稿块的所有 token 在一次前向传播中并行生成,然后用目标模型一次性验证。

这里的关键词是”块扩散”。不同于图像扩散模型在连续的高斯噪声空间中迭代去噪,DFlash 的”扩散”发生在离散 token 空间:一个候选块中,除第一个锚点 token 外的所有位置被初始化为 [MASK] token,等效于”全噪声”状态;草稿模型的一次前向传播完成从”全噪声”到”预测 token”的去噪过程。

打个比方:自回归草稿模型像一个打字员,逐字敲出草稿;DFlash 像一个填字游戏玩家,看着上下文和空格位置,一眼把整个空填完。

DFlash 与已有方法的本质区别:

方法草稿生成方式草稿耗时块大小可扩展性
EAGLE-3自回归逐 token线性增长 O(k)差,k>8 后延时代价超过收益
DSpark半自回归并行接近常数中等,受置信度调度影响
DFlash块扩散并行接近常数优,k 增长几乎不增加草稿耗时

这个本质区别的代价是:每个 token 位置的条件依赖被削弱了。自回归生成中,第 k 个 token 显式地以第 1 到第 k-1 个 token 为条件;块扩散中,所有位置同时预测,只能以锚点 token 和目标模型的隐藏状态为条件。这会导致单 token 预测准确率下降——但 DFlash 通过一个关键设计弥补了这一点:KV 注入

原理详解#

投机解码的通用框架#

在深入 DFlash 之前,先回顾投机解码的通用流程。

设目标模型为 T\mathcal{T},草稿模型为 D\mathcal{D},块大小为 kk。给定前缀序列 x<tx_{<t}

  1. 草稿阶段D\mathcal{D} 生成候选序列 x^t,x^t+1,,x^t+k1\hat{x}_t, \hat{x}_{t+1}, \dots, \hat{x}_{t+k-1}
  2. 验证阶段T\mathcal{T}(x<t,x^t,,x^t+k1)(x_{<t}, \hat{x}_t, \dots, \hat{x}_{t+k-1}) 做一次前向传播,得到每个位置的输出分布 pT(x<t,x^<t+i)p_{\mathcal{T}}(\cdot \mid x_{<t}, \hat{x}_{<t+i})
  3. 接受/拒绝:从第一个位置开始,逐一比较草稿 token x^t+i\hat{x}_{t+i} 与目标模型在该位置的采样结果。找到第一个不匹配的位置 t+jt+j,接受前 jj 个 token,在该位置重新采样,丢弃后面的所有 token。

关键性质:无论草稿模型如何,验证后的输出分布严格等于目标模型的自回归分布。投机解码是”无损加速”——加速多少取决于草稿模型与目标模型的一致程度,但正确性不会妥协。

实际加速比可以写为:

speedup=kttargettdraft+tverify\text{speedup} = \frac{k \cdot t_{\text{target}}}{t_{\text{draft}} + t_{\text{verify}}}

其中 ttargett_{\text{target}} 是目标模型生成一个 token 的耗时,tdraftt_{\text{draft}} 是草稿阶段耗时,tverifyt_{\text{verify}} 是验证阶段耗时。tverifyt_{\text{verify}} 通常接近 ttargett_{\text{target}}(只多了一点注意力计算开销),所以加速比主要由两个因素决定:(1)草稿模型的预测精度(影响有效接受的 token 数),(2)草稿耗时相对于目标模型耗时的比例。

块扩散:从逐 token 到全块并行#

DFlash 的草稿阶段完全抛弃了自回归结构。给定锚点 token(即上一轮目标模型产生的 bonus token),草稿块构建如下:

  1. 将锚点 token 放在位置 0。
  2. 位置 1 到 k1k-1 全部填充为 [MASK] token。
  3. 整个块通过草稿模型做一次前向传播。
  4. 所有 [MASK] 位置的输出 logits 直接用作预测 token。

EAGLE-3 自回归草稿(左)与 DFlash 块扩散草稿(右)的对比:前者逐 token 串行生成,后者一次前向并行生成整个草稿块
EAGLE-3 自回归草稿(左)与 DFlash 块扩散草稿(右)的对比:前者逐 token 串行生成,后者一次前向并行生成整个草稿块

图源:NVIDIA Technical Blog《Boost Inference Performance up to 15x on NVIDIA Blackwell Using DFlash Speculative Decoding》

草稿模型内部使用双向(非因果)注意力。这意味着位置 3 的预测可以同时看到位置 1、2、4、5 的信息——这在自回归草稿中是不可能的。双向注意力允许模型利用”全局一致性”来生成更连贯的草稿块;例如在生成代码时,如果位置 2 预测了 for,位置 5 可以同时”知道”这个上下文并预测 range,而不需要等位置 2 先生成出来。

但这里有一个微妙之处:双向注意力的”全局一致性”有利有弊。好处是跨位置的信息交换;坏处是各个位置的预测实际上互相影响,可能导致”集体错觉”——一个位置的错误预测通过注意力扩散到其他位置,造成整个块的系统性偏差。这也是为什么后续工作 JetSpec 将注意力改回因果结构的动机之一。

草稿耗时的分析如下。设草稿模型的一次前向传播耗时为 tdt_d,目标模型的一次前向传播耗时为 tTt_T。对于自回归草稿模型(如 EAGLE-3),生成 kk 个草稿 token 的耗时为 ktdk \cdot t_d;对于 DFlash,无论 kk 多大,耗时都是 tdt_d

取一组典型数据:5 层 DFlash 草稿模型的 td0.01tTt_d \approx 0.01 t_T(即目标模型耗时的 1%)。EAGLE-3 单层草稿模型的每步耗时约为 0.02tT0.02 t_T。生成 16 个草稿 token 时,DFlash 只需 0.01tT0.01 t_T,EAGLE-3 需要 16×0.02tT=0.32tT16 \times 0.02 t_T = 0.32 t_T——差了 32 倍。

这就是为什么即使 DFlash 的单 token 预测准确率低于 EAGLE-3,它的端到端加速比仍然更高:草稿开销低到几乎可以忽略,使得更大的块成为可能

KV 注入:让每个草稿层直接感知目标模型#

DFlash 推理设计:从目标模型提取的多层隐藏特征经融合后,注入每个草稿层的 KV 缓存以实现条件化投机解码
DFlash 推理设计:从目标模型提取的多层隐藏特征经融合后,注入每个草稿层的 KV 缓存以实现条件化投机解码

图源:DFlash 论文 Figure 2(arXiv:2602.06036)

这是 DFlash 最关键的设计决策。要理解为什么需要它,先看 EAGLE-3 的做法。

EAGLE-3 将目标模型最后一层的隐藏状态拼接到草稿模型的输入嵌入中。这个设计有一个根本局限:目标模型的特征信号只在输入层注入,经过多个 transformer 层的变换后,信号逐渐被稀释。深层草稿层几乎看不到目标模型的原始特征,只能依赖前面层传来的、经过多次变换的间接信号。

DFlash 的做法完全不同:

  1. 从目标模型的多个中间层提取隐藏状态。默认选取 5 层,均匀分布在目标模型的第 2 层到倒数第 3 层之间(例如在 28 层模型中取第 [1, 8, 14, 20, 27] 层)。这些层捕获了不同粒度的语义信息——浅层有更多局部句法特征,深层有更多全局语义特征。

  2. 融合提取的隐藏状态。通过一个线性投影层,将来自不同层的隐藏状态(各自维度为 dmodeld_{\text{model}})拼接后映射到一个紧凑的”目标上下文特征”向量:

    hctx=Wf[hl1;hl2;;hlm]+bfh_{\text{ctx}} = W_f \cdot [h_{l_1}; h_{l_2}; \dots; h_{l_m}] + b_f

    其中 WfRdmodel×(mdmodel)W_f \in \mathbb{R}^{d_{\text{model}} \times (m \cdot d_{\text{model}})} 是投影矩阵,mm 是选中的目标模型层数。

  3. 将融合特征注入每个草稿层的 KV 缓存。对草稿模型的每一层,hctxh_{\text{ctx}} 被分别投影为 Key 投影和 Value 投影,写入该层注意力模块的 KV 缓存中:

    Kctx(l)=hctxWK(l),Vctx(l)=hctxWV(l)K_{\text{ctx}}^{(l)} = h_{\text{ctx}} \cdot W_K^{(l)}, \quad V_{\text{ctx}}^{(l)} = h_{\text{ctx}} \cdot W_V^{(l)}

    其中 ll 是草稿层索引。在注意力计算中,草稿 token 的 Query 不仅对草稿 token 自身的 Key/Value 做注意力,也对注入的 Kctx(l)/Vctx(l)K_{\text{ctx}}^{(l)} / V_{\text{ctx}}^{(l)} 做注意力:

    Attention(Qdraft,[Kdraft;Kctx],[Vdraft;Vctx])\text{Attention}(Q_{\text{draft}}, [K_{\text{draft}}; K_{\text{ctx}}], [V_{\text{draft}}; V_{\text{ctx}}])
  4. 跨轮复用。同一个草稿步骤中,hctxh_{\text{ctx}} 只需要提取一次,然后在所有草稿层、多个草稿轮次中复用(存储在 KV 缓存中)。

这个设计的核心优势:每个草稿层都能直接接触到目标模型的多粒度语义特征。浅草稿层能看到目标浅层的句法信息,深草稿层能看到目标深层的语义信息。这种”深度耦合”远比只在输入层注入一条信号有效。

实验数据也印证了这一点。在 GSM8K 数学推理任务上,同等 5 层草稿模型的条件下:

  • 仅输入层融合(EAGLE-3 方式):平均接受长度 τ=3.5\tau = 3.5
  • 逐层 KV 注入(DFlash 方式):平均接受长度 τ=4.2\tau = 4.2

20% 的接受长度提升,完全来自特征注入方式的改变。这直接转化为约 20% 的额外加速。

训练策略:随机锚点采样与衰减加权损失#

DFlash 的训练有三个关键设计。

随机锚点采样

推理时,草稿模型需要在任意位置启动扩散过程——本轮可能的锚点 token 可以出现在回复序列的任何位置。训练必须覆盖这种多样性。

具体做法:在每条训练样本的回复序列中,随机采样多个有效位置作为锚点(只采样 loss_mask > 0.5 的位置,排除填充和提示部分)。每个锚点标记一个块的起始位置,其后的 k1k-1 个位置被 mask 为预测目标。多个块被拼接成一条训练序列,通过 Flex Attention 的稀疏掩码隔离:

  • 块内双向可见:同一块内的所有位置可以互相看到(双向注意力)。
  • 目标特征始终可见:所有位置都能注意到 KV 注入的 hctxh_{\text{ctx}}
  • 块间完全隔离:不同块之间不可见,防止信息泄漏。

每个训练序列最多包含 512 个锚点,这意味着每个样本可以提供多达 512 个独立的草稿训练信号。这种高密度采样极大地提高了训练效率——DFlash 用 EAGLE-3 约 1/5 的训练数据量就超越了它的表现。

DFlash 训练注意力结构:块内双向可见、目标上下文特征始终可见、块间完全隔离以防止信息泄漏
DFlash 训练注意力结构:块内双向可见、目标上下文特征始终可见、块间完全隔离以防止信息泄漏

图源:DFlash 论文 Figure 4(arXiv:2602.06036)

指数衰减位置权重

投机解码的验证过程是逐位置顺序进行的:一旦在位置 j 发现草稿 token 与目标模型不一致,位置 j 之后的所有 token 都被丢弃。这意味着早期位置的准确率远比晚期位置重要——位置 1 的错误直接浪费整个块,位置 15 的错误只浪费最后一个 token。

DFlash 用一个指数衰减权重来体现这个优先级。对块内第 ii 个预测位置(i=1,2,,k1i = 1, 2, \dots, k-1i=0i=0 是锚点不计 loss),权重为:

wi=exp(i1γ)w_i = \exp\left(-\frac{i-1}{\gamma}\right)

其中 γ\gamma 是衰减因子。当 γ\gamma 较小时(如 γ=3\gamma = 3),早期位置的权重远大于晚期位置;当 γ\gamma 较大时(如 γ=10\gamma = 10),权重分布更均匀。论文中的默认设置倾向于较小的 γ\gamma,以强约束早期位置精度。

最终训练损失为加权交叉熵:

LDFlash=i=1k1wiCE(p^i,yi)\mathcal{L}_{\text{DFlash}} = \sum_{i=1}^{k-1} w_i \cdot \text{CE}(\hat{p}_i, y_i)

其中 p^i\hat{p}_i 是草稿模型在位置 i 的预测分布,yiy_i 是目标模型在该位置的真实 token。

D-PACE 变体(Dynamic Position-Aware Cross-Entropy)

标准 DFlash 损失对所有训练样本使用固定的衰减权重。D-PACE 更进一步:动态估计每个位置的学习难度,对困难位置分配更高权重

具体做法:维护每个位置的平均历史损失 ˉi\bar{\ell}_i。对当前批次,计算:

wiDPACE=wiiˉiw_i^{\text{DPACE}} = w_i \cdot \frac{\ell_i}{\bar{\ell}_i}

如果一个位置的损失显著高于历史平均,说明该位置对当前样本特别困难,应获得更高权重。这使得训练更聚焦于每个样本的”瓶颈 token”——那些草稿模型反复预测错误的关键位置。

验证流程#

验证阶段保持投机解码的标准流程,没有任何变化:

  1. 目标模型接收 [前缀; 锚点; 草稿1; 草稿2; ...; 草稿k-1] 的完整序列。
  2. 一次前向传播后,得到每个位置的条件概率分布 pT(前缀,锚点,草稿<i)p_{\mathcal{T}}(\cdot \mid \text{前缀}, \text{锚点}, \text{草稿}_{<i})
  3. 从位置 1 开始,逐一比较草稿 token 与目标模型的贪婪采样结果(或温度采样结果)。
  4. 找到第一个不匹配的位置,接受之前的所有 token,在该位置用目标模型重新采样作为 bonus token。
  5. 返回步骤 1,以新 bonus token 作为锚点开始下一轮。

整个过程保证了最终输出分布严格等于目标模型的自回归分布——这是”无损加速”的含义。

架构与实现细节#

草稿模型架构#

DFlash 草稿模型是一个极轻量级的 Qwen3 风格 decoder-only transformer。一个典型的 5 层草稿模型参数约 340M,主要配置如下:

参数说明
层数5远少于目标模型(通常 28-40 层)
隐藏维度与目标模型相同保证特征维度对齐
注意力头数22(Q)/ 22(KV)与目标模型匹配
头维度128标准配置
中间层维度9728FFN 膨胀比约 3.5
词表大小与目标模型相同共享嵌入层和 LM Head
块大小8 或 16高并发场景用 8,低并发用 16

草稿模型共享目标模型的嵌入层(embed_tokens)和输出投影层(lm_head),且这两部分在训练和推理中都是冻结的。这意味着草稿模型不需要存储两份词表,节省了大量显存。

为什么用 5 层?这是精度与速度的权衡。层数越多,预测精度越高,但草稿耗时也线性增加。论文的消融实验显示:2 层草稿在接受长度上显著弱于 5 层;8 层相比 5 层的接受长度提升很小(<5%),但耗时增加了近 60%。5 层是 experimentally found sweet spot。

目标特征提取与融合#

目标模型中间层特征的提取在目标模型预填充阶段完成,不需要额外的目标模型前向传播。具体流程:

  1. 目标模型处理输入前缀,逐层计算直到最后一层。
  2. 在预设的中间层位点(如 [1, 8, 14, 20, 27])处,hook 该层的隐藏状态输出。
  3. 将 hook 到的隐藏状态保存到 KV 缓存中,供后续草稿轮次使用。

一个重要的实现细节:选定的是哪些层? 默认策略是从目标模型的第 2 层到倒数第 3 层之间均匀采样 5 层。为什么跳过了第一层和最后两层?第一层的隐藏状态太接近输入嵌入,语义信息太少;最后两层的隐藏状态已经高度压缩,包含过多任务特定信息,用于草稿模型的通用预测时反而可能引入噪声。

关键伪代码#

以下伪代码展示了 DFlash 推理的核心流程:

def dflash_generate(target_model, draft_model, prefix, block_size=16):
# 1. 预填充:目标模型处理前缀
# target_features 是从多个中间层 hook 的隐藏状态
logits, target_features = target_model.prefill(
prefix,
hook_layers=[1, 8, 14, 20, 27]
)
# bonus_token 是预填充的输出 token
bonus_token = sample(logits[-1])
generated = [bonus_token]
# 2. 将目标特征融合并注入草稿模型的所有层
context_feature = draft_model.fuse_features(target_features)
draft_model.inject_kv_context(context_feature) # 注入所有草稿层
while not done:
# 3. 构建草稿块:[anchor, MASK, MASK, ..., MASK]
anchor_id = token_to_id(bonus_token)
draft_block = [anchor_id] + [MASK_TOKEN_ID] * (block_size - 1)
# 4. 块扩散:一次前向传播预测所有 MASK 位置
draft_logits = draft_model.forward(
draft_block,
attention_mask="bidirectional", # 块内双向注意力
use_kv_context=True # 使用注入的目标特征
)
# 取每个 MASK 位置的 argmax 作为草稿 token
draft_tokens = [argmax(logits[i]) for i in range(1, block_size)]
# 5. 验证:目标模型一次性检查整个块
full_seq = generated + draft_tokens
target_logits = target_model.forward(full_seq)
# 6. 接受/拒绝
accepted = []
for i, draft_tok in enumerate(draft_tokens):
target_tok = argmax(target_logits[len(generated) + i])
if draft_tok == target_tok:
accepted.append(draft_tok)
else:
# 分歧点:用目标模型的 token 作为新 bonus
bonus_token = target_tok
accepted.append(bonus_token)
break
else:
# 全部接受:最后一个位置的预测作为 bonus
bonus_token = sample(target_logits[-1])
generated.extend(accepted)
return generated

训练流程#

训练数据以对话形式的指令微调数据为主。每条样本包含指令、上下文和期望回复。训练流程:

  1. 数据准备:用目标模型对训练数据做一次完整的前向传播,在每个位置的隐藏状态都保存下来(这一步最耗时,但只做一次)。
  2. 锚点采样:在每条回复中随机采样多达 512 个锚点位置。
  3. 块构建与掩码:为每个锚点构建 [anchor, MASK, ..., MASK] 的草稿块,块大小等于训练块大小(通常 16)。
  4. 多块拼接:将所有块按 Flex Attention 稀疏掩码拼接成一条长序列,块间互不可见。
  5. 前向+损失:草稿模型前向传播,计算衰减加权交叉熵损失。
  6. 优化:AdamW 优化器,学习率 6×1046\times 10^{-4},线性衰减。

训练数据量因模型而异。以 Qwen3-Coder-30B-A3B 的 DFlash 草稿模型为例,训练数据包括:

  • NVIDIA Nemotron-Post-Training-Dataset-v2(代码部分):约 200K 样本
  • evol-codealpaca-v1:约 50K 样本
  • Cline 执行轨迹:约 39K 样本
  • 合计约 289K 样本

相比之下,EAGLE-3 的训练使用了约 1.4M 样本的 open-perfect-blend 数据集。DFlash 用约 1/5 的数据量就超越了 EAGLE-3 的加速比,数据效率显著更高。原因在于:

  • 每个样本通过多锚点采样提供了数百个训练信号,而非自回归方法的一个。
  • KV 注入提供了更强的条件信号,降低了模型对数据量的依赖。

性能表现#

主要基准测试#

以下数据来自 DFlash 论文和社区验证,涵盖不同模型规模、不同硬件、不同工作负载。

Qwen3-8B 上 DFlash 与 EAGLE-3 相对自回归解码的加速对比,DFlash 整体高出 EAGLE-3 约 2.5 倍
Qwen3-8B 上 DFlash 与 EAGLE-3 相对自回归解码的加速对比,DFlash 整体高出 EAGLE-3 约 2.5 倍

图源:DFlash 论文 Figure 1(arXiv:2602.06036)

Qwen3-8B 上的加速比(greedy decoding)

任务基准 (tok/s)EAGLE-3 加速DFlash 加速
MATH-500282.4×6.08×
HumanEval252.3×5.52×
GSM8K222.1×4.32×
MT-Bench301.9×3.14×
ShareGPT321.7×2.71×

代码和数学类任务加速最显著(4-6×),因为这类文本的结构性强、可预测性高,块扩散能充分利用全局一致性。开放域对话的加速较小(2-3×),但仍然是显著的。

Qwen3.6-35B-A3B(MoE 模型,GB10 平台)

基准无投机 (tok/s)DFlash (tok/s)加速比
GSM8K22954.3×
HumanEval251104.4×
MT-Bench28863.1×
ShareGPT30822.7×

MoE 模型由于稀疏激活的特性,单 token 生成的计算量相对更大,投机解码的相对收益更高。

Gemma 4 26B-A4B(RTX 5090,三种方法的直接对比)

方法解码速度 (tok/s)加速比接受长度单 token 接受率
无投机1921.00×
EAGLE-33251.69×2.4448%
DFlash (k=15)4222.19×3.4516%
MTP4112.13×3.8571%

注意这个表中一个反直觉的数据点:DFlash 的单 token 接受率只有 16%,远低于 EAGLE-3 的 48%,但接受长度(3.45)和端到端加速(2.19×)都更高。这是因为 DFlash 一次并行生成 15 个草稿 token,即使大部分被拒绝,只要平均有 3.45 个被接受,就已经值得了——生成这 15 个草稿的开销几乎和 EAGLE-3 生成 3 个草稿差不多。

按工作负载分解(Gemma 4,DFlash vs EAGLE-3 加速比)

工作负载EAGLE-3DFlash
散文/叙事1.30×1.04×
问答1.50×1.32×
代码1.75×1.55×
JSON 输出2.01×2.68×
重复性文本1.88×4.37×

DFlash 在不同工作负载上的表现差异极大——从散文叙事的几乎无加速,到重复性文本的 4.37 倍加速。这种”冰火两重天”的特征需要在实际部署中认真评估。如果你的应用主要是开放域闲聊,DFlash 可能不是最佳选择;如果是结构化 JSON 输出或代码补全,DFlash 的收益是压倒性的。

NVIDIA Blackwell 上的表现#

DFlash 在 Blackwell GPU 上的优势尤为突出,因为 Blackwell 的设计恰好契合了 DFlash 将串行工作转为并行工作的思想。

在 DGX B300(8× B300 GPU)上使用 TensorRT-LLM + DFlash 部署 gpt-oss-120b 模型:

  • 无投机基准:~40 tok/s/用户
  • DFlash(k=16):500-600 tok/s/用户,约 15 倍吞吐量提升
  • 相比 EAGLE-3:1.5 倍额外吞吐量提升

这个 15 倍的数字需要理解其条件:它测量的是高并发下的吞吐量增益,不是单用户的延迟改善。当数百个用户同时请求时,DFlash 通过将解码从内存带宽瓶颈转变为计算瓶颈,充分利用了 Blackwell 的 15 PFLOPS NVFP4 算力。单用户 batch size 为 1 时,加速比在 2-4 倍之间。

DFlash 在 Blackwell 上的吞吐量-交互延迟 Pareto 曲线:在保持相近交互延迟的前提下,gpt-oss-120b 吞吐量最高提升约 15 倍
DFlash 在 Blackwell 上的吞吐量-交互延迟 Pareto 曲线:在保持相近交互延迟的前提下,gpt-oss-120b 吞吐量最高提升约 15 倍

图源:NVIDIA Technical Blog《Boost Inference Performance up to 15x on NVIDIA Blackwell Using DFlash Speculative Decoding》

在 vLLM 部署中(同等工作负载、相同并发数):

  • Coding 数据集:DFlash 2.6× vs EAGLE-3 1.8×
  • RAG 数据集:DFlash 2.3× vs EAGLE-3 1.7×
  • Reasoning 数据集:DFlash 2.3× vs EAGLE-3 1.8×

在 SGLang 部署中:DFlash 实现了约 5.1 倍的吞吐量提升。

消融实验#

DFlash 论文中的关键消融实验揭示了几个设计选择的重要性:

KV 注入 vs 输入拼接

取 5 层 DFlash 草稿模型,在 GSM8K 上对比两种特征注入方式:

注入方式接受长度 τ
输入层拼接(EAGLE-3 方式)3.5
逐层 KV 注入(DFlash 方式)4.2

KV 注入将接受长度提升了 20%。这种优势随草稿模型加深而放大:层数越多,输入层信号被稀释的效应越明显,逐层注入的优势越大。

草稿模型深度

在 Qwen3-8B 上,保持其他配置不变,改变草稿模型层数:

层数接受长度草稿耗时 (ms)端到端加速
23.10.81.9×
54.21.52.7×
84.32.62.1×

8 层草稿的接受长度几乎不增长(4.2 → 4.3),但草稿耗时近乎翻倍(1.5 → 2.6 ms),导致端到端加速反而下降。这表明草稿模型的深度存在一个”饱和点”,超过之后边际收益为负。

块大小

块大小 k接受长度端到端加速
42.81.8×
83.52.3×
164.22.7×
324.82.5×

k=32 时加速开始下降,因为虽然接受长度仍在增长(4.8),但验证阶段需要处理更长序列,验证耗时的增加开始超过额外接受 token 的收益。

集成与部署生态#

DFlash 论文发表于 2026 年 2 月,被 ICML 2026 接收。到 2026 年 6 月,NVIDIA 正式宣布将 DFlash 集成到其推理生态中,并开源了 20 个预训练草稿模型 checkpoint 在 Hugging Face 上。

推理框架集成#

DFlash 目前支持的推理框架:

框架集成方式状态
vLLMspeculators 插件,--speculative-model 指定 DFlash 草稿模型生产可用
SGLangSpecForge 子项目,原生支持 DFlash 算法生产可用
TensorRT-LLMNVIDIA 原生集成,Blackwell 优化生产可用
llama.cpp--spec-type draft-dflash实验性

vLLM 中的使用方式(来自 vLLM Speculators 文档):

Terminal window
vllm serve Qwen/Qwen3-8B \
--speculative-model z-lab/Qwen3-8B-DFlash \
--speculative-config '{
"method": "dflash",
"block_size": 16,
"target_layer_ids": [1, 8, 14, 20, 27]
}'

SGLang 中的使用方式:

Terminal window
python -m sglang.launch_server \
--model Qwen/Qwen3-8B \
--speculative-algorithm dflash \
--speculative-draft-model z-lab/Qwen3-8B-DFlash \
--speculative-block-size 16

支持的模型家族#

截至 2026 年 8 月,Hugging Face 上已有覆盖以下模型族的 DFlash 草稿模型:

  • Qwen3.x / Qwen3.5 / Qwen3.6 系列(8B、14B、32B、35B-A3B、Coder 30B-A3B 等)
  • Gemma 4 系列(26B-A4B 等)
  • Llama 3.1 系列(8B 等)
  • gpt-oss 系列(120B 等)
  • Kimi K2.6 / K2.7 系列
  • Alpamayo-1.5(NVIDIA,自动驾驶 VLA)

训练自己的 DFlash 草稿模型#

NVIDIA 提供了 TensorRT-Model-Optimizermodelopt>=0.43.0)中的 DFlash 训练工具链:

from modelopt.speculative import DFlashTrainer
trainer = DFlashTrainer(
target_model_path="Qwen/Qwen3-8B",
block_size=16,
num_draft_layers=5,
target_layer_ids=[1, 8, 14, 20, 27],
gamma=3.0, # 衰减因子
max_anchors=512, # 每样本最大锚点数
)
trainer.train(
dataset="your-dataset",
output_path="./my-dflash-drafter",
learning_rate=6e-4,
max_steps=10000,
)

训练硬件需求相对亲民:Pilot 品质的草稿模型(5K 样本)可以在单张 RTX PRO 6000 Blackwell(96GB)上完成;生产品质(2M+ 样本)需要多 GPU 训练。

草稿模型的 top-1 匹配率随训练数据量的增长情况:

训练数据量预期 top-1 匹配率
5K(pilot)~25%
50K~55%
500K接近收敛
2M+(生产级)收敛到最优

局限与未解决的问题#

工作负载敏感性强#

DFlash 在不同类型的文本上表现差异极大。在散文和叙事性文本上,加速比接近 1×(几乎无加速甚至轻微退化),因为这类文本的 token 间依赖关系复杂,块扩散无法有效捕获。在高度结构化的输出(JSON、代码、数学推导)上,加速比可达 4-6×。

这意味着在实际部署中需要做动态策略选择:根据请求类型(或观察到的接受率)在 DFlash、EAGLE-3 和无投机解码之间切换。NVIDIA 的 ModeSwitch-LLM 和 SGLang 的请求级路由已经在探索这个方向。

草稿模型需要逐模型定制#

每个目标模型都需要训练一个对应的 DFlash 草稿模型。草稿模型的隐藏维度、注意力头配置、词表都必须与目标模型对齐。这意味着:

  • 不能像 EAGLE-3 那样部分复用草稿架构
  • 模型生态中每增加一个新目标模型,都需要额外的草稿模型训练工作
  • 微调过的目标模型需要重新训练或至少重新校准草稿模型

高并发场景下的接受率下降#

DFlash 论文中的多数加速数字来自低并发(batch size ≤ 8)或单请求场景。在高并发(batch size ≥ 32)条件下,由于目标模型的 KV 缓存压力增大、批处理效率下降,实际接受的草稿 token 数可能减少。

社区报告显示,在 32 并发时,Qwen3.6-35B-A3B 的 DFlash 加速比从 4.3× 下降到约 2.9×——仍然显著,但下降幅度值得注意。

块扩散的双向注意力问题#

DFlash 的块内双向注意力使得每个位置的预测互相影响。这种”全局一致性”在某些场景下是优势(如 JSON 结构生成),但在需要严格因果关系的场景下会导致系统性错误(如数学证明中的逐步推导)。

这正是后续工作 JetSpec(2026 年 6 月,arXiv:2606.18394)要解决的问题。JetSpec 在 DFlash 的基础上做了两个关键改动:

  1. 块内注意力改为因果结构:位置 i 只能看到位置 0 到 i,保证每个位置的预测显式以前面所有位置的预测为条件。
  2. 前向 KL 蒸馏损失:用温度缩放的前向 KL 散度替代硬标签交叉熵,让草稿模型学习目标模型的完整软分布,而非仅仅 top-1 token。

JetSpec 将加速比继续推高至最高 9.64 倍。

视觉语言模型支持有限#

当前的 DFlash 实现在视觉语言模型上支持有限。当输入包含视觉信息时,DFlash 的草稿过程被抑制(退化为无投机解码),因为草稿模型无法有效利用视觉特征。这是未来工作的一个方向。

小结#

DFlash 代表了投机解码的一次范式转移:用块扩散的并行生成取代自回归的逐 token 生成

这个思路的关键洞察是:在投机解码中,草稿模型的单 token 准确率不是唯一重要的指标。推理加速由”接受长度 / 草稿耗时”决定,而 DFlash 通过将草稿耗时压到接近常数,使得在单 token 准确率显著低于自回归方法的情况下,仍然实现了更高的端到端加速比。

KV 注入是让这个设计可行的关键技术。通过将目标模型的中间层隐藏状态注入草稿模型的每一个 transformer 层,DFlash 在缺乏显式因果条件的情况下仍能维持可接受的预测精度。

这篇工作的工程影响已经显现:NVIDIA 的全面集成、vLLM 和 SGLang 的原生支持、20+ 个预训练草稿模型的发布,意味着 DFlash 正在从一篇论文变成生产推理栈的标准组件。

对于关注推理加速的从业者,有几个值得跟进的方向:

  • JetSpec 的因果树草稿(arXiv:2606.18394):将加速比继续推高至接近 10×。
  • D-PACE 的动态难度感知训练:进一步优化草稿模型在”瓶颈 token”上的精度。
  • 请求级自适应路由:根据负载类型在 DFlash/EAGLE-3/无投机之间动态切换。

参考资料#

  1. DFlash: Block Diffusion for Flash Speculative Decoding — Jian Chen, Yesheng Liang, Zhijian Liu, ICML 2026
  2. DFlash GitHub 仓库 — z-lab
  3. Boost Inference Performance up to 15x on NVIDIA Blackwell Using DFlash Speculative Decoding — NVIDIA Technical Blog
  4. vLLM Speculators: DFlash Algorithm — vLLM Project
  5. SGLang SpecForge: DFlash Training Pipeline — SGLang Project
  6. JetSpec: Breaking the Scaling Ceiling of Speculative Decoding with Parallel Tree Drafting — Hao AI Lab, 2026
  7. EAGLE-3: Scaling up Inference Acceleration of Large Language Models via Training-Time Test — Yuhui Li et al., NeurIPS 2025,对比基线方法
  8. DSpark:半自回归生成与置信度调度的投机解码 — 本系列前作
  9. NVIDIA TensorRT-Model-Optimizer DFlash Documentation — NVIDIA NeMo AutoModel
  10. DFlash Hugging Face Models — z-lab on Hugging Face

文章分享

如果这篇文章对你有帮助,欢迎分享给更多人!

DFlash 块扩散解码:以并行扩散替代自回归草稿,实现无损 6 倍推理加速
https://pinghaoyang.com.cn/aigc/posts/dflash/
作者
平昊阳
发布于
2026-08-12
许可协议
CC BY-NC-SA 4.0

评论区

Profile Image of the Author
平昊阳
乘长风,破巨浪, 展鸿图于未央!
--
总访问量
--
访客数
公告
欢迎来到我的个人博客!欢迎关注交流吖!
更多相关公告,见
社交-留言」。
音乐
封面

音乐

暂未播放

0:000:00
暂无歌词
站点统计
文章
66
分类
16
标签
93
总字数
477,284
运行时长
0
最后活动
0 天前

文章目录