DSpark:半自回归生成与置信度调度的投机解码

7139 字
36 分钟
DSpark:半自回归生成与置信度调度的投机解码

AI 生成内容声明

背景:投机解码的基本逻辑#

大语言模型的推理有一个根本矛盾:自回归解码本质上是串行的——每生成一个 token,都必须等上一个 token 计算完才能继续。这个串行依赖导致 GPU 的计算能力在 decode 阶段严重”吃不饱”:每个 step 只做一次矩阵-向量乘法(GEMV),计算密度极低,大量 SM 处于空闲状态。

投机解码(Speculative Decoding)是解决这个问题的主流方案之一。核心思路很简单:用一个轻量级的”草稿模型”(draft model)快速预测接下来若干个 token,然后让目标模型一次性验证这一整段草稿。由于目标模型可以并行处理多个 token(一次矩阵-矩阵乘法 GEMM),虽然总计算量多了,但耗时大幅下降。

投机解码的两阶段流程:草稿模型生成候选,目标模型并行验证
投机解码的两阶段流程:草稿模型生成候选,目标模型并行验证

投机解码把生成拆成两阶段:轻量草稿模型(assistant)先自回归生成一串候选 token,目标模型再一次性并行验证,一次前向即可产出多个 token。(来源:HuggingFace Blog「Faster Assisted Generation with Dynamic Speculation」,原图出自 Leviathan et al., 2022)

投机解码的加速比取决于两个因素:

  • 草稿模型的生成速度:草稿模型必须比目标模型快得多,否则拖慢整个流程
  • 草稿的接受率:目标模型验证时,草稿 token 被接受的比例越高,有效加速越大

这两个因素之间存在根本性的 trade-off:并行生成草稿(一个 forward pass 预测多个 token)速度快但接受率低,逐 token 自回归生成草稿接受率高但速度慢。

问题定义:并行 vs 自回归的两难#

两类草稿模型的困境#

在 DSpark 之前,投机解码的草稿模型大致分为两个流派。

自回归草稿模型以 Eagle3 为代表。Eagle3 使用一个轻量级 Transformer decoder,逐 token 自回归地生成草稿。它的优势是草稿质量高——每个 token 的预测都基于前面所有已生成的草稿 token,token 之间的依赖关系保持完好。代价是草稿生成本身也是串行的:要生成 7 个 token 就需要 7 次 forward pass,尽管每次 pass 比目标模型快得多,但 7 次的累积延迟仍然可观。

并行草稿模型以 DeepSeek 此前提出的 DFlash 为代表。DFlash 的核心设计是”非因果查询块”(non-causal query block):通过将 query 的因果 mask 去掉,让草稿模型在一个 forward pass 中同时预测 7 个位置的 token。这几乎消除了草稿生成的串行延迟——生成 7 个候选 token 的时间和生成 1 个几乎一样。

但并行草稿有一个致命弱点:接受率衰减(acceptance decay)。因为所有 token 是同时预测的,位置 k 的 token 预测时看不到位置 k-1 的实际预测结果,缺乏 token 间的条件依赖。这导致越靠后的位置,预测质量越差。在长草稿块中,后面几个 token 的接受率可能低到几乎没有加速贡献,却仍然消耗了目标模型的验证算力。

逐位置条件接受率:Eagle3 与 DFlash 的对比
逐位置条件接受率:Eagle3 与 DFlash 的对比

逐位置条件接受率:Eagle3 自回归草稿的接受率稳定甚至上升,而并行草稿 DFlash 在靠后位置出现明显的后缀衰减——这正是 DSpark 引入串行头修正的核心动机。(来源:arXiv:2607.05147 Figure 2)

两种方案的对比可以用一个表概括:

特性Eagle3(自回归)DFlash(并行)
草稿生成延迟高(7 次 forward)低(1 次 forward)
接受率高(token 间有条件依赖)低(后期衰减严重)
计算开销集中在草稿模型集中在目标模型验证

DSpark 要回答的问题是:能不能同时得到并行草稿的速度和自回归草稿的质量?

形式化定义#

将投机解码的过程形式化。设目标模型为 MtM_t,草稿模型为 MdM_d,草稿块长度为 γ\gamma(DSpark 中 γ=7\gamma = 7)。

