Repository navigation
UCP/RMA: Add SGL support to ucp_get_nbx - #12191
michal-shalev wants to merge 27 commits into
Conversation
|
🤖 Starting review — findings will be posted here when done. |
|
Not raised (checked and fine):
|
|
🤖 Starting review — findings will be posted here when done. |
|
the diff adds ~600 lines, above the 500-line limit. can the mechanical part — extracting Checked and not raised:
Residual coverage gaps:
|
|
🤖 Starting review — findings will be posted here when done. |
|
Residual coverage gap: no test forces Residual coverage gap: no test covers Residual coverage gap: the |
|
🤖 CI Triage Agent — TL;DR: The newly added gtest Full analysisSummary: 1 of 4108 gtests failed — Root cause: The test (added in the PR's top commit) runs with
The sibling tests are guarded and therefore pass everywhere: Implicated commit: [REDACTED:Hex High Entropy String] — "UCP/TEST: Add GET SGL short element layout and failure tests", Michal Shalev (feature it tests: 1310a95, same author) File: test/gtest/ucp/test_ucp_rma.cc:1905-1947 (test body), test_ucp_rma.cc:1911 + :1524 (first failing assert); related: src/ucp/rma/get_offload.c:280-285, src/ucp/proto/proto_multi.c:879-885 Suggested fix: Guard
Also make the leading Related: PR #12191 (this branch,
|
|
🤖 Starting review — findings will be posted here when done. |
|
🤖 CI Triage Agent — TL;DR: The Coverity gate failed with 4 new FORWARD_NULL defects caused by the new static callback Full analysisSummary: Root cause: Not a build/test failure — a static-analysis regression introduced by this PR. static void ucp_proto_get_sgl_short_elem_completion(void *request, ucs_status_t status, void *user_data)
{
ucp_request_t *req = user_data;
ucp_request_free(request);
ucp_invoke_uct_completion(&req->send.state.uct_comp, status); /* unconditional deref */
}It is assigned to
Coverity therefore reports NULL Implicated commit: PR #12191 branch File: Suggested fix: Make the NULL impossibility explicit so Coverity prunes the modeled path. static void ucp_proto_get_sgl_short_elem_completion(void *request, ucs_status_t status, void *user_data)
{
ucp_request_t *req = user_data;
ucs_assert(req != NULL);
ucp_request_free(request);
ucp_invoke_uct_completion(&req->send.state.uct_comp, status);
}Alternatives if the assert is not sufficient: (a) annotate the modeled call with Related: PR #12191 (this PR). No pre-existing issue found for this Coverity signature.
|
|
🤖 Starting review — findings will be posted here when done. |
|
🤖 CI Triage Agent — TL;DR: The new gtest Full analysisSummary: Root cause: From the backtrace, the completion was invoked by The only code exercised exclusively by this test is the new short-element path:
Nothing protects the parent from being completed/freed while those sub-request references are outstanding: if Implicated commit: File: Suggested fix:
Related: PR #12191 (this PR, "UCP/RMA: Add SGL support to ucp_get_nbx"); flush accounting context in PR #11923 ("UCP/FLUSH: Add topology-safe selective endpoint flush"); UCT side already merged in #11763 ("UCT/IB/MLX5/RC: Implement get_sgl_zcopy") |
|
🤖 Starting review — findings will be posted here when done. |
|
🤖 CI Triage Agent — TL;DR: The centos7 Full analysisSummary: Root cause: On the CentOS 7 image (old GCC, are written before use. They are filled by
This is a false positive from the old compiler, not a real logic bug — but Implicated commit: [REDACTED:Hex High Entropy String] (Michal Shalev, merge of File: src/ucp/proto/proto_multi.inl:417-419 (triggered from src/ucp/rma/get_offload.c:340,353 and src/ucp/rma/put_offload.c:460) Suggested fix: Give the compiler a definite initialization at the declarations in void *buffers[UCP_MAX_IOV] = {NULL};
size_t lengths[UCP_MAX_IOV] = {0};
uint64_t remote_addrs[UCP_MAX_IOV] = {0};Only the first element is strictly needed for the Related: PR #12191 (
|
| ucs_status_t status; | ||
|
|
||
| ++req->send.state.uct_comp.count; | ||
| status_ptr = ucp_get_nbx(req->send.ep, buffer, length, remote_addr, |
There was a problem hiding this comment.
A short element falls back to a full nested UCP request per element: parameter checks, protocol selection, memory detection and registration, plus a request from the mpool. That is the dominant cost exactly in the many-small-elements case this protocol targets (many_short_elements posts 1024, various_counts up to 4096). Can we post the short element on the same lane with the parent's uct_comp instead (e.g. uct_ep_get_bcopy like get/bcopy does), or at least pass the element's memh so it is not re-registered?
| .middle.lane_type = UCP_LANE_TYPE_RMA_BW, | ||
| .opt_align_offs = UCP_PROTO_COMMON_OFFSET_INVALID | ||
| .opt_align_offs = UCP_PROTO_COMMON_OFFSET_INVALID, | ||
| .min_sgl_frag_offs = is_sgl ? min_zcopy_offs : |
There was a problem hiding this comment.
This relies on cap.get.min_zcopy applying to every SGL element, but uct_ep_get_sgl_zcopy only documents the count limit. Please document the per-element minimum length in uct_v2.h, so the transports and this protocol agree on the contract.
|
Residual coverage gap: no test forces Residual coverage gap: no test covers
PR size is above the 500-added-line limit; the split request was already made in a previous round, so not repeated. |
|
🤖 CI Triage Agent — TL;DR: The CentOS 7 (gcc 4.8) Full analysisSummary: Compilation of Root cause: In Implicated commit: File: Suggested fix: Drop the /* Silence old-compiler maybe-uninitialized warning: the arrays are filled
* by ucp_datatype_iter_next_sgl_frags() when frag_count > 0 */
buffers[0] = NULL;
lengths[0] = 0;
remote_addrs[0] = 0;
ucs_assert(max_frag_count <= UCP_MAX_IOV);
ucs_assert((adjust_func == NULL) || (max_frag_count == 1));(Equivalently, declare them as Related: PR #12191 (branch
|
|
🤖 Starting review — findings will be posted here when done. |
|
|
||
| static void get_test_variants(std::vector<ucp_test_variant>& variants) { | ||
| static const char *op_names[] = {"put", "get"}; | ||
| add_variant_values(variants, get_memtype_variants, UCS_MASK(2), |
There was a problem hiding this comment.
minor: this doubles ~20 parameter-validation tests (invalid_rkey, missing_remote_*, memhs_*, rkeys_*, count_mismatch, ...) that all exercise the same UCP_RMA_SGL_CHECK_PARAMS macro, times 2 memory types times every TL instantiation. maybe keep them put-only with require_put() and leave one get case to verify ucp_get_nbx wires the checks in?
|
Previously raised, still open: PR size is above the 500-added-line limit / split request. Previously raised, still open: no coverage for Previously raised, still open: Residual gap: a short element recurses into full protocol selection, so on GPU memory without GPUDirect each 8-byte element becomes a rendezvous operation — the same path the Residual gap: for interleaved long/short element patterns the offload path posts one UCT op per long run plus one nested UCP request per short element; no test measures or bounds that behavior. |
|
🤖 CI Triage Agent — TL;DR: The aarch64 build fails with Full analysisSummary: Root cause: In
The block at proto_multi.inl:429-435 exists precisely to silence this class of warning for the Implicated commit: File: Suggested fix: Complete the silencing block in if (max_frag_count == 1) {
/* Silence compiler warning, a single fragment is read by the adjust
* and post functions */
buffers[0] = NULL;
lengths[0] = 0;
remote_addrs[0] = 0;
elem_indices[0] = 0; /* <-- add this */
}Note the two reads are reached from different paths ( Related: PR #12191 (branch |
|
🤖 Starting review — findings will be posted here when done. |
| @@ -381,4 +381,194 @@ ucp_proto_multi_rma_init_func(ucp_request_t *req) | |||
| return ucp_ep_rma_handle_fence(req->send.ep, req, mpriv->lane_map); | |||
There was a problem hiding this comment.
these helpers are RMA-SGL specific (req->send.rma.sgl, dt_iter->type.sgl) and are only used by put_offload.c/get_offload.c, but proto_multi.inl is also included by the AM, tag, stream and rndv protocols. can they live in src/ucp/rma/rma_sgl.inl (or rma.inl) instead, so the generic multi-lane header does not need to know the RMA request layout?
|
PR size is above the 500-added-line limit — please consider splitting it. No coverage for No test forces
No |
|
🤖 CI Triage Agent — TL;DR: The new Full analysisSummary: gtest job "roce on worker 0" aborted (core dumped, Root cause: From the log, the failure is a hard assertion, not a timeout (progress is continuous up to the abort; the later timestamps are only the crash handler printing the backtrace): A UCP EP‑flush request counts exactly one UCT completion per lane whose Everything in this path is new in this PR (branch /* src/ucp/rma/get_offload.c:301-328 */
++req->send.state.uct_comp.count;
status_ptr = ucp_get_nbx(req->send.ep, buffer, length, remote_addr, ...);
if (UCS_PTR_IS_PTR(status_ptr)) return UCS_INPROGRESS;
--req->send.state.uct_comp.count; /* immediate completion */and that /* src/ucp/proto/proto_multi.inl:446-452 */
status = adjust_func(req, lpriv, elem_indices[0], &buffers[0], &lengths[0], &remote_addrs[0]);
if (ucs_unlikely(status != UCS_OK))
return (status == UCS_INPROGRESS) ? UCS_OK : status; /* vs. ucp_proto_multi_progress(): UCS_OK => no ++count */The 1‑byte trailing element goes through this sub‑request path and is posted as a tiny RDMA READ, which is exactly why the completing CQE is an inline‑scatter one ( Implicated commit: File: Suggested fix:
Related: PR #12191 (this PR); feature predecessors #11763 ( |
|
Hi @michal-shalev, thanks for this. We run SGL gets in production for NIXL KV-cache reads (on our own UCX patch) and tested this PR at 1187eaa on B300 with rc_mlx5:
Are you planning the NIXL side (READs through sglXfer, like ai-dynamo/nixl#1835)? If not, we have it drafted against this branch and can send it. |
What?
Add SGL datatype support to
ucp_get_nbx: newget/sgl/offloadandget/sgl/offload_swprotocols, param validation, and gtests (SGL tests now run for both put and get).Why?
Completes SGL RMA at the UCP level. UCT
get_sgl_zcopywas added in #11763, and put SGL already exists.How?
Mirrors the put SGL protocols.