[Bugfix][MooncakeStore] Fix finish-time save crash on hybrid models - #54643
Conversation
1fe0f87 to
9132c71
Compare
MultiConnector queries every child but selects only the first cache hit. A losing MooncakeStore lookup therefore leaves a LoadSpec with can_load=False. The pending-load metadata path treated any LoadSpec as actionable and converted the rejected load into a save, using an empty block table on hybrid models and crashing the send thread.\n\nOnly build pending metadata for an accepted load. Normal stores continue to get their block tables from SchedulerOutput after the request is scheduled. Signed-off-by: zhewenl <zhewenl@users.noreply.github.com>
9132c71 to
8ad6f35
Compare
Backport vllm-project#54643 at 8ad6f35. A speculative load rejected by MultiConnector must not create a save outside the scheduled block-table snapshot. Reproduced the exact missing-table assertion before the fix. 427 scheduler, offload, and metric regressions plus the focused override suite pass. Co-authored-by: Codex <noreply@openai.com> Signed-off-by: Cam Quilici <cjquilici@gmail.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Team Run ID: 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (2)
Included review availability: Your plan provides up to 10 included reviews per hour; 9 remain after this review. 📝 SummarySummary by CodeRabbit
WalkthroughThe Mooncake store scheduler now skips pending loads rejected by MultiConnector. A regression test verifies that the losing connector clears allocated blocks, emits no metadata, and removes stale request state. ChangesPending load rejection handling
Estimated code review effort: 2 (Simple) | ~10 minutes Merge Risk: ⚪ Minimal · up to The scheduler now drops rejected pending-load work and clears its stale state, preventing non-selected connectors from emitting metadata or retaining allocations. The targeted regression coverage and reported test results indicate no remaining merge-readiness risk. 🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
Full details: Title checkExplanation The title describes fixing a finish-time save crash on hybrid models, but the summarized changes only tighten pending-load handling for rejected non-chosen connectors and add a regression test. The title does not accurately identify the primary change.
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Note GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer. |
|
/ci run |
|
✅ Triggered Buildkite CI #87487 for commit |
…llm-project#54643) Signed-off-by: zhewenl <zhewenl@users.noreply.github.com> Co-authored-by: zhewenl <zhewenl@users.noreply.github.com> Signed-off-by: Jyotirmoy Roy <jyotirmoyroy649@gmail.com>
What & why
Fixes a crash in
MooncakeStoreConnector's save path on hybrid (multi KV-group) models such as Kimi-K3 (MLA + GDN):Root cause
Under
MultiConnector,update_state_after_allocforwards the realnum_external_tokensonly to the connector that supplied them; every other connector is called with0(multi_connector.py). The store connector used that as a condition to record an empty block-table tuple in_unfinished_requests:The finish-time save path (
scheduler.py, requests that left the schedule with a load spec) rebuilds the request tracker from that stored entry, so the worker's per-group save loop indexed into an empty tuple — on hybrid models with N>1 KV groups this raisesIndexErrorper affected request. Each crash silently drops that request's store save (store pool stays under-populated); single-group models never hit it.Observed live on Kimi-K3 PD + store offload (GB300): 997 crashes in one eval run while ~7 GB of saves still succeeded via the in-schedule path.
Fix
store/scheduler.py::update_state_after_alloc: always record the full-width per-group block table (drop thenum_external_tokens > 0condition). The stored tuple's only consumer is the finish-time save, which needs it regardless of who supplied external tokens.store/worker.py::_handle_request: skip (with a warning) any group the request metadata does not cover, so a malformed entry can never kill the sending thread again.Tests
Live-verified on Kimi-K3 1P1D (TP8) +
MultiConnector(NixlConnector, MooncakeStoreConnector)with a deliberately tiny GPU KV pool (--num-gpu-blocks-override 24) to force store read/write traffic: gsm8k accuracy holds at 0.967 (0 request errors) and the IndexError is gone.AI assistance
Developed with AI assistance (Kimi Code); a human reviewed the diff and ran the tests above.