Repository navigation
[None][feat] Reuse the standalone DSpark drafter's KV with the target's prefix cache - #22
Merged
zheyuf merged 4 commits intoOct 28, 2026
Conversation
DSpark drafters are trained with a non-causal block and a two-sided sliding window, but the drafter resolved every windowed layer as causal. GQA DSpark layers now resolve non-causal (W-1, W-1). trtllm-gen windows only causal attention, so the TRTLLM backend serves such a layer as the causal windowed decode, which also returns its log-sum-exp, plus a compiled merge of the block keys after each query. The workspace holds the softmax stats flashinfer carves off for the log-sum-exp. The window validator, which refused these layers, is removed. Based on efa53ad by Pranav Shrestha. Signed-off-by: Zheyu Fu <zheyuf@nvidia.com>
…ection sampling
The DSpark Markov head biases block position k by the token at position
k-1. With use_rejection_sampling the worker chained the bias through the
argmax and then sampled each position on its own, so once a draw left the
argmax, later proposals were conditioned on tokens the block does not
contain: lossless, but with lower acceptance from position 2 on.
Sampled DSpark drafts are now drawn ancestrally: position k from
softmax((base_k + bias(d_{k-1})) / T), d_{k-1} being the token drawn before
it, with the temperature only (vLLM's probabilistic drafting), and that
distribution is stored as its proposal. Greedy requests keep the greedy
sentinel temperature and draft the argmax chain.
Add rejection_sample_method ("standard" | "block", prototype, default
"standard"). "block" replaces the chain kernel of the one-model rejection
path with block verification (Sun et al., 2024, arXiv:2403.10444): lossless,
equal to the token-level rule for one draft, and the rule vLLM serves as
rejection_sample_method="block". It runs on static shapes without host
synchronization inside the CUDA graphs; its uniforms are a counter hash of
each request's acceptance-slot (seed, offset), and the emitted token is
drawn by the seeded sampler. Ragged (confidence-scheduled) steps keep
token-level verification.
Signed-off-by: Zheyu Fu <zheyuf@nvidia.com>
… a missed iteration A generation request absent from one batch (e.g. suspended by the V2 scheduler) lost its drafter slot and came back at context length 0: it drafted from nothing and wrote its accepted K/V at positions 0..K through its block table. On the manager-bound pool the context stays in the request's own pages, so a freed slot now parks its read base, the returning request resumes it, and the length follows the target position of its first input token. Signed-off-by: Zheyu Fu <zheyuf@nvidia.com>
…'s prefix cache The DSpark draft pool used 64-token pages, so it could not pair with the target's 128-token prefix cache: on a hit the drafter started from nothing. - Page size by capability: without the non-causal context kernel, the DFlash TRTLLM ops serve power-of-two pages from 128 tokens, so the draft pool takes the target's page size. Only a pool the drafter reads is paired. - Claims: a paired claim is valid where both pools hold it, or, with no draft page reused (fresh mirror), up to L + 1 - W of the target's match. A fresh mirror that ends within a window of its branch point recomputes from one window before it and publishes the drafter's window there. - Publication: the paired pool publishes only pages the drafter wrote. - Host tier: the paired pool gets its GPU funding of an explicit host budget (at most half), the same on every rank. - Attention DP: the pad dummy also gets a cache in the paired draft pool, which the V2 scheduler admits together with the target. Signed-off-by: Zheyu Fu <zheyuf@nvidia.com>
zheyuf
force-pushed
the
zheyuf/brb-dspark-draft-reuse
branch
from
October 28, 2026 03:38
e227b7f to
ae1a573
Compare
zheyuf
merged commit Oct 28, 2026
20a1a00
into
brb-nv:user/brb/m3.1-flash-gb300-initial
5 of 8 checks passed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #21: merge #21 first, then review the last 2 commits of this PR.
Description
With KV-cache block reuse on, the standalone DSpark drafter now keeps its context on a prefix-cache hit. Its draft pool used 64-token pages, so it could not pair with the target's 128-token prefix cache: on a hit the target reused the prefix while the drafter started from nothing. On #21 alone, greedy AL drops 9.4% from a cold request to the same request on a prefix-cache hit, and a sampled warm pass loses 6-8%.
Nothing to enable: with block reuse and KV cache manager V2, the drafter binds the draft pool at
page_size=128withreuse_addressable=True.Results
GB300, MiniMax-M3.1-Flash + DSpark K7, on a wheel of the base (1aa2dfc) with #21 and this PR applied on top; one fresh server per cell. Reuse cells use a production-like recipe (TP4 EP1 bs30, per_conversation reuse, 140 GiB host tier). In the #21-alone column, the golden / default and agentic cells were measured on #21's current head; the other three cells come from earlier runs of #21.
Test Coverage
test_paired_draft_reuse.py(new, GPU): two realKVCacheManagerV2s +KVCacheV2Scheduler: continuation hit, branch point (fresh-mirror recompute, then shared), commit gate with a negative control, attention-DP pad dummy admission.test_dflash_slot_resume.py(new, CPU): a request that misses an iteration resumes its parked context.test_kv_cache_estimation.py: page-size capability rule.test_kv_cache_budget_split.pyx8,test_estimation_temporarily_uses_inferred_pool_sizingx5,test_forward_step_carries_context_logits_request_to_runnerx5,test_mla_dspark_auto_backend_resolves_to_cutedsl).cleanup_stale_prs.test.jsand every pre-commit hook pass on the changed files;scripts/release_check.pyfails only at its whole-package bandit scan, on the 10 issues the branch head already has.🤖 Generated with Claude Code