对于给定的前缀 x0x_0(已确定的前文),草稿模型生成 γ\gamma 个候选 token:

x~1,x~2,,x~γMd(x0)\tilde{x}_1, \tilde{x}_2, \ldots, \tilde{x}_{\gamma} \sim M_d(\cdot \mid x_0)

目标模型以 x0x_0 为前缀,一次性对 γ\gamma 个位置的前向计算得到每个位置的目标分布 pktp_k^t。然后按位置逐一验证:

P(接受 x~k)=min(1,pkt(x~k)pkd(x~k))P(\text{接受 } \tilde{x}_k) = \min\left(1, \frac{p_k^t(\tilde{x}_k)}{p_k^d(\tilde{x}_k)}\right)

第一个被拒绝的位置 kk 之后的所有 token 都被丢弃,目标模型从该位置采样一个”补偿 token”。整个过程保证输出分布与目标模型完全一致,不损失任何质量。

加速比的上限近似为:

加速比γ接受率1+TdTt+TvTt\text{加速比} \approx \frac{\gamma \cdot \text{接受率}}{1 + \frac{T_d}{T_t} + \frac{T_v}{T_t}}

其中 TdT_d 是草稿生成时间,TvT_v 是目标模型验证 γ\gamma 个 token 的时间,TtT_t 是目标模型生成 1 个 token 的时间。要提高加速比,要么提高接受率,要么降低 TdT_d,要么提高 γ\gamma(但 γ\gamma 增大通常导致接受率下降)。

核心思想:把自回归塞回并行草稿#

DSpark 的核心洞察是一个”为什么不能两全”的设计:

用一个并行主干(backbone)做快速草稿生成,再用一个极轻量的串行模块(sequential head)在草稿内部注入 token 间依赖。 并行主干负责速度——一次 forward pass 产出所有位置的候选 token;串行模块负责质量——它在并行主干的输出之上,逐位置修正预测,把”前面预测了什么”的信息编码进去。

串行模块的计算量极小(相比并行主干可以忽略),所以整体草稿生成延迟仍然接近并行方案,但草稿质量回到了自回归方案的水平。

这个设计的直观类比:并行主干像是同时写出 7 个句子的”初稿”,串行模块像是逐句校对一遍,根据前一句的实际内容调整后一句的措辞。校对的工作量远小于重写,但能大幅提升质量。

半自回归生成:并行主干 + 串行头#

整体架构#

DSpark 的草稿模型由两部分组成:

  1. 并行主干(Parallel Backbone):复用了 DFlash 的 decoder 结构。对于基于 Qwen3 的草稿模型,主干是一个标准的 Qwen3 decoder stack,但在计算 query-block 前向时使用非因果 mask(即每个 query 可以看到所有 key,不受位置限制)。这允许一个 forward pass 产出 γ\gamma 个位置的草稿 logits。

  2. 串行头(Sequential Head):一个极轻量的额外模块,从位置 1 开始,逐位置地根据已采样的前一个 token 修正当前位置的草稿预测。DSpark 提供了两种串行头实现:Markov Head 和 RNN Head。

DSpark 草稿模型架构:并行主干 + 串行头
DSpark 草稿模型架构:并行主干 + 串行头

DSpark 草稿模型架构:并行主干一次前向产出多个位置的候选 logits,串行头逐位置注入转移偏置修正预测。(来源:arXiv:2607.05147)

草稿分布的形式为:

pkd(vx0,x~<k)=exp(Uk(v)+Bk(x0,x~<k,v))uexp(Uk(u)+Bk(x0,x~<k,u))p_k^d(v \mid x_0, \tilde{x}_{<k}) = \frac{\exp\left(U_k(v) + B_k(x_0, \tilde{x}_{<k}, v)\right)}{\sum_u \exp\left(U_k(u) + B_k(x_0, \tilde{x}_{<k}, u)\right)}

其中:

  • Uk(v)U_k(v) 是并行主干在第 kk 个位置对 token vv 的原始 logit(不含任何 token 间依赖信息)
  • Bk()B_k(\cdot) 是串行头注入的”转移偏置”(transition bias),编码了前一个 token x~k1\tilde{x}_{k-1} 对当前位置的影响

