Appearance
DSpark 推测解码——DeepSeek 为 DeepSeek V4 Flash 发布的辅助草稿模型。它读取主模型的隐藏状态、一次提议最多 5 个未来 token,主模型验证后只提交被接受的前缀。主模型始终权威;被拒或低置信度的后缀退回普通目标解码。属于显式 opt-in 的实验性加速路径。
它解决什么
decode 是严格自回归的——每生成一个 token 都要把 81GB 权重读一遍却只算一个 token,瓶颈是内存带宽(见 Part 4)。推测解码的思路:用一个小/快模型先猜 N 个 token,主模型一次验证,猜对就"免费"获得 N 个 token。当多个提议被接受时,一次目标验证能把流推进好几个 token。
它不加速 prefill,草稿和验证也不是免费的。可预测的续写(尤其是代码)收益最大;低收益 prompt 可能不变快甚至更慢。所以 DSpark 仍显式 opt-in。
与旧 MTP 的关系
ds4 原本有一套单阶段 MTP(Multi-Token Prediction)推测路径(--mtp-draft,带置信度门 --mtp-margin)。DSpark 取代了它用于 Flash,而非叠加:
- DSpark 检查点约 5.6 GiB,是一个独立的支持 GGUF,不是独立模型
- 用
--mtp传支持文件,用--dspark选 DSpark 运行时(不加--dspark时--mtp走旧的单阶段 MTP) - 同一个支持文件可用于 Flash 的
q2-imatrix、q2-q4-imatrix、q4-imatrix;DeepSeek V4 PRO 暂不支持 - Metal 上主模型可常驻或
--ssd-streaming;支持模型仍额外占自己的权重和运行时状态
sh
./ds4 -m ds4flash.gguf \
--mtp gguf/DeepSeek-V4-Flash-DSpark-support.gguf \
--dspark --temp 0置信度门与限制
默认置信度阈值按后端区分(42033ee):Metal 0.6,CUDA / ROCm 0.7(2026-08 先从 0.9 统一下调到 0.7,再为直接提交验证器状态后的 Metal 单独调到 0.6),剪掉不太可能"值回验证成本"的后缀。--dspark-confidence 0 强制固定 5-token 块,仅用于诊断(2026-09 起置信度门为 0 时连探测回读都跳过——一个永远不可能剪枝的探测不值得跑)。--quality 和 --dspark-strict 保持纯目标解码,便于对比和正确性检查。
下调门限是因为验证不是逐个 token 判定,而是对一个 5-token 块取被接受的前缀——0.9 太严会把本可接受的后缀整段丢掉、退化成只接受 1 个 token,验证算力没充分换回 token;放宽让前缀更长,单次验证换回的 token 期望值更高。被拒后缀的草稿算力"白花",但草稿模型远比一次主模型目标解码便宜,平均接受长度上升的收益更大。
采样模式:机会式(默认)与精确随机(2026-09)
"采样解码不用 DSpark 提议"曾是硬规则,2026-09 被一对方向相反的提交改写:769a8ba 实现分布精确的随机推测解码并设为默认,8d683d6 随即反转为机会式温度采样默认、精确模式降级 opt-in。
- 机会式温度采样(默认):边界 token 按请求的温度/top-p/top-k/min-p 正常采样(精确),DFlash 的贪心后缀只要与目标模型贪心路径一致就逐个提交,首次失配处恢复普通采样。比完全不用提议快(可预测代码续写 temp 1 下 M5 Max ~+8%),且比普通采样更确定——随机性只进入边界 token。
- 精确随机推测(
--mtp-exact-sampling,引擎选项dspark_exact_sampling;曾短暂名--dspark-exact-sampling,未发布即改名):教科书 Leviathan/Chen speculative sampling,草稿是点质量 q(贪心 argmax one-hot)。sample_build_probabilities()物化用户过滤链(temperature→top-k→top-p→min-p)后的概率向量 p;speculative_point_accept()点质量下接受概率即min(1, p);拒绝时speculative_point_replacement()置零草稿 token 按残差重采样(入口ds4_session_eval_dspark_speculative_stochastic())。输出分布与直接采样目标模型完全一致;未显式设置时置信度门提至 0.8、要求草稿长 ≥ 2。tests/test_sampling.c的check_speculative_distribution()用 10 万次 Monte-Carlo 锁定频率误差 < 0.006。
ROCm gfx1151 快路径(DS4_DSPARK_SEED_BATCH,"seed-plus-five verifier")把已提交 token 拼进验证批量、部分接受时保留已验证后缀的 KV 捕获——它只活在 argmax 路径且额外要求"发出的 token 等于目标贪心 top",所以不影响精确随机模式的分布保证。
直接提交验证器状态(2026-08,0e89a0e)
DSpark 调度保持确定性(--dspark 开即按固定顺序提/验)。接受后的状态提交方式经历了一次语义转变:
- 旧路径(回滚 + 重放):验证后恢复快照,把被接受的前缀当普通单 token 解码重放一遍——保证 compressor 状态与逐 token 解码数值一致(这是修"贪心同一性"bug 时引入的),代价是接受越多、白算的重放越多。
- 新默认(直接提交):全部提议被接受(full accept)且 final logits 可用时,直接采用批量验证器产出的状态——它与逐 token 解码跑的是同一张图,只是浮点运算分组顺序不同。部分接受(partial accept)则用新增的前缀快照槽位(
DS4_SPEC_PREFIX_SLOTS)直接提交前 k 个的状态。直接提交失败仍回退回滚 + 重放,正确性不变。
代价是与逐 token 解码的字节同一性不再保证:同一条图、不同的浮点结合顺序,长贪心运行可能在某个被接受的块之后与不开 DSpark 的运行发散。这不是降精度或近似模式——需要逐字节复现时用 --dspark-strict(或 --quality、普通解码)。QA 基线因此从"输出必须 byte-identical"改为记录首个输出差异位置、接受率、直接提交数、回退数(direct_full_commits / direct_partial_commits / replay_fallbacks / net_saved / output_match)。
TP(张量并行)的 partial accept 曾长期走回滚 + 重放(worker 收不到中间前缀快照);2026-09 起验证块经 DS4_TP_FRAME_VERIFY 镜像、RDMA 窗口预投递,ds4_tp_verify_commit_mode 三态(ROLLBACK_REPLAY / COMMIT_FULL / COMMIT_PREFIX)让 TP 也能直接提交前缀——但实测 TP 下 DSpark 仍比纯 decode 慢(30-40 vs 47-48 t/s,每个验证行重流它的专家)。
Metal 侧配套(42033ee):DFlash 验证器的小批量按每 4 层 flush 一次命令缓冲增量提交,让 GPU 在 host 编码后续层时就开始算这些小批量(CPU/GPU 重叠),不改变验证器的内核与算术。
后端覆盖
DSpark 最初只在 Metal 上可用,CUDA 随后补齐;84cc882 补上 ROCm 缺的草稿/验证内核后三个 GPU 后端都已支持。新增的 rocm/ds4_rocm_attention.cuh 提供 attention_noncausal_raw_batch_heads_kernel——草稿块用的非因果注意力(每个 query 行看完整 raw-KV 环而非因果前缀);rocm/ds4_rocm_indexer.cuh 补 dspark_markov_argmax_kernel;rocm/ds4_rocm_attention_launch.cuh 把这些接进 ds4_gpu.h 的注意力 API。
c
// ds4.h — 相关引擎选项
float dspark_confidence_threshold;
bool dspark;
bool dspark_strict;
bool dspark_confidence_threshold_set;GLM 5.2 的推测解码走另一条路:MTP 块在主 GGUF 内部(不靠单独的 Flash MTP 文件),用 --glm-mtp / --glm-mtp-timing 启用实验性贪心推测。
种子批处理、六 token 验证与 EOS 契约(2026-09)
- 种子批处理(
be76012,M5):高置信种子融进验证器批量一起前向——被批的种子是"正常选出的目标 token"、不是草稿成功,不改变输出分布;接受率差的窗口暂停起草 32 周期。DS4_DSPARK_SEED_BATCH=0恢复旧调度。实测:Q2 C 哈希表 55.71→62.95 t/s(temp 0);DGX Spark 常驻 Q2 19.72→23.44→31.41 t/s(散文 ~18.8——推测只对可预测文本回本)。 - 六 token 验证 / 部分前沿(
8d309ab):种子 + 5 草稿需要前缀 1-4 各一份新鲜压缩器/索引器状态;spec_capture_prefixes+spec_frontier_commit_prefix()复用DS4_SPEC_PREFIX_SLOTS槽位。测试钩子ds4_test_dspark_prefix_capture比较压缩器/索引缓存行数(不止文本);tests/test_dspark_window.py不加载模型覆盖全部窗口管理 helper。 - EOS 契约(
7a8c1b2):草稿含内部 EOS 时,验证/捕获/提交前先截到首个 EOS——会话状态绝不跑到已返回 token 之外;尊重ignore_eos。tests/test_dspark_eos_contract.py对 mock 编译真实辅助函数,7,217 用例 / 240,503 断言。 - 什么时候回本:单 M5 Max 常驻 Q2 纯 decode 46.5 t/s vs DSpark 36-44(随
--dspark-confidence);CUDA 保留全部五个部分前缀(f6c169f),ROCm 保留四个、第五个重放(394865c)。诊断:DS4_DSPARK_CYCLE_TRACE/DS4_BENCH_SPEC_TRACE/DS4_DSPARK_EXPERT_OVERLAP。
相关概念
- Part 4 §推测解码 — MTP 原理与"逐行 argmax"验证不变量
- moe / quantization — 路由专家的激进量化让 Flash 能塞进本地内存,是本地推测解码的前提
- V4.1 Flash 不支持 DSpark/MTP 推测解码(引擎打开时直接拒绝,原生批处理路径也跳过捕获)
详见上游 docs/SPECULATIVE_DECODING.md。