Repository navigation
Conversation
The V2 scheduler admits an unpaired draft mirror when it schedules an attention-DP pad dummy (_admit_unpaired_draft). When the fleet then vetoes the forward, _finalize_adp_dummy_allocation rolls the dummy back through _free_pad_dummy_kv, which freed the draft pool only when it is paired. The mirror stayed in the draft kv_cache_map under the fixed dummy request ID, and the deferred update_resources of the rank's previous dummy batch then resized it: "ValueError: History length cannot exceed capacity", which kills the DSpark attention-DP gen worker in disaggregated serving. Free the dummy in whichever draft pool exists. Freeing a pool that holds no cache for it is a no-op. Signed-off-by: Zheyu Fu <zheyuf@nvidia.com>
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.
Description
Bug (M3.1 ask 2a). A DSpark attention-DP gen worker in disaggregated serving raises
ValueError: History length cannot exceed capacityfrom the draftKVCacheManagerV2.update_resources→kv_cache.resize. The crash handler then hard-kills every rank.It shows up at gen
max_batch_size2–4 per rank: DEP4 → DEP4 B16 died in all 3 e2e runs. It has never shown up at 16 per rank, on TP gens, or in gen-only runs.Root cause. Rolling back an attention-DP pad dummy leaks the dummy's unpaired draft mirror:
_pad_empty_attention_dp_batchrefuses oncelen(active_requests) >= max_num_active_requests, and requests still receiving KV reach that cap at 2–4 per rank._can_queuethen vetoes the forward on every rank._try_allocate_generation→_admit_unpaired_draft→admit_mirrorcreated a draft mirror for it, at capacity 0._finalize_adp_dummy_allocation(False)frees the dummy through_free_pad_dummy_kv, which frees the draft pool only when it is paired (enable_joint_kv_cache_reuse). With an unpaired pool (UNPAIRED_DRAFT_POOL, the M3.1 DSpark default on Blackwell since 15ffec1), the mirror stays in the draftkv_cache_mapunder the fixed dummy request ID.should_process_previous_batchis False, so the update of the previous batch waits. That batch held the previous dummy.update_resourcesof the old dummy finds the leaked mirror under the same ID and callsresize(None, 3)on a capacity-0 cache, which throws.Small batch sizes fail only because step 1 needs a rank at the pad cap. The draft pool's size plays no part: it never filled up in any crash log.
Fix.
_free_pad_dummy_kvnow frees the dummy in whichever draft pool exists, paired or not. Freeing a pool that holds no cache for the dummy is a no-op, so its other two callers behave as before. Those callers handle a spec-slot failure right after a dummy is created, when an unpaired pool holds nothing for it yet.Test Coverage
test_adp_dummy_rollback_frees_unpaired_draft_mirrorintests/unittest/_torch/executor/test_py_executor.py. CI collects it through theunittest/_torch/executorentry (e.g.l0_cpu.yml).test_forward_step_carries_context_logits_request_to_runner, whoseSimpleNamespacestub lacks_loop_on_execution_stream.tensorrt_llm/_torchon image516f0342cd, which has no compiled files under_torch.516f0342cd, the one in the bug report. That image's rollback freed only the target, so it has the same leak.max_batch_size2 per rank, 1600 requests per run:update_resourcesthat skips dummies. It never fired, so it is not part of this PR.PR Checklist
py_executor.py), and ruff check/format (test file), are clean at the pinned versions (yapf 0.43.0, ruff 0.9.4).🤖 Generated with Claude Code