Repository navigation
[Bugfix][NIXL] Fix multiple handles xfer race - #56104
Conversation
|
/ci run |
|
✅ Triggered Buildkite CI #87944 for commit |
|
Thanks @NickLucche! I think this change may introduce some problems on the push side though, will add more detail soon. |
|
This pull request has merge conflicts that must be resolved before it can be |
njhill
left a comment
There was a problem hiding this comment.
Thanks @NickLucche.
Also here are tests you could include to cover the push mode changes fixed by the inline suggestion: njhill@4143de0
| self, | ||
| req_id: str, | ||
| handle: int | None, | ||
| failed_req_ids: set[str] | None = None, |
There was a problem hiding this comment.
nit:
| self, | |
| req_id: str, | |
| handle: int | None, | |
| failed_req_ids: set[str] | None = None, | |
| self, req_id: str, handle: int | None, failed_req_ids: set[str] | None = None |
| if not self._handle_failed_transfer( | ||
| request_id, handle, self._recv_failures | ||
| ): | ||
| assert handle is not None |
| # writer thread also appends to it, so guard the pop. | ||
| with self._sending_transfers_lock: | ||
| done_pushing = self._pop_done_transfers(self._sending_transfers) | ||
| done_pushing, _ = self._pop_done_transfers(self._sending_transfers) |
There was a problem hiding this comment.
| done_pushing, _ = self._pop_done_transfers(self._sending_transfers) | |
| done_pushing, failed_pushing = self._pop_done_transfers( | |
| self._sending_transfers | |
| ) | |
| # A failed send must never be reported as done: its blocks | |
| # are freed via the lease / watchdog instead. | |
| done_pushing = { | |
| req_id | |
| for req_id in done_pushing - failed_pushing | |
| if req_id in self._recving_metadata | |
| } |
Otherwise failed sends could be reported as succesful (done_sending) and successful sends could complete early at write handle time bypassing the consumer notif accounting.
231c1de to
551a9db
Compare
|
/ci run |
|
✅ Triggered Buildkite CI #88324 for commit |
551a9db to
47f5a96
Compare
|
/ci run |
|
✅ Triggered Buildkite CI #88336 for commit |
47f5a96 to
c551acb
Compare
|
/ci run |
|
Thanks for reviewing @njhill , added your push fix |
|
/ci run |
|
✅ Triggered Buildkite CI #88377 for commit |
|
This pull request has merge conflicts that must be resolved before it can be |
| if handle is not None and not self._handle_failed_transfer( | ||
| request_id, handle, self._recv_failures | ||
| ): |
There was a problem hiding this comment.
| if handle is not None and not self._handle_failed_transfer( | |
| request_id, handle, self._recv_failures | |
| ): | |
| if not self._handle_failed_transfer( | |
| request_id, handle, self._recv_failures | |
| ): | |
| assert handle is not None |
@NickLucche my bad I think this was my incorrect prior suggestion. This should fix the test ^^
There was a problem hiding this comment.
I would have pushed this but don't have permission for your branch.
There was a problem hiding this comment.
@njhill sorry about that, I'll look into branch permissions
In get_finished, filter popped write-transfer req_ids against failed_pushing and _recving_metadata: a failed send must never be reported as done (its blocks are freed via the lease / watchdog), and a successful send still waits for the consumer notification instead of completing at write-handle time. Also apply review nits (collapse _handle_failed_transfer signature, drop the redundant assert in pull_worker by folding the handle check into the condition) and adapt two tests from njhill's review branch covering the failed-send and consumer-notif cases. Generated by Mistral Vibe. Co-Authored-By: Mistral Vibe <vibe@mistral.ai> Signed-off-by: NickLucche <nicolo.lucchesi@mistral.ai> Co-authored-by: Nick Hill <nickhill123@gmail.com>
Always record setup failures, including when make_prepped_xfer raises before returning a handle. Retain a handle only when releasing it fails. Co-authored-by: OpenAI Codex <noreply@openai.com> Signed-off-by: NickLucche <nicolo.lucchesi@mistral.ai>
Assert delayed receive failures through get_transfer_results, initialize the push stub for direct receive synchronization, and keep the upstream push failure test consistent with the reviewed lease/watchdog behavior. Validation: all 48 push tests and five focused receive lifecycle tests pass; pre-commit passes on all five PR files. The setup-failure test is blocked on macOS because CPU_ATTN rejects its block size of 16. Co-authored-by: OpenAI Codex <noreply@openai.com> Signed-off-by: NickLucche <nicolo.lucchesi@mistral.ai>
c551acb to
7ce48f9
Compare
|
/ci run |
|
✅ Triggered Buildkite CI #88801 for commit |
|
/ci run |
|
✅ CI is already running for this commit: https://buildkite.com/vllm/ci/builds/88801 |
|
Not sure what is going on with the CI here :( |
|
/ci cancel |
|
/ci run --allow-stale |
|
✅ Triggered Buildkite CI #89004 for commit
|
Signed-off-by: NickLucche <nicolo.lucchesi@mistral.ai> Co-authored-by: Nick Hill <nickhill123@gmail.com>
Signed-off-by: NickLucche <nicolo.lucchesi@mistral.ai> Co-authored-by: Nick Hill <nickhill123@gmail.com>
A request can own multiple in-flight NIXL transfer handles (one per remote TP rank under heterogeneous TP).
On
main, the first handle to reachERRimmediately invalidates the request's blocks and reports the failure to the scheduler, while the sibling handles may still be posting RDMA writes into those same blocks.Posted transfers cannot be aborted, so once the scheduler reassigns the blocks, the in-flight writes corrupt whichever request owns them next.
This PR fixes this race by deferring NIXL receive-failure reporting and block invalidation until all transfers for the request have stopped, preventing in-flight RDMA writes from corrupting reused KV blocks.
Some cascading changes to keep purpose of data structures clear:
_failed_recv_reqsQ to report failures_recv_failuresset to minimize overhead_failed_recv_reqsQ failures are addressed inget_finished;_pop_done_transfersalso returns current poll failures, so we can track them and check whether all handles have been processed (or we delay, bulk of this PR)