Skip to content

UCP/RMA: Add AM-based software emulation protocol for SGL put - #11943

Open
michal-shalev wants to merge 8 commits into
openucx:masterfrom
michal-shalev:sgl-put-am-emulation
Open

michal-shalev wants to merge 8 commits into
openucx:masterfrom
michal-shalev:sgl-put-am-emulation

Conversation

@michal-shalev

@michal-shalev michal-shalev commented Sep 13, 2026

Copy link
Copy Markdown
Contributor

What?

Add put/sgl/am/bcopy, an active-message software emulation protocol for SGL put, re-enable the SGL CUDA gtests and add tests that force the new protocol.

Why?

SGL was the only datatype without an emulation fallback, so ucp_put_nbx failed with "cannot find remote protocol" whenever lane selection left no RMA_BW lane (e.g. a cross-socket HCA derated below MULTI_LANE_MAX_RATIO), while contig and IOV fall back to put/am/bcopy in the same configuration.

How?

Reuse ucp_proto_put_am_bcopy_probe and send one AM PUT per SGL element, since each element carries its own remote address, ucp_proto_sw_rma_cfg_thresh keeps it a last resort so hardware SGL protocols are unaffected.

@michal-shalev michal-shalev self-assigned this Sep 13, 2026
@svc-nvidia-pr-review

Copy link
Copy Markdown

🤖 Starting review — findings will be posted here when done.

Comment thread test/gtest/ucp/test_ucp_rma.cc Outdated
Comment thread test/gtest/ucp/test_ucp_rma.cc Outdated
Comment thread test/gtest/ucp/test_ucp_rma.cc
Comment thread src/ucp/rma/put_am.c Outdated
@svc-nvidia-pr-review

Copy link
Copy Markdown

🤖 Starting review — findings will be posted here when done.

Comment thread src/ucp/rma/put_am.c
Comment thread test/gtest/ucp/test_ucp_rma.cc
Comment thread test/gtest/ucp/test_ucp_rma.cc
@svc-nvidia-pr-review

Copy link
Copy Markdown

🤖 Starting review — findings will be posted here when done.

Comment thread test/gtest/ucp/test_ucp_rma.cc
Comment thread src/ucp/rma/put_am.c Outdated
Comment thread test/gtest/ucp/test_ucp_rma.cc
@svc-nvidia-pr-review

Copy link
Copy Markdown

No blockers found; residual coverage gap worth noting: the new tests only run under forced PROTOS, so the emulation SGL path is never exercised in the default (offload-selected) configuration, and there is no test asserting put/sgl/am/bcopy was actually selected (a name change would surface as a "no protocol found" failure, so this is acceptable).

@svc-nvidia-pr-review

Copy link
Copy Markdown

🤖 Starting review — findings will be posted here when done.

Comment thread src/ucp/rma/put_am.c
Comment thread test/gtest/ucp/test_ucp_rma.cc Outdated
@svc-nvidia-pr-review

Copy link
Copy Markdown

test/gtest/ucp/test_ucp_rma.cc

was the sporadic CUDA failure root-caused? with the default PREFER_OFFLOAD=y the new put/sgl/am/bcopy is last-resort only, so on offload-capable configs CUDA still runs the same protocol as before and this test may become flaky again.

@svc-nvidia-pr-review

Copy link
Copy Markdown

🤖 Starting review — findings will be posted here when done.

Comment thread test/gtest/ucp/test_ucp_rma.cc Outdated
@svc-nvidia-pr-review

Copy link
Copy Markdown

src/ucp/rma/put_am.c

minor: passing the fragment length as total_len gates off the NT-copy path in ucs_memcpy_relaxed() for large fragmented elements (the contig pack passes the whole message length here) - can we pass the element length instead?

@svc-nvidia-pr-review

Copy link
Copy Markdown

🤖 Starting review — findings will be posted here when done.

Comment thread test/gtest/ucp/test_ucp_rma.cc
@svc-nvidia-pr-review

Copy link
Copy Markdown

Residual coverage gap: the emulation protocol is only exercised with forced PROTOS=put/sgl/am/*; with the default PREFER_OFFLOAD=y it is a last-resort protocol, so the "default selection falls back to emulation" path (e.g. tcp-only) is still not covered — the non-forced SGL tests skip there via the has_lane_with_caps(PUT_ZCOPY) check. This was already noted in an earlier round.

Not repeated here (already raised in previous rounds): the CUDA skip removal without a root cause, and passing the fragment length as total_len to ucp_dt_contig_pack().

@svc-nvidia-pr-review

Copy link
Copy Markdown

🤖 Starting review — findings will be posted here when done.

UCP_SGL_EMULATION_PROTOS) {
m_require_zcopy_lane = false;
test_put_sgl(10, UCS_KBYTE, true, true);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor: with the emulation proto the put normally completes in place, so the callback is never invoked and this test adds nothing over put_emulation. can we set UCP_OP_ATTR_FLAG_NO_IMM_CMPL here to actually cover the callback path?

With the emulation protocol every fragment is sent synchronously by uct_ep_am_bcopy(), so ucp_request_send() drains the whole SGL in one call and ucp_proto_request_send_op_common() returns via ucp_request_imm_cmpl_param() — a status, not a request. In that case UCX does not invoke the send callback, and the new !UCS_PTR_IS_PTR(sptr) branch in test_sgl() skips the cb.completed/cb.status checks entirely. For 10×1KB this is the normal outcome.

@svc-nvidia-pr-review

Copy link
Copy Markdown

The CUDA FIXME skip removal has no stated root cause (plausibly this PR's fallback fixes "no protocol found" for CUDA, but that is not written down anywhere).

Generic SGL data-verification tests still skip on tcp via the has_lane_with_caps(PUT_ZCOPY) check, so the emulation is data-verified only under forced PROTOS.

No test asserts that put/sgl/am/bcopy was the selected protocol.

@svc-nvidia-pr-review

Copy link
Copy Markdown

🤖 Starting review — findings will be posted here when done.

Comment thread src/ucp/rma/put_am.c

ucs_assertv(lpriv->max_frag > sizeof(ucp_put_hdr_t), "max_frag=%zu",
lpriv->max_frag);
max_payload = lpriv->max_frag - sizeof(ucp_put_hdr_t);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we add a short comment on why ucp_proto_multi_max_payload() is not used here? for SGL dt_iter->length is the element count, so the weight scaling inside the helper would cap the payload by the number of elements — without a note someone is likely to "simplify" this back to the helper.

Comment thread src/ucp/rma/put_offload.c
ucp_proto_t ucp_put_sgl_offload_sw_proto = {
.name = "put/sgl/offload_sw",
.desc = "sgl " UCP_PROTO_RMA_EMULATION_DESC,
.desc = "sgl per-element zcopy",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor: use the existing macro, like the other protos in this file:

Suggested change
.desc = "sgl per-element zcopy",
.desc = "sgl per-element " UCP_PROTO_ZCOPY_DESC,

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants