DSpark in SGLang: Speculative Decoding with Confidence-Driven, Variable-Length Verification

发表时间: 2026-07 · Blog post by SGLang Team (lmsys.org)

原文: https://lmsys.org/blog/2026-07-06-dspark-sglang

SGLang Team, July 6, 2026

速读

一句话结论
SGLang 引擎集成了 DSpark 投机解码算法,通过半自回归草稿模型和基于置信度的变长验证机制,在 DeepSeek-V4 等模型上实现了高并发下吞吐量与延迟的最佳折中,单批次解码速度可达 383.7 tok/s。

要解决什么问题
传统的投机解码用额外的计算量换取更少的解码步数,但这种收益会随着系统负载的增加而恶化。当批处理大小为 $B$、每个请求生成 $K$ 个草稿 token 时,目标模型每步需要验证 $B \times K$ 个 token。在并发量较低时,目标模型的验证成本不敏感;但当并发量跨过某个临界点,验证这些庞大且包含大量最终会被拒绝的 token 所带来的计算开销,会超过投机解码节省下来的时间,导致系统吞吐量遇到瓶颈。此外,在工程实现上,不同请求的草稿接受长度不一,如果使用固定形状的 CUDA 图进行验证,就必须将所有请求对齐填充到最大块长度,这会将原本试图通过裁剪掉低置信度 token 来节省的计算量,以无效填充的形式重新加回来,使得变长验证的构想在底层硬件上失效。

怎么做的
DSpark 从草稿生成和目标验证两端同时解决上述卡点,核心思路是保证高接受率的同时,动态裁剪掉不值得验证的 token,并用无填充的底层工程将其落地。首先,在草稿端引入半自回归块生成器(Block drafter)。它通过一次前向传播生成包含 $\gamma$ 个 token 的块,并用轻量级的序列头(马尔可夫或 RNN)让每一步条件依赖于前一个 token,从而维持高接受率。同时,置信度头(Confidence head)会评估每个草稿 token 存活的概率,并通过顺序温度缩放(STS)进行校准,使其反映真实的接受率。其次,在服务端引入置信度调度器(Confidence scheduler)。它在线读取离线分析的附加 SPS 成本表,成本模型定义为:

$$T(bs, K) = bias + \alpha(bs) + \theta(bs + K)$$


其中 $\alpha(bs)$ 是不受裁剪影响的基础开销,$\theta$ 是验证 token 的边际成本。调度器据此权衡预期接受的 token 数与真实边际成本,为每个请求动态分配不同的验证长度预算,停止验证那些大概率会被拒绝的 token。最后,为了让变长验证真正省时,SGLang 设计了基于完整 CUDA 图的参差验证(Ragged verify)。它不按最大长度填充,而是将批次内长度不一的请求前置打包进一个紧凑的缓冲区,仅将总 token 数向上取整到最近的 CUDA 图捕获层级。当调度器削减预算时,打包后的总数下降,系统会重放一个真正更小的 CUDA 图。此外,系统还集成了零开销调度,将调度器的开销隐藏在模型前向传播的异步流中,消除了每步之间的气泡。

效果如何
实验在 H200(4 卡 DP)和 B300(8 卡 TP)硬件上运行,测试了 DeepSeek-V4-Flash 和 DeepSeek-V4-Pro 模型。对比基线包括:不使用投机解码的常规自回归基线,以及代表 EAGLE 路线的 MTP 方法(取 1-1-2 和 3-1-4 配置在不同批处理大小下的最优值)。在批处理大小从 1 到 256 的并发扫描中,DSpark 在整个区间内均提供了优于 MTP 和常规基线的吞吐量与延迟折中。在单批次下,DeepSeek-V4-Pro 达到了 383.7 tok/s 的解码速度。在混合流量(高接受率的 gsm8k、中等的 arena-hard、低接受率的 poetry)测试中,调度器成功实现了请求级别的差异化:gsm8k 分配了 5.24 个 token 的验证窗口,而 poetry 仅分配 2.91 个,且两者对理论接受上限的利用率均保持在 0.88 到 0.97 的高位。作者也指出了当前实现的局限性:当前的置信度调度器和 SPS 成本表仍是初代基础版本,尚未完全覆盖上下文长度变化对步进成本的影响;此外,动态裁剪会掩盖真实的接受率上限,必须依赖额外的 cap-accept 模式或专门的块接受估计器来进行事后观测。

A1 主要贡献

