一句话主线:DFlash 2 革的是”草稿怎么出”(事后选路 + 物理补流),DSpark 革的是”验证多少”(置信度调度);起草器在框架里是互斥配置项,调度器才是可正交组合的部分——而 DSpark 调度器依赖它自己的置信度头信号,要在 DFlash 起草器上复用还得写一层”置信度代理”+ 跑基准,这正是还没被打包成命名组合的原因。
本文接 ep3(DFlash)/ ep4(DSpark)/ ep5(同台对比)/ ep7(MTP 与置信度头)。先快速回顾 DFlash 2 改了什么,再回答那个元问题。
1. DFlash 2 改了什么(一句话回顾)
DFlash 1 的两个已证短板:块内不连贯(各位置独立 Top-1,出现”我 我 想”)、块尾衰减(浅层块内注意力只剩 8%)。DFlash 2 用两针补丁补上:
| 补丁 | 做什么 | 代价 |
|---|---|---|
| 路径选择器(2M 参数) | LM Head 本来就出全词表 → 免费保留 Top-16 候选;轻量打分函数并行算”相邻亲密度”;贪心回溯挑 1 条连贯路径(回溯只是查表,0.6% 延迟);带拒绝采样,数学无损 | +2M |
| 局部卷积(16.5M / +3%) | 每个 Attention/FFN 子层前后插两抽头动态深度卷积(只看当前位+左一位),强制信息左→右流动;块内注意力 9.4%→0.5%,等效加深到 15 层 | +16.5M |
实测(MindStudio,单卡 H200,Qwen3.8-27B):acceptance length 在 GSM8K 上 5.46,高于内置 MTP 头(5.02)与社区 DSpark 起草器(4.36);并发 1 时 3.1–3.4×,并发 32 时仍 >1.0×,且全并发全任务都压过 MTP 和 DSpark 起草器。
2. 元问题:为什么不直接组合?
直觉很自然——“DFlash 2 的起草器 + DSpark 式的置信度调度验证,一个管草稿、一个管验证,层面不同,为什么不叠?“拆成三层看就清楚了。
2.1 起草器在框架里是”互斥配置项”,不是可叠加模块
推测解码一次请求只跑一个起草器。框架用单一 method 字段选定它:
- SGLang:
--speculative-algorithm DFLASH或DSPARK(互斥) - vLLM:
speculative-config '{ "method": "dflash" }'或"dspark"(互斥)
DFlash 是块扩散(一次前向并行出整块),DSpark 是半自回归 + 马尔可夫头(块级并行、块内串行)。两者是不同的起草器 checkpoint 和前向逻辑,你没法在同一个前向里既”块扩散”又”半自回归”。所以”组合起草器”在物理上不成立——能选的要么是 DFlash 2 起草器,要么是 DSpark 起草器。
2.2 真正可组合的是”验证/调度策略”,而它已经部分统一了
DSpark 的”置信度调度器”(高置信多验证、低置信少验证)作用在 verify 阶段,与起草器解耦。这部分本质上是模型无关的调度策略,理论上可以套在任何起草器上。事实是:
- vLLM 已在做
#48692自适应推测解码(adaptive SD); - SGLang
#30261已合入完整置信度调度 + ragged verify + CUDA graph; - aihot 记录 vLLM/SGLang 的”自适应 token 预算”已把 DSpark TTFT 拉高 55–65%。
也就是说,“DFlash 2 起草器 + 自适应验证预算”这个组合,在框架里其实已经是最接近的形态——只是它通常不叫”DFlash+DSpark 组合”,而叫”DFlash + adaptive K”。
2.3 那为什么没人把 DSpark 的调度器直接挂在 DFlash 上?卡在”置信度信号源”
DSpark 调度器的输入是它自己在起草时由 Markov / Confidence Head 产出的逐 token 置信度。换到 DFlash 2 起草器,这个信号源变了:
- DFlash 2 的”路径选择器”产出的是连贯性/接受得分,不是逐 token 的接受概率;
- 目标模型验证时才能拿到真正的逐 token 接受概率。
要把 DSpark 式调度原样搬到 DFlash 起草器上,得先写一层**“置信度代理”(把路径选择器得分 / 目标模型接受概率映射成调度器期望的输入),再发表基准证明组合确实更优**。这层胶水 + 评测正是”还没被打包成命名组合”的关键——它不是不可能,而是缺少一个贡献者把它 PR 进来并 benchmark。
2.4 还有两个现实约束
- 成熟度:截至最新,DFlash 2 的集成还没进稳定版——vLLM 是未合并 PR(
#52816,需装分支),SGLang 需从源码构建。DSpark 虽已合入但在”积极扩展”期。两个都未稳,先组合低优先。 - 高并发会反噬:并发 32 时 DSpark 的某些任务已 <1.0×(比纯自回归还慢),DFlash 2 仍 >1.0×。自适应调度若在重负载下调错 K,会直接掉速。框架默认用最稳的固定 K 避免回归,自适应是 opt-in。
3. 结论:当前框架里”最优组合”长什么样
| 组合 | 是否可行 | 现状 |
|---|---|---|
| DFlash 2 起草器 + 固定 K 验证 | ✅ 已落地 | SGLang(源码)/ vLLM(PR #52816) |
| DSpark 起草器 + 置信度调度 | ✅ 已落地 | vLLM #46995 / SGLang #30261 |
| DFlash 2 起草器 + 自适应验证预算 | ✅ 实质可行 | vLLM #48692 / SGLang 自适应预算,只是不叫”组合” |
| DFlash 2 起草器 + DSpark 原版置信度调度(零改动) | ❌ 不可行 | 置信度信号源不匹配 |
| DFlash 2+ DSpark 双起草器并行 | ❌ 不可行 | 起草器互斥,单请求只能一个 |
所以你那句”不是替代,是叠加”是对的,但要加一句精确注脚:叠的是调度层,不是起草器层;而把 DSpark 的调度”原样”叠到 DFlash 上,缺的是一层置信度代理 + 一份基准——这层活儿今天没人替你做完,所以框架里你看到的是”DFlash 2 + 自适应 K”,而不是”DFlash 2 × DSpark”的命名组合。对 OpenInfer 而言,最务实的落脚点就是前者:DFlash 2 起草器 + 借 vLLM/SGLang 已有的自适应验证预算,把”验证多少”交给框架现成的置信度调度,而非去改 DSpark 的 Markov 头。
4. 和前文的衔接
- ep5 说二者”正交可叠加”——本文把”叠加”精确成”调度层叠加、起草器层互斥”。
- ep7 讲 DSpark 的 Confidence Head 与负载感知调度——本文点明这个调度依赖 Confidence Head 信号,所以不能直接平移到 DFlash 起草器。
- 想继续深挖:可把”路径选择器打分→回溯”或”两抽头卷积数据流”单独画成算子级图,或写 ep9 专门讲 vLLM #48692 / SGLang #30261 的自适应预算实现。
💬 留言
NaphJohn/LLM-blog尚未启用 Discussions:请在 GitHub 仓库 Settings → General → Features 勾选 Discussions 后刷新本页,评论区即自动显示。