UCT/RC: Preserve pending order for multi-credit SGL puts - #11841
UCT/RC: Preserve pending order for multi-credit SGL puts#11841michal-shalev wants to merge 9 commits into
Conversation
|
🤖 Starting review — findings will be posted here when done. |
f20e507 to
f44378a
Compare
|
Behavioral scope beyond Test coverage note: The new |
|
🤖 Starting review — findings will be posted here when done. |
|
minor: in_pending could be a UCT_RC_EP_FLAG_* bit in the existing
The new put_am_pending test shares one sgl_ctx/local/remote/param across all worker threads and issues on the same ep under MULTI_THREAD_WORKER. That is safe (read-only SGL contents, MT worker mode), but since there is no data verification and no direct ordering assertion, the test only catches crashes/asserts/errors — it will not detect silent ordering violations. |
flags is already a full uint8_t (bits 0-4 ep state, 5-7 FC AM header). No spare bit without widening, which does not save space vs a dedicated
Correct, it is a debug-assert reproducer, not a payload/FIFO checker. The invariant is UCT QP order. Checking PUT data before AM would close the race the test is meant to hit. |
|
🤖 Starting review — findings will be posted here when done. |
|
🤖 CI Triage Agent — [incomplete: stop_reason=max_tokens] |
|
🤖 Starting review — findings will be posted here when done. |
|
🤖 Starting review — findings will be posted here when done. |
|
🤖 Review complete — no issues found. |
|
🤖 Starting review — findings will be posted here when done. |
|
🤖 Review complete — no issues found. |
|
🤖 CI Triage Agent — TL;DR: Full analysisSummary: gtest step failed with 2 failures — Root cause: Implicated commit: [REDACTED:Hex High Entropy String] — "UCT/RC: Block sends only when pending is queued" (Michal Shalev); builds on f44378a "UCT/RC: Preserve pending order for multi-credit SGL puts" File: src/uct/ib/rc/base/rc_ep.h:108-115 (pending check added at line 109); test assertion at test/gtest/uct/ib/test_rc.cc:959 Suggested fix: Drop Related: PR #11841 (this PR), #11677 (put_sgl_zcopy implementation), #11361 (per-EP
|
|
🤖 Starting review — findings will be posted here when done. |
| uint16_t cq_reserve; | ||
| uint8_t path_index; | ||
| uint8_t flags; | ||
| uint8_t in_pending; |
There was a problem hiding this comment.
The iface already tracks dispatch state via iface->tx.in_pending, set around the very same callback in uct_rc_iface_invoke_pending_cb(). The new per-ep ep->in_pending (set/cleared in uct_rc_ep_process_pending around that same call) is redundant with it — pending dispatch is one-request-at-a-time per iface. Suggestion: can we reuse iface->tx.in_pending here instead of adding a per-ep byte? Today it's #if UCS_ENABLE_ASSERT only, so it'd need to be compiled unconditionally and UCT_RC_EP_MUST_BLOCK_SEND would read it via the iface. This avoids growing every rc_ep. This is a soft suggestion; if there's a reason per-ep granularity is needed (e.g., nested dispatch across ifaces), it's fine to keep as-is.
There was a problem hiding this comment.
iface->tx.in_pending is iface-wide and not refcounted, so it would allow other eps on the same iface to skip their pending queue during this callback (and break under nested dispatch).
| ucs_status_t status; | ||
|
|
||
| status = uct_rc_iface_invoke_pending_cb(iface, req); | ||
| ep->in_pending = 1; |
There was a problem hiding this comment.
The new per-ep ep->in_pending set here is redundant with iface->tx.in_pending, which is set around the same callback in uct_rc_iface_invoke_pending_cb(). Consider reusing the iface-level state instead of a per-ep field.
|
Note (no action required): The Note (no action required): |
| uint16_t cq_reserve; | ||
| uint8_t path_index; | ||
| uint8_t flags; | ||
| uint8_t in_pending; |
There was a problem hiding this comment.
can it be just a new flag?
There was a problem hiding this comment.
ep->flags is already a full uint8_t (bits 0–4 local, 5–7 FC AM header). Adding this would need a 16-bit flags field and would mix dispatch state with bits that go on the wire, so a separate in_pending is cleaner.
brminich
left a comment
There was a problem hiding this comment.
should we check that we have max_put_sgl credits on the qp for all operations?
| enable_entity(m_e2); | ||
| set_tx_moderation(m_e2, 0); | ||
| EXPECT_EQ(UCS_OK, uct_ep_put_short(m_e2->ep(0), NULL, 0, 0, 0)); | ||
| uct_rc_iface_arbiter_dispatch(rc_iface(m_e2)); |
There was a problem hiding this comment.
can we avoid direct call of arbiter dispatch but trigger it with some message instead?
There was a problem hiding this comment.
A user send is blocked while the FC grant is queued (that was the old put_short hack), dispatching the arbiter after enable_entity is the same pattern as test_rc_keepalive.
| #include <uct/ib/rc/verbs/rc_verbs.h> | ||
| #include <uct/test_peer_failure.h> | ||
|
|
||
| extern "C" { |
There was a problem hiding this comment.
it seems this is redundant include
Each op should only check the credits it needs, requiring |
|
🤖 Starting review — findings will be posted here when done. |
|
🤖 Review complete — no issues found. |
|
🤖 Starting review — findings will be posted here when done. |
|
🤖 Review complete — no issues found. |
can we require max_put_sgl credits to be available for each op, but every op will take just the credits it needs. This way just max_put_sgl may be idle at max which is not that big. |
|
|
🤖 Starting review — findings will be posted here when done. |
|
🤖 Review complete — no issues found. |
What?
Enforce FIFO ordering for RC pending operations on all send paths (PUT/GET/AM/atomic/flush/keepalive).
Previously, a new send could be posted while the EP already had a pending request:
Why?
CHECK_RESdid not check the pending queue.For example, SGL PUT may return
NO_RESOURCEwhile some credits are still available because it needscountWQEs. A later 1-credit AM could still pass the resource check and be posted before the pending SGL.How?
Block new sends when the EP has a queued pending request. The EP's pending callback is allowed to retry its operation.
pending_addalso respects reserved credits so multi-credit operations can be queued correctly.