在推测解码(Speculative Decoding)中,通过消耗额外的计算资源来减少解码步数,但随着系统负载的增加,这种权衡会变得不再划算:在批次大小为 $B$ 且推测token数为 $K$ 时,目标模型每步需要验证 $B \times K$ 个token,当超过某个临界点时,其带来的成本将高于其节省的时间。DSpark 算法从两端解决了这一问题:一是引入了半自回归区块草稿模型(每次草稿前向传播生成整个区块,从而保持高接受率);二是引入了由草稿模型自身置信度驱动的每请求可变验证长度机制,停止验证系统不太可能接受的token。

本文的主要贡献在于将 DSpark 算法成功集成至 SGLang 服务引擎中,并支持密集模型(如 Qwen3)和稀疏模型(如 DeepSeek-V4)。该集成不仅在开源服务引擎上复现了原论文中性能增益的趋势(即提升了每用户速度,并展示了负载上升时验证预算的收缩),还实现了将其转化为实际挂钟时间(wall-clock time)的工程架构:包括在不规则、每请求可变的验证长度上支持完整的 CUDA 图;实现隐藏调度开销的重叠感知推测路径;引入成本表分析器以在线调整每个请求的验证预算;以及提供截断操作下接受上限的可观测性。

非推测基线、MTP与DSpark的吞吐量与每用户解码速度对比
图1:总吞吐量(y轴)与每用户解码速度(x轴)的对比;每条曲线展示了并发量从批次1扫描至256的结果。右上角代表更优的性能。

A2 方法细节

DSpark算法核心组件:算法在草稿端(draft-side)包含三个核心部分。首先是区块草稿模型(Block drafter),支持密集模型(如 Qwen3)和稀疏模型(如 DeepSeek-V4),其一次前向传播会生成一个包含 $\gamma$ 个token的区块。该模型结合了一个轻量级的序列头(马尔可夫或RNN),使每一步都条件依赖于前一个token,从而实现半自回归。其次是置信度头(Confidence head),它对每个生成的草稿token通过验证的几率进行打分,整个区块内分数的乘积即为该区块的存活概率。最后是序列温度缩放(STS, Sequential Temperature Scaling),用于校准这些置信度分数,确保存活概率能够准确反映调度器进行预算规划时所依据的真实接受率。

SGLang的服务支持层扩展:围绕DSpark算法,SGLang增加了多项服务支持面。核心包括置信度调度器(Confidence scheduler),负责在每一步将每区块的存活概率转化为每个请求的验证预算。系统实现了每请求不规则验证(Per-request ragged verify),允许在同一个批次内存在可变的验证长度(支持 static、compact、cap-accept 模式)。此外,系统在不规则的、可变长度的验证之上捕获了完整的CUDA图(Full CUDA graph)。为了支持分析,引入了可观测性机制(Observability)来监控截断下的接受上限及其他指标。系统还包含一个附加的SPS成本表(Additive SPS cost table),这是一个离线分析的步进时间模型,由调度器在线读取。在并行策略上,支持数据并行注意力(Data-parallel attention)并与其他并行维度共存。最后,通过集成到SGLang的重叠调度器中,实现了几乎没有DSpark特定特殊处理的零开销调度(Zero-overhead scheduling),并通过融合的Triton内核和分片的区块草稿模型矩阵乘法完成了性能优化。

验证模式设计:系统的运行主要围绕三种验证模式展开。static 模式是基线路径,在每一步都会验证完整的草稿区块。compact 模式是生产环境路径,仅验证调度器为每个请求挑选的窗口长度。cap-accept 模式则验证完整的区块,但仅提交到调度器设定的窗口长度:其输出与 compact 模式完全相同,但暴露了如果进行完整验证本可以接受的token数量,以此来衡量截断操作下的接受上限。

基于完整CUDA图的不规则验证机制:由于每个请求的窗口大小不同,无法直接适应固定形状的CUDA图。例如,在一个批次中,如果一个请求验证2个token,另一个验证6个,则不存在单一的查询长度;如果将所有请求都填充到完整的区块宽度,那么截断所节省的计算量就会被填充物抵消。因此,系统保持批次的不规则性(ragged),并根据总token数来键入CUDA图。具体做法是,将可变长度的请求前向打包(front-pack)到一个紧凑的缓冲区中,并向上取整到最近的已捕获CUDA图层级。当预算减少导致截断时,打包后的总token数会下降到一个更小的层级,此时DSpark能够重放一个真正更廉价的CUDA图(包含更少的注意力和MLP行,而不是掩码化的全宽前向传播)。在数据并行(DP)注意力下,各个rank共享一个层级(即任何rank所需的最大层级),并同步降低层级。打包后的缓冲区采用类似 cu_seqlens 的可变长度输入格式,因此紧凑验证重用了后端已有的注意力内核。例如在 DeepSeek-V4 上,直接复用了模型原生的稀疏MLA路径(flash_mla),无需编写新内核;每个支持的后端在图重放时,只需根据打包布局重建其可变长度元数据。
固定形状解码图与不规则紧凑图的对比
图2:将具有每请求可变验证长度的批次适配到已捕获的CUDA图中。固定形状的图将每个请求填充到完整的区块宽度;不规则路径将调度的token前向打包,并仅将总数向上取整到最近的捕获层级,从而在产生相同接受token的情况下计算少得多的填充单元。

