02_DeepSpec-DSpark-核心原理_推测解码与draft模型
02 · 核心原理:推测解码与 draft 模型
本篇在总分总中承上启下:上一篇 00 总览 给出项目地图,本篇从"为什么需要 draft 模型"这一根本问题出发,讲清楚推测解码的数学保证、三种 drafter 范式的优劣、DSpark 半自回归设计的动机。后续 03 DSpark 建模 与 04 Eagle3 建模 在此基础上展开实现细节。
总览段(总)
推测解码(Speculative Decoding)的本质是用"猜 + 验"替代"逐字生成":让一个轻量 draft 模型快速预测接下来 K 个 token,让大 target 模型一次性批量验证这 K 个候选。验证用拒绝采样(rejection sampling)实现,数学上保证输出分布与原 target 完全一致——即无损加速。
DeepSpec 实现的三种 drafter 范式:
| 范式 | 算法 | draft 耗时 | suffix decay | 代表代码 |
|---|---|---|---|---|
| 自回归 | Eagle3 | O ( K ) O(K) O(K) | 弱 | [eagle3/loss.py](file:///workspace/deepspec/modeling/eagle3/loss.py) |
| 并行 | DFlash | O ( 1 ) O(1) O(1) | 强 | [dspark/config](file:///workspace/config/dflash/dflash_qwen3_4b.py) |
| 半自回归 | DSpark | O ( 1 ) + O ( K ) 轻 O(1) + O(K)_{\text{轻}} O(1)+O(K)轻 | 弱 | [dspark/modeling.py](file:///workspace/deepspec/modeling/dspark/qwen3/modeling.py) |
DSpark 的核心洞察:并行主干拿到高吞吐,串行 Markov head 解决 suffix decay,confidence head 让验证变"聪明"。
图说明: 这是推测解码的最小循环单元。target 先生成 1 个 anchor token;draft 用它生成 K 个候选;target 一次 forward 验证 K+1 个 token(K 个 draft + 1 个 bonus);拒绝采样产出"最长正确前缀 + 1 个修正/bonus token",作为下一轮 anchor。每轮净产出 ≥ 1 \geq 1 ≥1 个 token,最多 K + 1 K+1 K+1 个。
分述段(分)
2.1 为什么自回归慢、并行快
大模型推理的瓶颈不是 FLOPs 而是显存带宽:每次 forward 都要把整个模型权重从 HBM 搬到 SRAM。这意味着——让 GPU 同时验证 10 个 token,只比验证 1 个 token 慢一点点(权重只搬一次)。
图说明: 自回归逐 token 生成时每步都要重新加载权重,所以 draft 耗时随 K 线性增长;并行把 K 个 token 打包成一个 batch,权重只搬一次,耗时几乎不随 K 变化。这是 DSpark 选择"并行 backbone + 轻量串行修正"的根本动因——保留并行吞吐,但用极轻的串行 head 解决下文将讲的 suffix decay。
2.2 拒绝采样的无损保证
核心算法在 [base_evaluator.py:186-304](file:///workspace/deepspec/eval/base_evaluator.py#L186-304) 的 verify_draft_tokens。对每个 draft 候选
x
k
x_k
xk:
accept_prob k = min ( 1 , p k t ( x k ) p k d ( x k ) ) \text{accept\_prob}_k = \min\left(1, \frac{p^t_k(x_k)}{p^d_k(x_k)}\right) accept_probk=min(1,pkd(xk)pkt(xk))
- p k t p^t_k pkt 是 target 在该位置的分布, p k d p^d_k pkd 是 draft 的分布
- 采样
rand < accept_prob决定接受/拒绝 - 第一个拒绝位置之后所有 token 归零(
cumprod实现) - 拒绝时从残差 max ( 0 , p t − p d ) \max(0, p^t - p^d) max(0,pt−pd) 归一化后采样修正 token
- 全接受则从 target 最后位置采一个 bonus token
为什么无损:这是经典拒绝采样,接受概率恰好抵消 draft 与 target 分布的差异,期望输出分布严格等于 target 分布。论文 Section 3.2.2 强调的 non-anticipating 性质——截断决策不能依赖未来 token——正是为保证这一性质而设。
2.3 三种 drafter 范式对比
图说明: Eagle3 用 1 层 draft + KV cache 串行生成 K 步,draft 耗时 O ( K ) O(K) O(K);DSpark/DFlash 用 5 层 draft + mask-token block 单次 forward 出 K 个 logit,draft 耗时 O ( 1 ) O(1) O(1)。DSpark 在 DFlash 的并行 backbone 之上加了一个极轻的串行 Markov head(参数量 O ( r V ) O(rV) O(rV), r = 256 r=256 r=256)和 confidence head,既保留并行吞吐又解决 suffix decay。
2.4 suffix decay 与 capacity advantage
论文 Figure 2 揭示了一个关键现象(Section 4.3.1):
- 位置 1:并行 drafter(DFlash)显著高于自回归(Eagle3),因为并行可以用更深网络(5 层 vs 1 层),capacity advantage。例:Qwen3-4B 上 Math 任务 DFlash 0.88 vs Eagle3 0.81,Chat 任务 0.72 vs 0.53。
- 位置 2–7:并行 drafter 快速衰减(“multi-modal collision”——并行预测独立 marginalize 所有可能前驱,无法条件化于已采样 token),自回归 drafter 反而上升。
图说明: DSpark 的设计目标就是把两种范式的优势叠加:位置 1 用并行深网络拿到高 capacity,位置 2–7 用 Markov head 注入前缀依赖避免 suffix decay。论文实测 DSpark 在 Math 上从 0.93 起步且整个 block 稳定,比 DFlash 高出约 5–15 个百分点。
2.5 τ 与 acceptance rate 公式
acceptance rate(论文 Eq. 8):单个位置的接受概率等于 1 减去 draft 与 target 分布的 total variation 距离的一半:
c k ∗ = 1 − 1 2 ∥ p k d − p k t ∥ 1 c^*_k = 1 - \frac{1}{2}\|p^d_k - p^t_k\|_1 ck∗=1−21∥pkd−pkt∥1
代码实现见 [dspark/loss.py:60-70](file:///workspace/deepspec/modeling/dspark/loss.py#L60-70) 的 _compute_accept_rate_3d。这个公式是 DSpark confidence head 的训练目标——直接用解析的接受率作为 soft label,不需要实际跑推测解码就能监督。
τ(accepted length):每轮验证平均被接受的 token 数(含 bonus),论文 Table 1 的核心指标。其期望值近似为:
τ ≈ 1 + ∑ k = 1 K ∏ i ≤ k c i \tau \approx 1 + \sum_{k=1}^{K} \prod_{i \leq k} c_i τ≈1+k=1∑Ki≤k∏ci
代码中 tau_prob_per_block = expected_draft_accepted + 1([loss.py:40-57](file:///workspace/deepspec/modeling/dspark/loss.py#L40-57)),加 1 是因为 bonus token 总会被接受。
2.6 lossless 性质与 non-anticipating 约束
论文 Section 3.2.2 与 Appendix A 强调:为了不破坏无损性,调度器决策不能依赖未来 token。具体到 Algorithm 1:
- 按 a r , j = ∏ i ≤ j c r , i a_{r,j} = \prod_{i \leq j} c_{r,i} ar,j=∏i≤jcr,i 全局排序候选
- 贪心加入 token,更新 Θ = τ ⋅ SPS ( B ) \Theta = \tau \cdot \text{SPS}(B) Θ=τ⋅SPS(B)
- 一旦 Θ \Theta Θ 下降就 break(早停保证 non-anticipating)
如果做 retrospective 全局搜索(不早停),会泄露
x
r
,
k
x_{r,k}
xr,k 的采样结果到 step
k
k
k 的决策中,引入 selection bias。本仓库开源版只提供单请求的 confidence_threshold 截断近似([draft_ops.py:82-93](file:///workspace/deepspec/eval/dspark/draft_ops.py#L82-93)),生产版 Algorithm 1 在 HAI-LLM 内部实现。
2.7 三种 loss 的角色
DSpark 的训练目标(论文 Eq. 12):
L = α c e L c e + α t v L t v + α c o n f L c o n f , α c e = 0.1 , α t v = 0.9 , α c o n f = 1.0 L = \alpha_{ce} L_{ce} + \alpha_{tv} L_{tv} + \alpha_{conf} L_{conf}, \quad \alpha_{ce}=0.1, \alpha_{tv}=0.9, \alpha_{conf}=1.0 L=αceLce+αtvLtv+αconfLconf,αce=0.1,αtv=0.9,αconf=1.0
图说明: Lce 是标准交叉熵,Ltv 直接惩罚 acceptance rate 的对偶(total variation),Lconf 监督 confidence head。 α t v = 0.9 \alpha_{tv}=0.9 αtv=0.9 远大于 α c e = 0.1 \alpha_{ce}=0.1 αce=0.1,说明 DSpark 把"对齐 target 分布"放在比"预测正确 token"更重的位置——因为对齐分布直接最大化期望接受率。位置权重 w k = exp ( − ( k − 1 ) / γ ) w_k = \exp(-(k-1)/\gamma) wk=exp(−(k−1)/γ) 让靠前位置权重更大([loss.py:25-37](file:///workspace/deepspec/modeling/dspark/loss.py#L25-37)),因为前缀 token 决定整 block 是否被接受。
小结段(总)
本篇建立了三个直觉:
- 并行验证便宜、自回归贵:因为权重搬运是瓶颈,并行把 K 个 token 打包成一次 forward。
- 并行 drafter 有 suffix decay:并行预测无法条件化已采样 token,position 2–7 接受率快速衰减;自回归 drafter 反而稳定但 position 1 capacity 受限。
- DSpark = 并行主干 + 串行 Markov head + confidence head:用并行拿吞吐、用串行解决 decay、用 confidence 智能截断验证。所有 loss 项都与 acceptance rate 直接相关(CE/TV/BCE),训练目标与评测目标对齐。
这套原理在 03 DSpark 建模 中落地为 13 步 forward 流程;在 07 评测系统 中落地为 verify_draft_tokens 循环;在 08 实验复现 中复现为 Table 1 的 9×4 矩阵。
延伸阅读:进入 03 DSpark 建模 看半自回归具体怎么实现,或读 04 Eagle3 建模 对照自回归范式。论文原文 Section 2(Preliminaries)与 Section 3.1(Semi-Autoregressive Generation)在 [DSpark_paper.pdf](file:///workspace/DSpark_paper.pdf)。
更多推荐
所有评论(0)