注意 BkB_k 的输入包含了 x~k1\tilde{x}_{k-1}——这是串行头在位置 k1k-1 采样后才计算出来的。所以虽然 UkU_k 是并行算出的,但整个草稿采样流程仍然是位置间串行的:先采样 x~1\tilde{x}_1,用 x~1\tilde{x}_1B2B_2,修正 U2U_2,采样 x~2\tilde{x}_2,再算 B3B_3……以此类推。

Markov Head:一阶转移偏置#

Markov Head 是 DSpark 的默认串行头。它假设草稿 token 的依赖关系主要存在于相邻位置之间(一阶 Markov 性),用一个低秩矩阵来编码”上一个 token 是什么 → 下一个 token 的预测如何调整”。

具体实现:

  • markov_w1:将上一个 token 的 ID 映射到一个 r=256r = 256 维向量:

    hk1=W1[x~k1]R256h_{k-1} = W_1[\tilde{x}_{k-1}] \in \mathbb{R}^{256}
  • markov_w2:将这个 256 维向量映射回词表空间,得到对每个词表 token 的偏置:

    Bk(x~k1,v)=hk1TW2[v]B_k(\tilde{x}_{k-1}, v) = h_{k-1}^T \cdot W_2[v]

    这里 W2[v]W_2[v]W2R256×VW_2 \in \mathbb{R}^{256 \times |V|} 的第 vv 列。

这个设计的工程精巧之处在于:W1[x~k1]W_1[\tilde{x}_{k-1}]W2W_2 的矩阵乘实际上是两个小矩阵的乘法(隐向量 × 词表矩阵),计算量极小。以 Qwen3-8B 为例,词表大小约 152k,这一步的 FLOPs 约为 256×152k×278M256 \times 152\text{k} \times 2 \approx 78\text{M},与主干网络每个 token 数十 GFLOPs 的前向计算相比可以忽略不计。

Markov Head 还能解决并行草稿中的一个具体问题:多模态冲突(multi-modal collision)。并行草稿由于看不到前一个 token 的实际预测,容易产生不协调的组合——比如位置 1 预测了 “artificial”,位置 2 预测了 “course”,但实际上合理的组合是 “artificial intelligence” 和 “of course”。Markov Head 在位置 2 看到 x~1="artificial"\tilde{x}_1 = \text{"artificial"} 后,会大幅提高 “intelligence” 的偏置而压低 “course”,从而避免这种冲突。

RNN Head:长程依赖#

Markov Head 只考虑紧邻的前一个 token,对长程依赖的建模能力有限。DSpark 也提供了 RNN Head 作为替代方案。

RNN Head 维护一个 GRU 风格的循环状态 sks_k

sk=GRU(sk1,Emb(x~k1))s_k = \text{GRU}(s_{k-1}, \text{Emb}(\tilde{x}_{k-1}))

其中 s0s_0 从一个学习到的初始化向量开始。状态 sks_k 累积了草稿块内从位置 1 到 k1k-1 的所有已采样 token 的信息,而不仅仅是最近一个。偏置 BkB_k 同样通过将 sk1s_{k-1} 映射到词表空间得到。

RNN Head 的计算量比 Markov Head 稍大(多了 GRU 的门控计算),但仍然可以忽略不计。在 DSpark 的实验结果中,两者在大多数 benchmark 上的表现非常接近,Markov Head 因为实现更简单、延迟更低而被推荐为默认选择。

为什么不是完全的自回归草稿?#

一个自然的疑问是:既然串行头已经在做逐 token 修正了,为什么不直接用 Eagle3 那样的全自回归草稿?

核心原因是延迟结构。Eagle3 每次 forward pass 只预测 1 个 token,计算中间的大部分结果(KV cache 更新等)在每个 step 都要重新计算或加载。DSpark 的并行主干一次性完成了 γ\gamma 个位置的”骨架”计算——所有位置的 hidden state、所有位置的 query/key/value——这一步占了草稿模型计算的绝大部分。串行头只在这副骨架上做轻量的逐 token 修正,不涉及 attention 计算,不涉及 FFN,不需要加载 KV cache。