可观测性与截断上限恢复:截断操作掩盖了系统的接受上限:compact 模式仅验证区块的前几个位置(即调度器的窗口),因此在这一步完整区块验证本可以接受的token数量是不可观测的。如果没有这个数据,就无法区分合理的截断与有损的截断。cap-accept 运行模式恢复了这一数据,它验证完整区块但仅提交到窗口长度,从而在暴露上限的同时保持与 compact 相同的提交内容。系统还提供了每请求的置信度和校准指标(如ECE)以供事后分析。

截断下的上限估计器:对于生产环境或不希望运行额外伴随测试(如 cap-accept)的场景,系统设计了一个区块接受估计器(block-accept estimator),能够直接在 compact 运行中恢复被掩盖的上限。该估计器利用未来步骤中目标token的使用情况及其对数概率(logprobs),并假设截断与未截断轨迹中锚点token的属性相似,从而计算反事实尾部的估计区间。

性能优化与零开销调度(ZOS)实现:工程实现通过两种方式将调度转化为挂钟时间的缩减:降低每步成本,以及将调度器隐藏在前向传播之后。这些优化使得系统在 DeepSeek-V4-Pro (TP=8, B300) 上,批次大小为1且接受长度约为5时,达到了 383.7 tok/s。在内核层面,将零散的微小操作重写为融合的Triton内核,例如紧凑散射(compact scatter)、SWA页面索引、验证长度top-k调度以及不规则窗口打包。区块草稿模型的采样路径被折叠进融合内核中,其矩阵乘法也被分片。在示例配置中,目标验证之外的开销从7.3毫秒缩减了1.7毫秒。在调度层面,DSpark被直接集成到SGLang的零开销(重叠)调度器中,几乎没有增加特定的管道代码。SGLang的spec-v2运行时已经在独立的流上将下一步的调度与当前的前向传播重叠,DSpark作为一等工作节点加入其中:前向传播输出作为异步future返回,跨迭代排序依赖运行时的设备端屏障(device-side barrier),设备端页表意味着无需每步进行主机同步。论文中提出的两步后向置信度中继(two-step-back confidence relay)使用相同的通道进行读取。最终,解码循环运行时没有每步气泡,比关闭调度器时紧凑约1.5倍。
批次1解码:重叠调度器关闭与开启的对比
图5:批次大小为1时的解码,重叠调度器关闭(顶部)与开启(底部)的对比。开启后,run_batch 迭代之间,以及单个步骤内的区块草稿生成与目标验证阶段之间均无气泡。

成本表分析与建模:系统通过加法模型来表达调度器对步进时间 $T(bs, K)$ 的估计(其中 $K$ 为批次的额外验证token数):$T(bs, K) = bias + \alpha(bs) + \theta(M)$,其中 $M = bs + K$。公式中 $\alpha(bs)$ 是请求扩展的底线成本(包括草稿传递加上部分注意力),该项不受截断影响;$\theta(M)$ 是目标的验证token成本,也是截断唯一能恢复的项。调度器的 argmax 算法在预期接受的token数与实际边际成本之间进行权衡,因此只有在 $\theta$ 较大时才会显现出截断的余地。
附加成本模型拟合与预测验证
图6:附加成本模型——原始步进时间与拟合结果(a)及吞吐量(b)——以及预测与测量的解码步进时间对比(c)。

A3 背景知识/关键Observation/设计原则

动态与固定调度的对比观察:通过对比 compact(每步SPS-argmax预算的动态截断)与 no-trim(在相同不规则路径下运行的完整区块调度),可以观察到动态预算的优势主要体现在高批次场景下。在批次大小为1时,目标模型的验证并不会因为token增多而明显减慢,因此截断节省的时间很少,两者的表现持平。随着并发量的增加和吞吐量开始趋于平稳,截断通过缩短步长使得 compact 模式取得了领先。在接受率较低的示例中,由于较低的接受率留下了更多的尾部可供截断(这与成本模型的预测完全一致),这种性能差距更大,且在较低的批次时就已显现。
高接受率示例下的动态截断与完整区块对比
低接受率示例下的动态截断与完整区块对比
图3:在DP4下批次1至256,compact(动态截断)与 no-trim(完整区块)在两个接受率不同的示例上的对比。

