Repository navigation
[NIXL][PCP] Report replicated-PCP ranks > 0 as done sending instead of hiding them - #53903
NickLucche merged 4 commits into
Conversation
…f hiding them With replicated KV under PCP only PCP rank 0 takes part in transfers, so NixlConnector ranks > 0 cleared `done_sending` and `get_finished_count` was lowered to TP x PP so the scheduler only waited for rank 0. That breaks as soon as NixlConnector is wrapped in a MultiConnector with a sibling that saves on every rank (e.g. OffloadingConnector): * `MultiConnector.get_finished_count` returns None when any child returns None, so the aggregator expects `world_size` finishes per request; * `MultiConnector` records an extra async save per request and only reports it finished once *every* child on that worker has, and NIXL on ranks > 0 never does. Requests therefore never finish sending, their blocks are never freed and the prefill engine stalls at 0 running / N waiting with the KV cache full (observed with GLM-5.2 PCP8 prefill + NIXL + CPU offloading). Fix: ranks > 0 report the requests they are asked to send as finished as soon as the connector metadata arrives, and the finished count is back to `world_size`. Rank 0 still reports only when the consumer has actually read the blocks, so the aggregate completes exactly when it did before. Signed-off-by: Lucas Wilkinson <lwilkinson@neuralmagic.com>
…ng instead of hiding them With replicated KV under PCP only PCP rank 0 takes part in transfers, so NixlConnector ranks > 0 cleared `done_sending` and `get_finished_count` was lowered to TP x PP so the scheduler only waited for rank 0. That breaks as soon as NixlConnector is wrapped in a MultiConnector with a sibling that saves on every rank (e.g. OffloadingConnector): * `MultiConnector.get_finished_count` returns None when any child returns None, so the aggregator expects `world_size` finishes per request; * `MultiConnector` records an extra async save per request and only reports it finished once *every* child on that worker has, and NIXL on ranks > 0 never does. Requests therefore never finish sending, their blocks are never freed and the prefill engine stalls at 0 running / N waiting with the KV cache full (observed with GLM-5.2 PCP8 prefill + NIXL + CPU offloading). Fix: ranks > 0 report the requests they are asked to send as finished as soon as the connector metadata arrives, and the finished count is back to `world_size`. Rank 0 still reports only when the consumer has actually read the blocks, so the aggregate completes exactly when it did before. Signed-off-by: Lucas Wilkinson <lwilkinson@neuralmagic.com>
NickLucche
left a comment
There was a problem hiding this comment.
Agree semantics of _expected_finished_count is a bit weird here, but at least it's not particularly inefficient as we have to poll from the worker anyway due to offloading.
I left some comments about unifying the _replicated_pcp_done_sending file change @LucasWilkinson
Co-authored-by: Nicolò Lucchesi <nicolo.lucchesi@gmail.com> Signed-off-by: Lucas Wilkinson <LucasWilkinson@users.noreply.github.com>
|
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 (3)
Included review availability: Your plan provides up to 10 included reviews per hour; 9 remain after this review. 📝 SummarySummary by CodeRabbit
WalkthroughThe NIXL connector now tracks requests skipped by replicated PCP ranks and reports them as finished. It also removes the fixed completion count for multi-PCP KV producers. ChangesReplicated PCP completion reporting
Estimated code review effort: 2 (Simple) | ~10 minutes Merge Risk: ⚪ Minimal · up to Replicated PCP ranks now report skipped KV sends as complete, allowing multi-connector requests to finish and KV blocks to be freed without changing rank-0 transfer completion behavior. No concrete current-head merge risk remains. Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
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 |
Co-authored-by: OpenAI Codex <codex@openai.com> Signed-off-by: Lucas Wilkinson <lwilkins@redhat.com>
|
/ci run |
|
✅ Triggered Buildkite CI #88052 for commit |
…f hiding them (vllm-project#53903) Signed-off-by: Lucas Wilkinson <lwilkinson@neuralmagic.com> Signed-off-by: Lucas Wilkinson <LucasWilkinson@users.noreply.github.com> Signed-off-by: Lucas Wilkinson <lwilkins@redhat.com> Co-authored-by: Nicolò Lucchesi <nicolo.lucchesi@mistral.ai> Signed-off-by: Jyotirmoy Roy <jyotirmoyroy649@gmail.com>
Purpose
With replicated KV under PCP only PCP rank 0 takes part in NIXL transfers, so
NixlConnectoron ranks > 0 cleareddone_sendingandget_finished_count()was lowered toTP x PPso the scheduler only waited for rank 0.That breaks as soon as
NixlConnectoris wrapped in aMultiConnectorwith a sibling that saves on every rank (e.g.OffloadingConnector):MultiConnector.get_finished_count()returnsNonewhen any child returnsNone, so theKVOutputAggregatorexpectsworld_sizefinishes per request;MultiConnectorrecords an extra async save per request and only reports it finished once every child on that worker has — and NIXL on ranks > 0 never does.Requests therefore never finish sending, their blocks are never freed and the prefill engine stalls at
Running: 0 reqs, Waiting: N reqswith the KV cache full. Observed with GLM-5.2-FP8 PCP8 prefill,MultiConnector = NixlConnector(kv_producer) + OffloadingConnector(TieringOffloadingSpec): 14/35 requests completed at concurrency 16, then nothing.Fix: ranks > 0 report the requests they are asked to send as finished as soon as the connector metadata arrives, and
get_finished_count()is back toworld_size. Rank 0 still reports only when the consumer has read the blocks, so the aggregate completes exactly when it did before.Test Plan
--prefill-context-parallel-size 8+ MultiConnector (NIXL producer + OffloadingConnector), DP8 decode; agentic trace benchmark at concurrency 16/32/64.Test Result
Before: prefill stalls after ~14 requests (0 running / 16 waiting / KV 70%). After: pending — will update with the benchmark run.
🤖 Generated with Claude Code; reviewed by author