直观来说:Eagle3 是 7 次完整的前向计算,DSpark 是 1 次完整计算 + 7 次纳米级修正。即使修正的总和大于零,它也远小于 6 次完整计算的代价。

置信度调度验证#

动机:不是所有草稿 token 都值得验证#

投机解码的另一个被忽视的效率问题是验证阶段的浪费。在标准流程中,草稿模型生成 γ\gamma 个 token 后,目标模型必须全部验证。但实际上,如果草稿模型的某个位置预测质量很差(几乎肯定会被拒绝),这个 token 后面的所有 token 都会因为级联拒绝(cascading rejection)而被丢弃,验证它们的计算就是纯粹的浪费。

更具体地说,假设草稿块长度为 7,但位置 3 的 token 几乎肯定被拒。在标准流程中,目标模型仍然会对位置 4-7 做完整的 forward pass(attention + FFN),但位置 3 被拒意味着位置 4-7 全部被丢弃。位置 4-7 的计算不仅无用,而且稀释了 batch 中其他请求的有效计算——在高并发 serving 场景下,验证 batch 的容量是有限的,每多验证一个”注定被丢弃”的 token,就少了一个位置可以处理其他请求的有效 token。

DSpark 的置信度调度(confidence-scheduled verification)直接解决这个问题:预测每个位置被接受的概率,只验证那些”值得验证”的 token

置信度头:预测自己的命运#

DSpark 在草稿模型上额外增加了一个置信度头(confidence head),对每个草稿位置 kk 输出一个标量:

ck=σ(wT[hk;W1[x~k1]])c_k = \sigma\left(w^T \cdot [h_k; W_1[\tilde{x}_{k-1}]]\right)

其中:

  • hkh_k 是并行主干在第 kk 个位置的 hidden state
  • W1[x~k1]W_1[\tilde{x}_{k-1}] 复用 Markov Head 的 token embedding(避免额外参数)
  • [;][\cdot; \cdot] 表示向量拼接
  • σ\sigma 是 sigmoid 函数,将输出压缩到 (0,1)(0, 1)

ckc_k 的直觉含义是:给定前文和已预测的前一个 token,位置 kk 的草稿 token 被目标模型接受的概率。

置信度阈值扫描:阈值越高,整体接受率越高,因为置信度头有效剪掉了注定被拒的 token
置信度阈值扫描:阈值越高,整体接受率越高,因为置信度头有效剪掉了注定被拒的 token

图源:DSpark 论文 Figure 5(arXiv:2607.05147)

校准问题:原始置信度不可靠#

神经网络输出的”概率”往往是未校准的(miscalibrated)——模型说”置信度 0.9”的 token 实际上只有 0.7 的概率被接受。在高并发 serving 场景中,校准误差的影响会被放大:如果系统根据未校准的置信度决定截断草稿,可能要么截得过短(浪费加速潜力),要么截得过长(验证了大量注定被拒的 token)。

DSpark 使用序列温度缩放(Sequential Temperature Scaling, STS)来校准置信度。与标准温度缩放(对所有预测用一个全局温度)不同,STS 为草稿块内的每个位置学习一个独立的温度参数 TkT_k,且学习过程在累积前缀上进行。

具体流程:

对每个位置 k=1,2,,γk = 1, 2, \ldots, \gamma

  1. 取当前位置及之前所有位置的置信度预测,计算累积前缀生存概率

    aj(k)=i=1jci,j=1,2,,ka_j^{(k)} = \prod_{i=1}^{j} c_i, \quad j = 1, 2, \ldots, k
  2. 在验证集上,统计实际的逐位置接受率 aja_j^*(真实标签来自目标模型的验证结果)

  3. 选择温度 TkT_k,使得温度缩放后的累积概率 i=1jσ(logit(ci)/Tk)\prod_{i=1}^{j} \sigma(\text{logit}(c_i) / T_k) 的期望校准误差(Expected Calibration Error, ECE)最小

TkT_k 的选择通过一个 1D 网格搜索完成,计算量极小。STS 的关键性质是保序(order-preserving):它不改变不同位置之间置信度的相对排序,只改变绝对数值,使累积生存概率与真实接受率对齐。

序列温度缩放校准置信度
序列温度缩放校准置信度

