Repository navigation
Conversation
|
🤖 Starting review — findings will be posted here when done. |
| @@ -50,14 +50,14 @@ UCS_TEST_F(test_obj_size, size) { | |||
| UCS_TEST_SKIP_R("Assert enabled"); | |||
There was a problem hiding this comment.
ucp_ep_ext_t grows 216->256 and ucp_request_t 272->280. Given the compactness guidance, consider whether fence_status (ucs_status_t) and the uint8_t fence_pending_scheduled can be packed, and whether lane_generation/fence_seq both need to be 64-bit, to limit per-ep growth.
|
PR Size limit exceeded: REVIEW.md sets a hard 500 added-line limit, but this PR is well over that, spanning ucp_ep.c (~180 lines), flush.c, ucp_request.h, rma.h (~55), ucp_ep.h/.inl, and ~470 lines of new tests. It also bundles several independent changes: (1) lane-generation tracking + ucp_ep_set_lane no-op guard + memset init refactor, (2) selective-lane flush (ucp_ep_flush_lanes_internal, lane_mask) and the flush lane-state helper, (3) request-struct union reorg moving rma/amo under a shared fence union, and (4) the async fence pending-queue state machine. Per guidance ('Feature PRs must not refactor code unrelated to the feature'; 'Refactoring must be in a separate PR'), please split at minimum the lane-generation/set_lane refactor and the request-struct reorg into their own PRs, and land the async-fence machinery separately from the selective-flush primitive. Dead production code: the new async-fence entry points appear to have no production caller — ucp_ep_fence_strong_nb, ucp_ep_fence_pending_add, ucp_ep_fence_pending_resume, UCP_STATUS_FENCE_DEFER, and UCP_REQUEST_FLAG_FENCE_BLOCKED are only exercised by the new gtests (only ucp_ep_fence_pending_purge is wired into ucp_ep_reqs_purge). REVIEW.md's compactness rule says to avoid adding code that isn't used. Is there a follow-up caller planned, or should the enqueue/dispatch path land together with its user? Please clarify intent in the description, or drop the currently-unreachable paths. Test-only aliasing risk: the new tests build fence requests on the stack and set req->send.state.completed_size, then feed them through the fence dispatch path, while real flush requests use the overlapping req->send.state.uct_comp in the same union. This works only because the synthetic requests never take the flush path, but it couples the tests to the current union layout; a short comment noting that these are deliberately non-flush requests would help future maintainers. Coverage note: the async-fence dispatch path has no production caller yet, so there is no end-to-end/integration coverage of it under real transports and failover. The new logic is otherwise covered by focused gtests for the flush lane-state helper, selective flush, lane generation, and the fence pending queue. Worth confirming end-to-end coverage before it ships as a live path. |
|
🤖 CI Triage Agent — TL;DR: The "roce on worker 1" job didn't fail on any test or compile error — the Azure Pipelines agent on Full analysisSummary: Job Root cause: Infrastructure, not code. The log shows a clean, continuously progressing build:
followed by Implicated commit: none — not a code regression. (The failure is unrelated to [REDACTED:Hex High Entropy String].) File: n/a — build was killed while compiling Suggested fix: Re-trigger the Related: none found — searches for the agent-shutdown signature and for this job name returned no matching issues or PRs in openucx/ucx.
|
Add an epoch-ordered per-endpoint queue and progress callback that can advance a fence with a selective remote flush before retrying blocked work. Track the in-flight flush explicitly and purge queued requests on terminal errors. Overlay the new fence metadata with the existing RMA and atomic request storage through an anonymous union. This preserves the established send.rma and send.amo field names and limits the request size increase to eight bytes. Signed-off-by: Nathan Bellalou <nbellalou@nvidia.com>
96defc2 to
fc656d5
Compare
|
🤖 Starting review — findings will be posted here when done. |
| return UCS_OK; | ||
| } | ||
|
|
||
| flush_req = (ucp_request_t*)request - 1; |
There was a problem hiding this comment.
blocker: the flushed callback can be invoked synchronously from ucp_ep_flush_lanes_internal() (ucp_ep_flush_is_completed() -> ucp_ep_flush_mem_start() -> ucp_ep_flush_mem_progress() -> flushed_cb) when ep->ext->flush_sys_dev_map != 0, while mem_start() still returns UCS_INPROGRESS so a valid-looking req + 1 is returned. In that flow the callback already did ucp_request_put(req) and its assert fires (fence_inflight_req is still NULL); here we then write flush_req->send.flush.fence_seq into freed memory and store a dangling fence_inflight_req that blocks the pending queue forever.
| ep->ext->fence_status = status; | ||
|
|
||
| if (ucs_likely(status == UCS_OK)) { | ||
| ep->ext->unflushed_lanes = 0; |
There was a problem hiding this comment.
ep->ext->unflushed_lanes = 0 in the async completion callback also clears lanes that got dirty after the flush started, while only req->send.flush.lane_mask was actually flushed, so a later fence can skip or weak-fence those lanes; pls clear just the flushed subset (ep->ext->unflushed_lanes &= ~req->send.flush.lane_mask).
| #define ucp_trace_req(_sreq, _message, ...) \ | ||
| ucs_trace_req("req %p: " _message, (_sreq), ## __VA_ARGS__) | ||
|
|
||
| #define UCP_STATUS_FENCE_DEFER ((ucs_status_t)(UCS_ERR_LAST + 1)) |
There was a problem hiding this comment.
UCP_STATUS_FENCE_DEFER (UCS_ERR_LAST + 1 = -99) is inside the ucs_status_t error range, so UCS_STATUS_IS_ERR() treats it as a real error and ucs_status_string() cannot name it; if a deferring progress function is reached from ucp_request_try_send() (the regular RMA/AMO send path) or from a UCT pending callback we get ucs_fatal("unexpected error"). Can we use a request flag or an explicit out-param instead of a fake status?
| ep->ext->fence_status = UCS_INPROGRESS; | ||
| ucp_ep_refcount_add(ep, flush); | ||
|
|
||
| request = ucp_ep_flush_lanes_internal(ep, UCP_REQUEST_FLAG_RELEASED, |
There was a problem hiding this comment.
How is the lane_mask contract from the ucp_ep_flush_lanes_internal() doc kept here ("defer new such writes on excluded lanes until this flush completes")? While this flush is in flight, non-fenced ops can still write on lanes outside the snapshot, and the mem flush will consume/clear flush_sys_dev_map for them.
|
|
||
| ucs_queue_head_t fence_pending_q; /* Fence-blocked requests */ | ||
| ucp_request_t *fence_inflight_req; /* Active fence flush */ | ||
| ucs_status_t fence_status; /* Current/last flush status */ |
There was a problem hiding this comment.
minor: fence_status looks redundant (effectively write-only) - its only read (fence_status == UCS_OK in ucp_ep_fence_try_advance_epoch()) is reachable only right after a synchronous completion where it is always UCS_OK; dropping it would also shrink ucp_ep_ext_t.
| EXPECT_EQ(UCS_INPROGRESS, ep->ext->fence_status); | ||
| EXPECT_NE(fence_seq, ep->ext->fence_seq); | ||
|
|
||
| ASSERT_NE(static_cast<uct_completion_t*>(NULL), test_flush_comp); |
There was a problem hiding this comment.
A failed ASSERT_NE inside the critical section returns from the test with the worker lock still held and iface->ops.ep_flush still pointing to the test stub, which breaks all following tests in the process; pls restore the ops and exit the CS before asserting (or use EXPECT_* with explicit cleanup).
| return 0; | ||
| } | ||
|
|
||
| if (ucs_unlikely((status != UCS_OK) && UCS_STATUS_IS_ERR(status))) { |
There was a problem hiding this comment.
minor: (status != UCS_OK) && UCS_STATUS_IS_ERR(status) is redundant since UCS_OK == 0 can never satisfy UCS_STATUS_IS_ERR(). Suggestion:
| if (ucs_unlikely((status != UCS_OK) && UCS_STATUS_IS_ERR(status))) { | |
| if (ucs_unlikely(UCS_STATUS_IS_ERR(status))) { |
|
Residual coverage gap: the inline-completion path ( |
|
🤖 CI Triage Agent — TL;DR: The Coverity gate failed with 4 new defects — all in Full analysisSummary: Azure "Coverity coverity devel on coverity_rh7" job exited non-zero: Root cause: Pure static-analysis gate failure (no runtime/test failure, no hang — the log shows the Coverity analysis completing and
Implicated commit: [REDACTED:Hex High Entropy String] — Nathan Bellalou, "UCP/FENCE: Add asynchronous endpoint fence engine" (the PR head commit; it is the only recent change to this file) File: Suggested fix: Restructure the critical section in
class scoped_worker_cs {
public:
scoped_worker_cs(ucp_worker_h w) : m_worker(w) {
UCP_WORKER_THREAD_CS_ENTER_CONDITIONAL(m_worker);
}
~scoped_worker_cs() {
UCP_WORKER_THREAD_CS_EXIT_CONDITIONAL(m_worker);
}
private:
ucp_worker_h m_worker;
};and replace lines 241 / 280 with
uct_completion_t *comp = test_flush_comp;
ASSERT_TRUE(comp != NULL);
if (comp == NULL) {
return; /* guard for static analysis; CS released by RAII guard */
}
uct_invoke_completion(comp, UCS_OK);(Alternatively keep Related: #11923 ("UCP/FLUSH: Add topology-safe selective endpoint flush", closed) appears to be the predecessor in this fence/flush series; no existing issue tracks these Coverity findings.
|
What
Add the asynchronous endpoint-fence engine: a per-endpoint queue of deferred requests, a single in-flight strong fence, and ordered fence epochs. This PR does not enable the asynchronous endpoint fence yet
Why
This is Part 2 of 5 of an updated split of the earlier endpoint-fence PR #11199.
This PR deliberately prepares and tests the engine before ordinary RMA and atomic requests use it. Keeping lifecycle, ordering, error handling, and request deferral separate makes that machinery independently reviewable; Part 4 will activate it for the normal data path.
How
Draft — merge only after PR #11923 is merged.