混合流量下的每请求差异化原则:同质化的扫描测试会掩盖置信度调度的真正价值。设计原则指出,在同一个批次中,如果一个请求的预测难度远低于另一个,它们就不应该获得相同的验证窗口,混合流量正是验证这一点的关键场景。当按接受难度混合三个负载(gsm8k高接受率、arena-hard中等、poetry低接受率)时,验证窗口随着难度的增加而显著收缩(分别为5.24、3.78、2.91个token),同时相对于上限的利用率(即未截断区块将接受的token数)保持在0.88–0.97的高水平。这表明调度器正在为每个请求定制大小,而不是简单地应用一个批次平均值。微观层面的观察显示,约55%的gsm8k步骤填满了完整的6个token窗口,而约80%的poetry步骤仅使用了3个或更少的token。
按负载划分的验证预算与每步验证长度分布
图4:按负载划分的验证预算(左)与每步验证长度分布(右)。

A4 实验环境

  • 数据集:用于混合流量测试的数据集包括 gsm8k(高接受率)、arena-hard(中等接受率)和 poetry(低接受率)。用于并发扫描测试的数据集为拼接的16个GSM8K问题(frontier_prompt.txt),以确保生成内容为真实文本。
  • 模型架构:支持密集模型(Qwen3)和稀疏模型(DeepSeek-V4, DeepSeek-V4-Flash, DeepSeek-V4-Pro)。
  • 硬件配置:

    • 并发扫描与吞吐量测试:搭载 H200 GPU,配置为数据并行度 DP=4。
    • 零开销调度测试:搭载 B300 GPU,配置为张量并行度 TP=8。
  • 软件配置:基于 SGLang 框架实现,依赖 FlashInfer 作为 MoE 运行后端(flashinfer_mxfp4),使用完整的 CUDA 图(CUDA graphs)和融合的 Triton 内核优化。

A4 实验结果

  • 非推测基线、MTP与DSpark的吞吐量/延迟对比实验:

    • 实验内容:在 H200 (DP4) 上运行 DeepSeek-V4-Flash,将并发批次从 1 扫描至 256,对比非推测基线、MTP(EAGLE风格基线,取1-1-2和3-1-4配置中的最优值)以及 DSpark。
    • 实验结果与分析:DSpark 在整个并发扫描中提供了最佳的吞吐量/延迟权衡,明显领先于 MTP 和非推测基线(见图1)。
  • 动态与固定调度的对比实验:

    • 实验内容:在不同接受率的提示词下,对比 compact(动态截断)与 no-trim(完整区块验证)在批次 1 至 256 下的表现。
    • 实验结果与分析:在批次1时两者性能持平;在高批次时,compact 显著提升吞吐量。在低接受率的数据集上,compact 的优势更大且出现得更早,证明了动态截断在系统负载增加时的有效性(见图3)。
  • 混合流量下的预算分配实验:

    • 实验内容:在同一批次中混合 gsm8k、arena-hard 和 poetry 请求,测试 cap-accept 模式下的验证窗口分配和利用率。
    • 实验结果与分析:验证窗口按难度动态调整(gsm8k 5.24, arena-hard 3.78, poetry 2.91 tokens),且上限利用率极高(0.88-0.97)。证明调度器能够精准地为每个请求进行差异化预算分配(见图4)。
  • 零开销调度性能评估实验:

    • 实验内容:在 DeepSeek-V4-Pro (TP=8, B300) 上测试批次大小为1的极限性能。
    • 实验结果与分析:在接受长度约为5时,达到了 383.7 tok/s 的极高速度。分析表明,目标验证之外的开销缩减了1.7毫秒,解码循环内无气泡(见图5)。
  • 成本模型验证实验:

    • 实验内容:记录实际运行时的步进时间并与附加成本模型的预测值进行对比。
    • 实验结果与分析:附加成本模型准确预测了不同批次和验证token数下的步进时间,在真实服务器上得到了有效验证(见图6)。

A5 结论

DSpark 算法已成功集成至 SGLang 服务引擎中,有效解决了推测解码在高负载下验证成本过高的问题。未来的工作展望主要集中在以下几个方面:

  1. 成本模型与调度:开发更强、更在线/自适应的成本模型,并进一步改进动态调度器。
  2. 模型覆盖:扩大对更多密集和稀疏模型的支持。
  3. 并行计算:在更广泛的并行模式和服务拓扑中提供支持。
  4. 可观测性:将区块接受估计器和跨检查点的置信度校准等指标推向生产环境。
  5. 鲁棒性:强化完整CUDA图路径,并进行更广泛的压力和回归测试。