DSpark 用序列温度缩放(STS)逐位置学习温度参数,使累积生存概率与真实接受率对齐。(来源:arXiv:2607.05147)

硬件感知前缀调度器#

有了校准后的置信度,DSpark 需要决定每个请求应该验证多少个草稿 token。这看似简单——按置信度高的就多验证——但高并发场景下有一个关键约束:验证 batch 的吞吐量取决于 batch 内请求的验证长度。如果某个请求验证了 7 个 token 但最终只接受 2 个,不仅浪费了算力,还慢了整个 batch。

DSpark 的硬件感知前缀调度器(Hardware-Aware Prefix Scheduler)将调度问题形式化为了一个优化:

Θ=τ(B)SPS(B)\Theta = \tau(B) \cdot \text{SPS}(B)

其中:

  • τ(B)\tau(B) 是 batch BB 内所有请求的期望接受 token 数之和
  • SPS(B)\text{SPS}(B) 是给定 batch BB 时的每秒序列数(sequences per second)

调度器的目标是最大化 Θ\Theta——在高效利用硬件的前提下,最大化有效吞吐。

算法流程:

  1. 对每个活跃请求 rr 和每个候选验证长度 jj,计算累积生存概率 ar,j=i=1jcr,ia_{r,j} = \prod_{i=1}^{j} c_{r,i}(经由 STS 校准)
  2. 创建所有 (r,j)(r, j) 对的候选集,按 ar,ja_{r,j} 从高到低排序
  3. 贪心地接纳候选对,动态更新每个请求的验证长度,跟踪 Θ\Theta 的变化
  4. Θ\Theta 不再提高时停止

这里的精妙之处在于异步机制。调度决策不应该阻塞 GPU 流水线——如果调度器同步等待置信度计算完成再做决策,GPU 会在等待期间空闲。DSpark 采用了一个巧妙的策略:使用前两次 inference step 的历史置信度预测来估计当前 step 的验证长度。由于服务负载的变化通常具有惯性(在上一个 step 和当前 step 之间变化不大),历史预测足够准确。置信度计算和调度决策在 GPU 计算的同时异步进行,不引入额外的气泡(bubble)。

这一设计与 vLLM/SGLang 等推理引擎中的零开销调度(Zero-Overhead Scheduling, ZOS)和连续 CUDA Graph 重放(continuous CUDA graph replay)完全兼容。

负载自适应的吞吐与验证预算:并发升高时,动态调度器自动压缩每个请求的验证长度
负载自适应的吞吐与验证预算:并发升高时,动态调度器自动压缩每个请求的验证长度

图源:DSpark 论文 Figure 8(arXiv:2607.05147)

训练策略#

损失函数设计#

DSpark 草稿模型的训练使用三部分加权的复合损失:

L=0.1Lce+0.9Ltv+1.0Lconf\mathcal{L} = 0.1 \cdot \mathcal{L}_{\text{ce}} + 0.9 \cdot \mathcal{L}_{\text{tv}} + 1.0 \cdot \mathcal{L}_{\text{conf}}

三个损失项的含义:

  • Lce\mathcal{L}_{\text{ce}}(交叉熵):标准的 next-token prediction loss。权重仅 0.1,因为投机解码中精确匹配目标分布不如获得高接受率重要。

  • Ltv\mathcal{L}_{\text{tv}}(全变差距离)pdpt1\|\|p^d - p^t\|\|_1,衡量草稿分布与目标分布的差异。这是核心训练目标——接受率直接由两个分布的距离决定,越近接受率越高。权重 0.9。

  • Lconf\mathcal{L}_{\text{conf}}(置信度损失):二元交叉熵,目标是预测每个位置是否被接受(接受为 1,拒绝为 0)。权重 1.0,用于训练置信度头。

所有损失都是按位置加权的

wk=exp(k1γ)w_k = \exp\left(-\frac{k-1}{\gamma}\right)

越靠前的位置权重越大(位置 1 权重为 1.0,位置 7 权重为 exp(6/7)0.42\exp(-6/7) \approx 0.42),因为靠前位置的接受对整体吞吐影响更大——位置 1 被拒意味着整个块被丢弃。

训练数据与流程#

