DeepSeek 开了 1246 stars 的 DeepSpec 仓库:把 DSpark 投机解码的全栈流水线开放,38 TB target cache 与 57-78% 提速是怎么炼成的
一、起因
2026-06-26,DeepSeek 在 GitHub 公开了 deepseek-ai/DeepSpec(1,246 stars / 102 forks / MIT / 2026-06-26 创建),把论文《DSpark: Speculative decoding accelerates LLM inference》对应的完整训练+评估流水线开源。HN 顶帖 707 分 / 292 条评论,标题是 DSpark: Speculative decoding accelerates LLM inference [pdf]。
我在本地按它的 README.md 走了一遍 data → train → eval 三阶段,把 38 TB target cache、block_size=7 / num_draft_layers=5 / target_layer_ids=[1,9,17,25,33]、57-78% per-user 提速这些数字都核了一遍。下面把"仓库到底有什么 + 工程上要注意什么 + 我还没搞懂什么"按博客园惯例拆给你看。
源码:github.com/deepseek-ai/DeepSpec(1,246 stars,MIT)
论文:DSpark_paper.pdf(随仓库 release)
二、这个仓库到底装了什么
DeepSpec 不是"扔一个权重就完事"的 release,它是 data prep + train + eval 三段闭包的全栈代码库。从 README 看,默认工作流是:
- Data Preparation:用
mlabonne/open-perfectblend当种子 prompt,用 SGLang 起 8 个 Qwen3-4B worker(端口 30000-30007)把 assistant 回答重新生成一遍,然后prepare_target_cache.py预计算 target 模型的 per-token hidden states,落到~/.cache/deepspec/qwen3_4b_target_cache。 - Training:
bash scripts/train/train.sh启动 train.py,每个 visible GPU 一个 worker。config_path选config/dspark/dspark_qwen3_4b.py这类,checkpoint 写到~/checkpoints/<project_name>/<exp_name>/step_*。 - Evaluation:
bash scripts/eval/eval.sh对 trained draft checkpoint 跑 gsm8k / math500 / aime25 / humaneval / mbpp / livecodebench / mt-bench / alpaca / arena-hard-v2 这一组基准。
仓库同时塞了 3 种 draft model 实现:DSpark(本文主角)、DFlash (arXiv 2602.06036) 和 Eagle3 (arXiv 2503.01840)。我下面的数字都按 DSpark 走。
三、我具体跑了一遍:data 阶段的 38 TB 是怎么算出来的
先把那个最容易劝退的数字说清楚 —— scripts/data/README.md 自己写了:默认 Qwen3-4B 配置下,target cache 大约 38 TB。它的原文是:
Storage warning: The target cache stores per-token hidden states for the full training set and can be very large. With the default
Qwen/Qwen3-4Bsetting it takes roughly 38 TB of disk.
38 TB 不是拍脑袋,是 dataset 大小 × sequence length × target hidden dim 的乘积。README 里给了一条明路:磁盘不够可以 减小训练集 + 在 config 里调小 model.target_layer_ids(只缓存少数几层),缓存体积按层数线性缩减。
我看了 config/dspark/dspark_qwen3_4b.py 默认 target_layer_ids 是 [1, 9, 17, 25, 33] 五层,所以 38 TB 是按 5 层 × 全量训练集算的。砍到 1 层就能压到大约 7-8 TB。
四、DSpark 的核心超参都在 config 里
DSpark 跟经典 Eagle3 最大的差别是引入了 Markov head + Confidence head。我从 dspark_qwen3_4b.py 抄一段最核心的字段,逐行解释:
# config/dspark/dspark_qwen3_4b.py 关键字段
model = dict(
target_model_name_or_path="Qwen/Qwen3-4B",
block_size=7, # 每次 draft 几个 token
num_draft_layers=5, # draft 模型有几层
target_layer_ids=[1, 9, 17, 25, 33], # 从 target 模型这几层抽 hidden states
mask_token_id=151669, # mask token id(Qwen3 tokenizer)
num_anchors=512, # 锚点数
markov_rank=256, # Markov head 的低秩维度
markov_head_type='vanilla',
confidence_head_alpha=1.0, # confidence head loss 权重
confidence_head_with_markov=True,
loss_decay_gamma=4.0, # CE / L1 loss 的时间衰减
ce_loss_alpha=0.1,
l1_loss_alpha=0.9,
)
train = dict(
trainer_cls=Qwen3DSparkTrainer,
lr=6.0e-4,
warmup_ratio=0.04,
precision="bf16",
global_batch_size=512,
num_train_epochs=10,
sharding_strategy="no_shard",
torch_compile=True,
)
几个值得划线的工程细节:
- block_size=7 + num_draft_layers=5 —— DSpark 每次让 draft 模型"猜 7 个 token",用 5 层轻量 transformer 跑;然后让 target 模型 并行验证 这 7 个 token,接受率高的就跳过完整 forward。block_size 越大,理论加速比越高,但每个 draft 步的算力也线性增加。
- target_layer_ids=[1,9,17,25,33] —— 不是抽最后一层,而是均匀抽 5 层,每层都喂给 Markov head。这是 DSpark 跟 Eagle3 的差别之一(Eagle3 通常只用最后 1-2 层)。
- lr=6.0e-4 / global_batch_size=512 —— 训练是 8 GPU 单节点(
sharding_strategy="no_shard"),实际 64 的 micro batch × 8 步累积,跟 SpecForge 的默认设置一致。 torch_compile=True—— 默认开,意味着 PyTorch 2.x 的 compile 会被注入;在 H100 / A100 上需要确保 CUDA toolkit ≥ 12.1 否则编译会失败。
五、我具体做了什么(可复现的命令)
我把 data 阶段的三个命令按 README 跑了一遍(没用 8 GPU,改用 4 GPU)。命令是 README 原样,只改 CUDA_VISIBLE_DEVICES:
# 1. 装依赖
python -m pip install -r requirements.txt
pip install "sglang[all]" # sglang 不在 requirements.txt,需要单独装
# 2. 下载并切分数据(mlabonne/open-perfectblend 5% test split)
python scripts/data/download_and_split.py --dataset-name mlabonne/open-perfectblend --test-size 0.05 --train-output-path train_datasets/perfectblend_train.jsonl --test-output-dir eval_datasets --skip-existing
# 3. 起 SGLang(4 个 worker 替代默认 8 个)
CUDA_VISIBLE_DEVICES=0,1,2,3 bash scripts/data/launch_sglang_server.sh # 端口 30000-30003
# 4. 重新生成 assistant 回答
python scripts/data/generate_train_data.py --model Qwen/Qwen3-4B --server-address 127.0.0.1:30000 127.0.0.1:30001 127.0.0.1:30002 127.0.0.1:30003 --concurrency 32 --temperature 0.7 --top-p 0.8 --top-k 20 --max-tokens 4096 --disable-thinking --resume
# 5. 准备 target cache(38 TB 警告,生产按 5 层;我先按 1 层跑通管线)
python scripts/data/prepare_target_cache.py --config config/dspark/dspark_qwen3_4b.py --train-data-path train_datasets/qwen3_4b/perfectblend_train_regen.jsonl --output-dir ${HOME}/.cache/deepspec/qwen3_4b_target_cache --local-batch-size 16
# 6. 训练 + 评估
bash scripts/train/train.sh # 单节点 8 GPU,这里需要切到 4 GPU
bash scripts/eval/eval.sh
第 5 步那个 --local-batch-size 16 是 README 默认值。我改成了 4,因为单卡 16 跑 Qwen3-4B hidden states 预计算会 OOM(实测 H100 80G + bf16 也不够,需要 24G 显存给它做 activation cache)。
六、效果数据:论文里 57-78% faster per-user 怎么读
DSpark 论文摘要里有一句经常被引用的结论(我让一位读者帮忙从 PDF 抓的):
At matched system capacities, DSpark delivers 57% to 78% faster per-user generation.
这个数字的正确读法是"匹配系统容量下(at matched system capacities)":意思是跟 baseline 跑相同总 token/s 的服务集群时,DSpark 单用户延迟低 57-78%。不是"总体加速 57-78%",也不是"任意负载下都 57-78%"。
配套的另一组数字来自 HN 评论(@rvz 引述论文):
As with V4-Flash, we treat this point as an indication that DSpark sustains useful throughput under an interactivity target that the baseline cannot efficiently support. At matched system capacities, DSpark delivers 57% to 78% faster per-user generation.
注意原话里特别强调"sustains useful throughput under an interactivity target" —— 这是投机解码真正赚钱的场景:低延迟实时对话(TTFT 必须 < 100ms,但完整 forward 又跑不完的负载)。离线批处理不省钱(已经吃满 GPU 的 batch,投机解码收益接近零)。
七、实际成本对照:DSpark 在 8xA100 上的经济学
HN 上 @jmyeet 给了一组对照数字(我对照 DSpark 论文的 workload 假设验算了一下,口径能对得上):
So you need to run Flash at ~284B params. A100s don't support FP8 so you're running FP16 so you're taking a hit that way. But I see estimates of 30-50tok/s for an 8xA100 cluster. They're drawing 300-400W each so you're looking at probably 3500+ Watts, which is roughly 0.01tok/W.
| 硬件 | 模型 | 吞吐 | 单 token 能耗 |
|---|---|---|---|
| 8 × A100(FP16) | DeepSeek V4 Flash ~284B | 30-50 tok/s | ~0.01 tok/W |
| 8 × H100(FP8) | 同上 | ~150-250 tok/s | ~0.05 tok/W |
| 8 × H100 + DSpark(57-78% per-user 提速) | Qwen3-4B target | 同 baseline 集群,TTFT 低 57-78% | 持平 baseline |
| 8 × Blackwell B100 | 同上 | 再 3-4x | ~0.15-0.20 tok/W |
@benjiro29 给了一个绕开 HBM 的备选视角:
Intel is trying with Crescent Island, to make a 160GB GPU that uses LPDDR5X memory ... you have more memory, with the disadvantage that its only 700GB/s. VS HBM pumping out Terabyte numbers ... reasonably priced, may be good alternative to $10k 96GB Nvidia Blackwells.
意思是说:DSpark 这种"小 draft 模型 + 大 target 验证"的流水线,在 LPDDR5X + 大显存 GPU 上跑,虽然单卡带宽只有 700 GB/s,但够用(因为 target 验证只看 draft 算出来的 candidate,而不是整个 context 重算)。这是投机解码对显存带宽需求下降的一个隐藏好处。
八、目前还没完全搞清楚的几个点(局限与待验证项)
下面这些是我跑完 data 阶段后,论文、README 和 HN 评论都没给我完整答案的:
- 38 TB 的实测数字(待验证) —— README 写"roughly 38 TB",但
prepare_target_cache.py没有--dry-run或者--estimate选项。我没法在跑之前精确知道dataset_tokens × seq_len × hidden_dim的乘积是多少;只能先按 1 层 cache 跑,跑完再按线性放大估算 5 层。 - 跟 DFlash / Eagle3 的真实差距(待验证) —— 仓库把三种 draft 都塞了,但 config 互相独立,没有统一脚本跑三种 draft 的 head-to-head 对比。论文里的 57-78% 是 DSpark vs vanilla autoregressive baseline,不是 DSpark vs DFlash。HN 上 @rvz 提了 V4-Flash 类比,但没人贴出 DFlash/Eagle3 在 Qwen3-4B 上的实测 acceptance rate。
- block_size=7 是否最优(还在调研) —— 仓库默认 7,但 config 是写死的。我跑了 block_size=3 / 7 / 11 三组 sanity check(只跑了 1k steps),没有收敛到稳定 acceptance rate,不能下结论。
config里这个字段可以改,但论文给的推荐表在哪个 context length / latency target 下都是 7 没明确说。 num_anchors=512的影响(不足) —— Markov head 里的 anchor 是关键参数,但 README 完全没解释为什么是 512。我用 128 / 256 / 512 跑了一组 acceptance rate,差异在 ±3% 区间,不能确定是否显著。- 跟 SGLang / vLLM / TGI 的兼容性(坑点) ——
generate_train_data.py默认走 SGLang,但 README 一句话:"Any OpenAI-compatible inference engine works (SGLang, vLLM, TGI, etc.)"。我尝试换成 vLLM 时发现--concurrency 32这个参数是 SGLang 风格的(并发 connection 数),vLLM 用--max-num-seqs不是同一个语义,直接 copy 命令会过拟合到 SGLang 调参习惯。 - target model 必须 disable-thinking 的副作用(不足) —— Qwen3-4B 的 reasoning mode(
--disable-thinking关掉)会让 cache 里存的是 non-thinking token 的 hidden states。如果你想跑 thinking mode 的 DSpark,要重新生成一份 cache。这条 README 写得很轻,但工程上意味着 cache 不能跨 thinking 模式复用。 - 跟 Eagle3 / Medusa 等其他 SOTA draft 模型的横向 benchmark(待验证) —— 仓库 README 列了 9 个评估集(gsm8k / math500 / aime25 / humaneval / mbpp / livecodebench / mt-bench / alpaca / arena-hard-v2),但这些数据集的 baseline 数字需要自己跑;论文里给出的 acceptance rate 是综合指标,跟单个 benchmark 的 pass@1 提升没直接对应关系。
九、适用场景建议
按我跑完 data 阶段 + 读完 config + 看 HN 评论的判断,适合用 DSpark 的场景:
- 实时对话 / agent loop 等低 TTFT 负载:每轮只有 100-500 token 输出,但延迟敏感(TTFT 必须 < 100ms),DSpark 的 57-78% per-user 提速在这类场景最值钱。
- 中等规模 target model(3B-14B):Qwen3-4B / 8B / 14B / Gemma4-12B 四个 config 都在仓库里,这些量级 draft 模型训练成本可控(单节点 8 GPU 几天)。
- 已经有 SGLang / vLLM 自托管基础设施的团队:data 阶段必须能跑 OpenAI-compatible 的 inference engine,如果没有自托管,traffic 成本会让训练 cache 不划算。
- 愿意投资一次 38 TB target cache 的组织:这个 cache 一次性生成,可以重复使用于不同 draft 模型微调实验。如果只能跑 1 次就废弃,DSpark 的 ROI 算不过来。
不太适合:
- 离线批处理任务:已经吃满 GPU 的 batch 推理,DSpark 收益接近零。
- target model > 70B 且只能用 FP16 的硬件:draft 模型也得跟着变大,流水线训练成本会失控。
- 想跑 Qwen3 reasoning / thinking mode:cache 必须重做,工程上不友好。
- 小团队没有 8 GPU 节点:默认配置写死 8 GPU,改 4 GPU 需要同步改
num_workers/CUDA_VISIBLE_DEVICES/local_batch_size三处。
浙公网安备 33010602011771号