A6 附录

复现细节:所有命令均在预构建的 Docker 镜像(docker pull lmsysorg/sglang:dev-dspark)中运行,或从特定的 PR 分支(commit 692c5f7d)源码构建。

图1、3和6的复现(前沿服务器,DeepSeek-V4-Flash, H200, DP4):
启动 DSpark 分支需使用 sglang.launch_server 模块,配置模型路径为 deepseek-ai/DeepSeek-V4-Flash-DSpark,推测算法设置为 DSPARK,并启用 DP 注意力和 DP LM 头部。MoE 运行后端指定为 flashinfer_mxfp4。参数 --disable-radix-cache 用于防止基准测试命中缓存。

SGLANG_ENABLE_METRICS_DEVICE_TIMER=1 \
python3 -m sglang.launch_server \
  --model-path deepseek-ai/DeepSeek-V4-Flash-DSpark \
  --speculative-algorithm DSPARK \
  --tp 4 --dp-size 4 --enable-dp-attention --enable-dp-lm-head \
  --moe-a2a-backend none --moe-runner-backend flashinfer_mxfp4 --disable-flashinfer-autotune \
  --swa-full-tokens-ratio 0.1 --chunked-prefill-size 1024 \
  --mem-fraction-static 0.8 --cuda-graph-max-bs 192 --max-running-requests 1024 \
  --disable-radix-cache --trust-remote-code --host 0.0.0.0 --port 30000

其他分支仅需修改推测配置:非推测分支移除 --speculative-* 参数并加载标准模型;MTP 分支使用相同的目标模型,算法设置为 EAGLE,并配置相应的步数和草稿token数。DSpark 的 compact 或 static 模式通过环境变量 SGLANG_RAGGED_VERIFY_MODE 切换;在执行带 SPS 表的 compact 模式时,使用 --speculative-dspark-sps-table-path 指定路径;图3的 no-trim 分支则是在没有 SPS 表的情况下运行 compact 模式。
批次扫描测试使用 one_batch_server 脚本,指定固定的提示词文件(包含16个拼接的GSM8K问题):

python3 -m sglang.benchmark.one_batch_server \
  --model None --base-url http://127.0.0.1:30000 \
  --batch-size 1 8 16 32 64 96 128 160 192 256 --output-len 1024 --temperature 0.7 \
  --fixed-prompt-file frontier_prompt.txt --fixed-prompt-apply-chat-template --show-report

图6的成本表通过在 compact 模式下设置环境变量 SGLANG_DSPARK_ENABLE_SPS_RECORD=1 SGLANG_SIMULATE_ACC_LEN=1.0 启动,随后运行 sglang.benchmark.dspark_sps_profiler all 拟合加法模型。

图4的复现(混合流量):
在与图1相同的服务器环境下,设置 --mem-fraction-static 0.7 和区块大小为6。通过修改 SGLANG_RAGGED_VERIFY_MODE,分别运行 static、compact 和 cap-accept 模式,并输入包含 gsm8k、arena-hard 和 poetry 的混合请求集,测量非流式完成时间(makespan)吞吐量。

图5的复现(零开销调度,DeepSeek-V4-Pro, B300, TP8):
启动服务器时,配置环境变量以启用紧凑验证、FP4专家模型以及Torch Profiler。

SGLANG_RAGGED_VERIFY_MODE=compact SGLANG_DSV4_FP4_EXPERTS=1 SGLANG_TORCH_PROFILER_DIR=./trace \
python3 -m sglang.launch_server \
  --model-path deepseek-ai/DeepSeek-V4-Pro-DSpark --speculative-algorithm DSPARK \
  --tp 8 --moe-runner-backend flashinfer_mxfp4 --disable-flashinfer-autotune \
  --mem-fraction-static 0.82 --chunked-prefill-size 4096 --cuda-graph-max-bs 4 \
  --trust-remote-code --host 127.0.0.1 --port 30000
# 若要关闭重叠调度:追加 --disable-overlap-schedule

随后捕获批次1的解码轨迹,并仅读取GPU通道数据:

python3 -m sglang.benchmark.one_batch_server \
  --model None --base-url http://127.0.0.1:30000 \
  --batch-size 1 --input-len 256 --output-len 256 \
  --profile --profile-activities GPU --profile-steps 20