DSpark 的训练数据生成遵循 DeepSpec 的标准流程:

  1. 数据准备:收集多样化的 prompt(覆盖数学、代码、对话、推理等场景),用目标模型生成回答(称为 target cache),记录目标模型在每个位置的 logits 分布
  2. 草稿模型训练:以目标模型的 logits 为 ground truth,训练草稿模型匹配目标分布。训练时使用目标模型的 hidden state 作为输入特征(而非草稿模型自身的 hidden state),这称为”特征蒸馏”——草稿模型学习的是目标模型的隐空间表示
  3. 评估:在 GSM8K、MATH500、HumanEval、MBPP、LiveCodeBench 等标准 benchmark 上评估接受率和加速比

对于 Gemma4 等非 Qwen 架构的模型,DSpark 的草稿模型使用了 Eagle3 风格的多层特征融合:从目标模型的不同中间层(如第 5、17、29、41、46 层)提取 hidden state,拼接后作为草稿模型的输入。这让草稿模型能够利用目标模型不同抽象层次的信息。

工程考量#

训练投机解码草稿模型有几个值得注意的工程点:

  • 草稿模型大小:DSpark 推荐的草稿模型大小约为目标模型的 5%-10%。以 Qwen3-8B 为例,DSpark 草稿模型约为 400M 参数。这个比例是经验上的 sweet spot——再小接受率下降明显,再大草稿生成延迟开始吞噬加速收益

草稿模型深度的影响:浅层 DSpark 就能超过更深的 DFlash,说明串行建模的参数效率
草稿模型深度的影响:浅层 DSpark 就能超过更深的 DFlash,说明串行建模的参数效率

图源:DSpark 论文 Figure 3(arXiv:2607.05147)

  • 草稿块长度 γ=7\gamma = 7:这个值是实验选择的。更短的块(如 4)无法充分利用并行验证的优势,更长的块(如 10+)的尾部接受率太低,验证开销超过收益

块长度与延迟开销的影响:DSpark 在各种块大小下都优于 DFlash,串行头引入的延迟开销可忽略
块长度与延迟开销的影响:DSpark 在各种块大小下都优于 DFlash,串行头引入的延迟开销可忽略

图源:DSpark 论文 Figure 4(arXiv:2607.05147)

  • Markov Head 的 rank r=256r = 256:在消融实验中,rank 64 的表现明显更差(转移偏置容量不足),rank 512 几乎没有额外提升(边际收益递减),256 是效率最优选择

性能与实验结果#

DeepSeek-V4 生产环境#

DSpark 最令人瞩目的结果是它在 DeepSeek-V4 真实服务流量上的表现。以下数据来自论文中的生产环境 A/B 测试:

场景加速比
DeepSeek-V4-Flash,单用户生成速度60%-85%
DeepSeek-V4-Pro,单用户生成速度57%-78%
DeepSeek-V4-Flash,高并发吞吐(120 token/s SLA)最高 661%

这里的 661% 吞吐增益需要正确理解:在严格的延迟 SLA 下(每个请求必须保证 120 token/s 以上的生成速度),系统能同时服务的请求数(即吞吐量)提升了 6.6 倍。这是因为 DSpark 不仅加速了单个请求,还通过置信度调度减少了无效验证计算,释放了更多 batch 容量给有效请求。

DeepSeek-V4 线上真实流量的加速表现
DeepSeek-V4 线上真实流量的加速表现

图源:DSpark 论文 Figure 7(arXiv:2607.05147)

离线 Benchmark:Qwen3 系列#

在离线、单请求的对比实验中,DSpark 与 Eagle3(自回归草稿)和 DFlash(并行草稿)进行了全面比较。所有实验在 NVIDIA H100 GPU 上进行。

Qwen3-8B(bf16):

方法几何平均加速比GSM8K 接受率MT-Bench 接受率
基线(无投机)1.00×
DFlash2.89×70.4%30.5%
Eagle33.12×77.2%33.1%
DSpark (Markov)3.35×78.9%35.6%
DSpark (RNN)3.31×78.5%35.2%

在 GSM8K(数学推理)上 DSpark 实现了 4.06× 的加速比和 78.9% 的接受率。

与 DFlash 和 Eagle3 的接受长度对比(Qwen3-14B):

