Repository navigation
Conversation
CUDA-graph padding rows and warmup dummies share the drafter's dummy slot. Their accepted tokens grow its context length like any request's, but nothing reset it, while their page-table rows are the padding request's pages with every other entry mapped to page 0, another request's page. Once the dummy length passed the padding request's own pages, the padding rows' context K / V (k3_ctx_kv, or the torch path) landed on that page: a live request's drafter context overwritten on every padded step, costing acceptance. prepare() now writes 0 to the dummy slot every step, with the evicted slots. test_dflash_dummy_slot.py: padded steps keep the dummy slot at 0 and the real slots untouched; an evicted request and the dummy reset in one step. It fails without the reset. Signed-off-by: Vasanth Sabavat <vsabavat@nvidia.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configuration
📒 Files selected for processing (2)
Included review availability: This review used your included allowance. Your plan provides up to 12 included reviews per hour; 11 remain after this review. WalkthroughDFlash now uses ChangesDFlash dummy-slot preparation
Priority: ➖ Normal Estimated code review effort: 2 (Simple) | ~10 minutes Change: Bug fix Suggested reviewers: Merge Risk: ⚪ Minimal · up to The dummy-slot reset is in place for the inspected drafting paths. No issue requiring a fix before merge was identified. 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
|
Thanks for tracking this down. The root cause matches what we have seen. For performance, though, I'd suggest doing the reset inside the drafting step rather than in self._ctx_len[slots] += gen_num_accepted_long
self._ctx_len.clamp_(max=self._max_ctx)
# Padding and ADP dummy rows share a slot that is never freed; keep its
# context empty. zero_() is graph-capturable, a scalar store is not.
self._ctx_len[self._dummy_slot].zero_()Why this is better for perf:
We validated this variant end to end on an internal branch: padded-step drafter attention dropped from ~520 to ~45 us/layer, and tokens/s/user improved by +2.8% (helix16, bs16) and +17% (DEP16). The unit tests would then need to drive the drafting-step update (or a small helper factored out of it) instead of |
The dummy slot's context length grows only where the drafting step adds the step's accepted tokens. Emptying it right after that add, with a zero_() on the fixed slot that a captured step replays, keeps it at 0 between steps without host work. prepare() again writes slot lengths only for evicted requests, instead of two pinned tensors, two H2D copies and an index_copy_ on every step. Dummy rows also attend no context in the step itself, rather than that step's accepted tokens. test_dflash_dummy_slot.py drives the drafting-step update (_advance_ctx_len), including a captured CUDA graph replayed over a dirtied dummy slot, and checks that prepare() writes only evicted slots. Signed-off-by: Vasanth Sabavat <vsabavat@nvidia.com>
|
@juney-nvidia could you please |
|
Thanks, agreed. It is pushed as a follow-up commit,
I checked the three points against the code:
The tests in Kimi K3 numbers: 16 GB200, DSpark with 7 drafts, acceptance forced to 6, ISL / OSL 1024, 5 reps per cell. Median TPOT
So the change is correct and a small win here. |
|
@juney-nvidia could you please |
…ummy slot in the drafting step Signed-off-by: Vasanth Sabavat <vsabavat@nvidia.com>
NVIDIA#19827 now empties the dummy slot in the drafting step, right after the torch path adds the step's accepted tokens, instead of in prepare(). The fused trtllm::k3_ctx_kv path does that add inside the kernel and skips the torch add, so without this its dummy slot would grow again. Empty it right after the kernel, the same fixed-slot zero_() a captured step replays. Signed-off-by: Vasanth Sabavat <vsabavat@nvidia.com>
|
/bot run |
|
PR_Github #76602 [ run ] triggered by Bot. Commit: |
|
PR_Github #76602 [ run ] completed with state
|
|
/bot run |
|
PR_Github #76625 [ run ] triggered by Bot. Commit: |
|
PR_Github #76625 [ run ] completed with state
|
|
Superseded by the consolidated draft PR: #19988. Source commits and follow-ups are retained; prior reviews remain historical evidence, not approval of the replacement heads. |
Pull request was closed
Description
CUDA-graph padding rows and warmup dummies decode on DFlash's dummy slot (
worker._dummy_slot,tensorrt_llm/_torch/speculative/dflash.py).DFlashSpecMetadata.prepareresets only evicted slots, and_assign_slotnever runs for thedummy slot, so the dummy's context length grows by every padded step's accepted tokens.
mapped to page 0, which belongs to another, live request.
A live request's drafter context is overwritten on every padded step. This costs acceptance only, because the
target verifies.
It is reachable in any configuration whose CUDA graphs pad a batch.
The drafting step empties the dummy slot right after it adds the step's accepted tokens (a
zero_()on the fixedslot, captured with the step), so
prepare()keeps writing only evicted slots.Test Coverage
tests/unittest/_torch/speculative/hw_agnostic/test_dflash_dummy_slot.py(new; needs a GPU, the slot lengths live onit):
_advance_ctx_len) keeps the dummy slot at 0 and leaves the real slots untouched;prepare()writes only evicted slots.On GB200 all 3 pass; the two dummy-slot tests fail without the
zero_().speculative/hw_agnostic/has no new failures.
l0_h100.ymlcollects the file throughunittest/_torch/speculative/hw_agnostic; onl0_cpuit skips (no GPU).PR Checklist
Please review the following before submitting your PR:
PR description clearly explains what and why. If using CodeRabbit's summary, please make sure it makes sense.
PR Follows TRT-LLM CODING GUIDELINES to the best of your knowledge.
Test cases are provided for new code paths (see test instructions)
If PR introduces API changes, an appropriate PR label is added - either
api-compatibleorapi-breaking. Forapi-breaking, includeBREAKINGin the PR title. (No API change.)Any new dependencies have been scanned for license and vulnerabilities (No new dependencies.)
CODEOWNERS updated if ownership changes (No ownership change.)
Documentation updated as needed (No user-facing change.)
Update tava architecture diagram if there is a significant design change in PR. (No design change.)
The reviewers assigned automatically/manually are appropriate for the PR. (To check once the PR is open.)
Please check this after reviewing the above items as appropriate for this PR.
GitHub Bot Help
To see a list of available CI bot commands, please comment
/bot help.Dev Engineer Review
DFlashWorker._advance_ctx_lenincrements and clamps context lengths, then resets the dummy slot to zero.prepare_1st_drafter_inputsuses this helper, keeping the reset in the drafting step and avoiding dummy-slot writes inprepare(). The change also applies after the Kimi K3 fused context-K/V kernel. No public API changes are reported.QA Engineer Review
Added three CUDA-gated tests in
test_dflash_dummy_slot.py. They cover padded-slot mapping and repeated advances, dummy-slot reset during captured CUDA-graph replay, andprepare()writing only evicted slots. The file is included by thehw_agnostictest-list entry inl0_h100.yml;l0_cpu.ymlalso selects the suite, but these tests skip when CUDA is unavailable. Coverage verdict: sufficient for the dummy-slot reset behavior. Test execution status is not established by the supplied evidence.Per-File QA Perspective
tensorrt_llm/_torch/speculative/dflash.py: Verify that real request context lengths still advance and clamp correctly, while the dummy slot resets after the drafting-step update, including the fused context-K/V path.tests/unittest/_torch/speculative/hw_agnostic/test_dflash_dummy_slot.py: Covers padding, captured-graph replay, and eviction-only writes inprepare(). Thehw_agnosticsuite is selected byl0_h100.ymlandl0_cpu.yml; CUDA-unavailable runs skip these tests.