BenchmarkDSpark vs Eagle3DSpark vs DFlash
数学(MATH500)+30.9%+16.3%
代码(HumanEval+MBPP)+26.7%+18.4%
日常对话(MT-Bench)+30.0%+18.3%

DSpark 在所有场景下同时超过了自回归草稿(Eagle3)和并行草稿(DFlash),验证了”同时获得两者优势”的设计目标。

跨模型规模的扩展性(Qwen3-4B / 8B / 14B):

DSpark 在三档模型规模上均保持了领先。值得注意的是,在较小的 Qwen3-4B 上,几何平均加速比约为 2.85×(比 8B 上的 3.35× 低),这是因为小模型的草稿生成延迟占比相对较大,削弱了投机解码的加速优势。

Gemma4-12B 跨架构验证#

DSpark 在 Google 的 Gemma4-12B 上也进行了验证,证明半自回归设计不限于特定模型架构:

  • 单流加速比:4.15×(vLLM, H100)
  • 平均接受长度:3.06-5.0 token/step
  • 草稿模型使用了 Eagle3 风格的多层特征融合

这与 DeepSeek 论文中强调的”DSpark 不是 DeepSeek 专属优化”一致——任何使用标准 Transformer decoder 架构的模型都可以训练 DSpark 草稿模型。

置信度调度的消融贡献#

论文中的消融实验量化了置信度调度在高并发场景下的独立贡献:

  • 仅半自回归生成(无置信度调度):相比 DFlash,吞吐提升约 8-12%
  • 仅置信度调度(使用 DFlash 并行草稿):吞吐提升约 15-20%
  • 完整 DSpark(半自回归 + 置信度调度):吞吐提升最高 661%(高并发)+ 单流加速 57-85%

置信度调度在高并发下的效果远大于单流场景,因为它的核心优势是减少无效验证——在单流场景下 batch 中没有其他请求来吸收释放的算力,所以收益不明显;在高并发下,释放的 batch 容量可以被其他请求立即利用。

部署与开源生态#

模型权重#

DeepSeek 在 HuggingFace 上发布了完整的 DSpark 草稿模型权重:

目标模型DSpark 草稿模型
Qwen3-4Bdeepseek-ai/dspark_qwen3_4b_block7
Qwen3-8Bdeepseek-ai/dspark_qwen3_8b_block7
Qwen3-14Bdeepseek-ai/dspark_qwen3_14b_block7
Gemma4-12Bdeepseek-ai/dspark_gemma4_12b_block7
DeepSeek-V4-Prodeepseek-ai/DeepSeek-V4-Pro-DSpark
DeepSeek-V4-Flashdeepseek-ai/DeepSeek-V4-Flash-DSpark

DeepSpec 训练框架#

与论文一同开源的 DeepSpec 是一个 MIT 许可的全栈训练工具链,支持:

  • 数据准备:自动下载 prompts,用目标模型重新生成答案,构建 target cache(对于 Qwen3-4B 默认配置约需 38TB 存储空间)
  • 草稿模型训练:支持 DSpark、DFlash、Eagle3 三种算法,可训练 Markova Head 和 RNN Head
  • 评估:在标准 benchmark 上自动评估接受率和加速比

DeepSpec 的训练 pipeline 设计为三个阶段,通过配置文件串联,适合在企业环境中针对自有模型定制草稿模型。

推理引擎集成#

DSpark 已快速集成到主流推理引擎:

  • vLLM:从 v0.8.x 开始支持 DSpark 草稿模型(见 PR #47216),包含对 Qwen3 和 Gemma4 的完整支持
  • llama.cpp:社区驱动的 DSpark 集成已在 PR 流程中(PR #25173)
  • mlx-dspark:Apple Silicon 上的社区移植(PyPI 包 mlx-dspark),在 M4 Pro 上实现 1.45-1.73× 加速

值得说明的是 Apple Silicon 上的加速比较低,不是因为 DSpark 设计不好,而是因为 Apple Silicon 缺少数据中心 GPU 的并行验证优势——在 H100 上验证 7 个 token 几乎和验证 1 个一样快(大 GEMM 掩盖了计算),但在 M4 Pro 上验证开销随 token 数线性增长。

实际部署案例#

到 2026 年 8 月,DeepSeek-V4-Flash + DSpark 已部署在中国联通北京分公司京元平台上,实测推理速度达到原 MTP(Multi-Token Prediction)方案的 2 倍,TPS 超过 60。

局限与讨论#

草稿模型训练成本#

DSpark 要求为每个目标模型单独训练一个草稿模型。虽然 DeepSpec 降低了这个门槛,但训练仍需要可观的算力(特别是 target cache 的构建,需要目标模型对大量 prompts 进行完整的前向推理)。对于参数规模特别大(> 100B)的模型,训练一个 5-10% 大小的草稿模型本身就需要数百 GPU 小时。

长上下文场景#

论文中未充分讨论 DSpark 在超长上下文(> 128K tokens)场景下的表现。投机解码的草稿模型在长上下文下可能面临额外的挑战:草稿模型的 attention 计算虽然比目标模型轻量,但在超长序列下仍可能成为瓶颈。

与 MTP 的关系#

DeepSeek-V4 之前已使用 MTP(Multi-Token Prediction)进行推理加速。DSpark 被定位为 MTP 的升级替代方案——论文中报告的生产数据是相对 MTP-1 基线(而不是无投机解码的原始模型)测得的。这意味着 60-85% 的加速是叠加在 MTP 已有的加速之上的。

但这也引出一个问题:DSpark 和 MTP 能否同时使用?论文没有明确回答。从架构角度看,MTP 使用了目标模型内部的额外预测头,DSpark 使用了外部的独立草稿模型,两者并不冲突。但叠加使用可能导致边际收益递减,且增加系统复杂度。

适用场景分析#

DSpark 在不同场景下的加速效果差异显著:

  • 数学推理(GSM8K,MATH500):效果最好,接受率可达 75-79%。数学推理的语言模式相对规范,草稿模型容易学习
  • 代码生成(HumanEval,MBPP):效果次之,接受率约 60-70%。代码的语法约束强,有利于草稿预测
  • 开放对话(MT-Bench):效果最弱,接受率仅 31-36%。对话的语用多样性使草稿预测更难

这个分布与投机解码的一般规律一致:结构化程度越高的文本,草稿模型预测越准,加速效果越好。

小结#

DSpark 在投机解码的设计空间中找到了一个优雅的平衡点。它不是推翻已有的并行草稿(DFlash)或自回归草稿(Eagle3),而是在并行草稿的基础上”打了一个轻量补丁”——一个计算量可忽略的串行头,解决了并行预测中缺乏 token 间依赖的根本问题。置信度调度则从系统层面进一步优化,减少了高并发场景下的无效验证计算。

从工程角度看,DSpark 的实用性很强:可以叠加在已有的 MTP 加速之上,不损失模型质量,训练成本可控(尤其对 10B 以下模型),已集成到主流推理引擎。它代表了投机解码从学术方法向生产基础设施过渡的一个重要节点。

DSpark 证明了一个朴素但常被忽视的原则:在推理加速领域,最好的优化往往不是重新发明轮子,而是找到现有轮子之间那个未被填充的间隙。

参考资料#

  1. DSpark: Confidence-Scheduled Speculative Decoding with Semi-Autoregressive Generation
  2. DeepSpec: A Full-Stack Codebase for Training and Evaluating Speculative Decoding Algorithms
  3. DeepSeek 开源 DSpark:推理提速最高 85%,吞吐量最高提升 661%
  4. DSpark Technical Review
  5. DeepSeek V4 Updates DSpark, Boosting Inference Speed by 80%
  6. vLLM DSpark Draft Model Support (PR #47216)
  7. DSpark HuggingFace Models (deepseek-ai)
  8. DFlash: Fast and Accurate Speculative Decoding with Parallel Token Generation
  9. Eagle3: Fast and Accurate Speculative Decoding via Retraining-Free Feature Augmentation

文章分享

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

DSpark:半自回归生成与置信度调度的投机解码
https://pinghaoyang.com.cn/aigc/posts/dspark/
作者
平昊阳
发布于
2026-08-11
许可协议
CC BY-NC-SA 4.0

评论区

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

音乐

暂未播放

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

文章目录