Skip to content

UCT/CUDA: Prepare GDRCopy support for cudaMallocAsync - #12092

Merged
nbellalou merged 8 commits into
masterfrom
nv4741160-async-gdr-qualification
Oct 25, 2026
Merged

nbellalou merged 8 commits into
masterfrom
nv4741160-async-gdr-qualification

Conversation

@nbellalou

@nbellalou nbellalou commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

What?

First of three PRs to enable the gdr_copy transport for buffers allocated with cudaMallocAsync.

This PR adds prerequisite detection and quiet registration-error handling. It does not enable async GDRCopy or change protocol/transport selection. The following PRs will add the dormant short-copy path, then enable it only on supported configurations.

Why?

internal issue
The feature needs to distinguish a supported GDRCopy runtime/backend/driver combination from one that cannot CPU-map stream-ordered CUDA allocations. It also needs registration attempts to honor the existing request to suppress error-level logging, before adding a registration-time fallback.

Keeping this groundwork separate lets it be reviewed without introducing new buffer classification or routing decisions.

How?

  • Add build-time declaration checks for the optional GDRCopy backend query and the required CUDA/GDRCopy test-build wiring.
  • Add a helper that checks the loaded GDRCopy version (at least 2.6), whether its selected backend is DMA-BUF mmap, and the CUDA driver API version (at least 13.5 / 13050).
  • Resolve the optional gdr_get_attribute symbol from the library that supplied gdr_open, rather than assuming that newer build headers imply a newer runtime. Missing declarations, symbols, or failed queries return unsupported.
  • Forward the existing UCT registration flags in the uncached GDRCopy registration path. Pin/map/info failures honor UCT_MD_MEM_FLAG_HIDE_ERRORS; ordinary failures retain error-level logs. Return codes and cleanup are unchanged.
  • Add tests comparing qualification against the actual environment and verifying that failed registrations log errors normally, but not when hiding errors is requested.

Scope and performance

The qualification helper has no production caller in this PR: normal initialization and copying do not invoke the new probes. There are no UCP changes, async allocation markers, new advertised capabilities, configuration knobs, protocol-cost changes, or changes to copy operations.

This is preparatory for selection and the copy fast path, not feature activation. It is not a complete runtime no-op: honoring the existing quiet-error flag is an intentional logging fix. No latency/throughput benchmarks or measured zero-overhead claim are included.

Validation

  • CUDA/GDRCopy-enabled developer build on an A100 with GDRCopy 2.6: passed.
  • Focused GDRCopy, datatype, memory-registration and memory-flag suite: 68 executed passes, 1 hardware skip (C2C unavailable).
  • The two added tests, cuda_async_qualification and hide_registration_error, both executed and passed.
  • Whitespace checks passed; the single-commit branch merges cleanly into current master.
  • This validates the preparatory PR, not enabled async GDRCopy transport or performance.

@svc-nvidia-pr-review

Copy link
Copy Markdown

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

@gleon99
gleon99 requested a review from rakhmets October 15, 2026 08:05
Comment thread src/uct/cuda/gdr_copy/gdr_copy_md.c Resolved
Comment thread src/uct/cuda/gdr_copy/gdr_copy_md.c Resolved
Comment thread test/gtest/uct/test_md.cc Resolved
Comment thread test/gtest/uct/test_md.cc Resolved
Comment thread test/gtest/uct/test_md.cc Resolved
Comment thread test/gtest/uct/test_md.cc Resolved
Comment thread test/gtest/Makefile.am Resolved
@svc-ucx

svc-ucx commented Oct 15, 2026

Copy link
Copy Markdown

🤖 CI Triage Agent — UCX PR (Tests new on worker 3) · commit 9d611962

TL;DR: The only failure in this 8792-test run was the timing-sensitive unit test mt/test_profile.log/1 (4 threads, log-only mode), which asserts a profiled thread's lifetime is ≤ 1 second — a bound that is easily exceeded on a loaded CI worker. This is unrelated to PR #12092 (CUDA/GDRCopy); the fix is to relax/remove the wall-clock bound in test_profile.cc, and the PR can simply be re-run.

Full analysis

Summary: make test in the gtest stage exited with error 1 because 1 of 8792 tests failed: [ FAILED ] mt/test_profile.log/1, where GetParam() = 4 (make: *** [Makefile:4926: test] Error 1).

Root cause: test_profile::test_thread_locations() bounds each profiled thread's wall-clock lifetime:

EXPECT_LE(thread_hdr->end_time - thread_hdr->start_time,
          ucs_time_from_sec(1.0) * ucs::test_time_multiplier() * (1 + exp_count));

For the log variant, exp_count = 0 (count is only accumulated in ACCUM mode, see do_test() line 306 and ucs_profile_record() in src/ucs/profile/profile.c:600-621), so the allowed span collapses to just 1 second, versus 6 seconds for the accum / log_accum variants. With GetParam() = 4 the test spawns 4 threads whose start_time is taken at first profile record and whose end_time is taken in the TSD destructor after pthread_join; on a heavily loaded worker (this run took 3715 s wall, with neighbouring stress tests taking 30–40 s each) thread creation/scheduling delay alone can push a thread's lifetime past 1 s. That makes exactly this parameterization (mt + log) the flakiest of the six combinations — matching the observed failure. Nothing in the profiling code path touches CUDA/GDRCopy, and test_profile.cc / src/ucs/profile/profile.c have not been modified since 2023, so the PR's changes cannot be implicated.

Implicated commit: Not the PR commit. The flaky assertion dates to 5bf3df83 (Roie Danino, "UCS/PROFILE: added ucx env to profiling output, changed profiling file structure"); PR commit 9d611962 (Nathan Bellalou, "UCT/CUDA: Prepare async GDRCopy support") only touches src/uct/cuda/gdr_copy and is unrelated.

File: test/gtest/ucs/test_profile.cc:269-270 (assertion), with the contributing exp_count definition at test/gtest/ucs/test_profile.cc:306

Suggested fix:

  1. Immediate: re-run the "Tests new on worker 3" job — this failure is load-dependent flakiness, not a regression from UCT/CUDA: Prepare GDRCopy support for cudaMallocAsync #12092.
  2. Real fix: decouple the thread-lifetime bound from exp_count, which is 0 in log-only mode. For example use a generous fixed allowance that is not mode-dependent:
    const double MAX_THREAD_LIFETIME_SEC = 60.0; /* generous: guards against garbage timestamps only */
    EXPECT_LE(thread_hdr->end_time - thread_hdr->start_time,
              ucs_time_from_sec(MAX_THREAD_LIFETIME_SEC) * ucs::test_time_multiplier());
    The assertion's purpose is sanity-checking that start_time/end_time are plausible, not measuring performance, so a tight 1-second bound buys nothing and costs CI stability. The same reasoning applies to the per-location loc->total_time bound at line 276-277, which is 0 when exp_count == 0 and should be guarded similarly.

Related: PR #12092 (openucx/ucx) — "UCT/CUDA: Prepare GDRCopy support for cudaMallocAsync" (the PR under test, not the cause); assertion introduced in PR #8918 "UCS/PROFILE: added ucx env to profiling output".

@svc-nvidia-pr-review

Copy link
Copy Markdown

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

@nbellalou
nbellalou force-pushed the nv4741160-async-gdr-qualification branch from a0f3244 to bf81ba5 Compare October 15, 2026 12:02
@svc-nvidia-pr-review

Copy link
Copy Markdown

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

@svc-ucx

svc-ucx commented Oct 15, 2026

Copy link
Copy Markdown

🤖 CI Triage Agent — UCX PR (AddressSanitizer roce on worker 2) · commit a0f32443

TL;DR: The ASAN gtest shard aborted because ud_mlx5/uct_p2p_mix_test_alloc_methods.mix1000 hit the 30 s UD peer timeout (UCS_ERR_ENDPOINT_TIMEOUT, -80) on a RoCE loopback endpoint, and because uct_p2p_mix_test registers no UCT error handler the timeout escalated to ucs_fatal() → core dump. This is unrelated to the PR's gdr_copy changes; it is a RoCE/ASAN-slowness flake that the test turns into a hard crash.

Full analysis

Summary: ud_mlx5/uct_p2p_mix_test_alloc_methods.mix1000/3 <ud_mlx5/mlx5_1:1/loopback> failed with "Endpoint timeout" followed by ud_ep.c:293 Fatal: UD endpoint ... unhandled timeout error, aborting the whole gtest binary (make: *** [Makefile:4926: test] Aborted (core dumped)).

Root cause: The test started at 11:57:24.6 and the fatal fired at 11:57:56.2 — a 31.6 s silent interval that exactly matches the UD default UD_TIMEOUT of 30s (src/uct/ib/ud/base/ud_iface.c:682). So an ACK was never received for an in-flight UD packet within the peer timeout while random_op() was spinning in its progress() loop (test/gtest/uct/test_p2p_mix.cc:162-177); no application-level hang in the test itself, just a stalled/dropped UD transfer on the RoCE loopback device. The timeout path then did:

  1. uct_ud_ep_purge(ep, UCS_ERR_ENDPOINT_TIMEOUT) → delivered status -80 to the outstanding completion, producing the first failure EXPECT_UCS_OK(comp->status) at test/gtest/uct/test_p2p_mix.cc:33.
  2. uct_iface_handle_ep_err() returned non-OK because uct_p2p_mix_test constructs its base as uct_p2p_test(0) with the default err_handler = NULL (test/gtest/uct/test_p2p_mix.cc:15-16, test/gtest/uct/uct_p2p_test.h:17), so no peer-failure handler is installed → ucs_fatal("UD endpoint %p ... unhandled timeout error") at src/uct/ib/ud/base/ud_ep.c:293, killing the process instead of failing one test.

Under AddressSanitizer the gtest binary is heavily slowed (and this is shard 3 of 4 sharing the same RoCE port), which makes a 30 s peer timeout easy to exceed. Nothing in the PR under test (commit a0f3244, which only touches src/uct/cuda/gdr_copy — "UCT/CUDA: Prepare async GDRCopy support") can affect an ud_mlx5 host-memory transfer, so this failure is not caused by the PR.

Implicated commit: unknown — not the PR commit a0f3244 (gdr_copy only). If this recurs on ud_mlx5, the recent UD/IB address-handle changes are the places to look: f53da7f "UCT/IB: Add refcounted, TTL-based address handle cache (#11845)" (Thomas Vegas) and 183a66d / 0ee470a (Ilia Yastrebov, UD private EP keepalive / dest_id generation).

File: src/uct/ib/ud/base/ud_ep.c:293 (fatal), test/gtest/uct/test_p2p_mix.cc:33 (reported failure), test/gtest/uct/ib/test_ib_xfer.cc:134 (the mix1000 test case)

Suggested fix:

  1. Short term: re-run the ASAN roce job — this is an infrastructure/timing flake, not a code regression from UCT/CUDA: Prepare GDRCopy support for cudaMallocAsync #12092.
  2. Make the test not crash the whole shard: pass an error handler to the base class in uct_p2p_mix_test (e.g. uct_p2p_test(0, err_handler_cb)) so an endpoint timeout is recorded as a test failure instead of hitting ucs_fatal, as was done for other UD tests in UCT/GTEST: Hardening of UD stale private EP tests #11920.
  3. Make the test tolerant of ASAN slowdown: add "UD_TIMEOUT=120s" (and optionally a larger UD_TIMER_TICK) to the mix1000 test's config overrides for UD transports, or skip/relax it under ucs::skip_on_address_sanitizer()-style gating, since the 30 s default peer timeout is too tight when 4 instrumented shards share one RoCE port.

Related: PR #12092 (the PR under test, unrelated change); #11920 / #11948 "UCT/GTEST: Hardening of UD stale private EP tests" (precedent for hardening UD tests against timeouts); #11845 (UD/IB AH cache)

Comment thread src/uct/cuda/gdr_copy/gdr_copy_md.c Resolved
Comment thread src/uct/cuda/gdr_copy/gdr_copy_md.c Resolved
Comment thread src/uct/cuda/gdr_copy/gdr_copy_md.c Resolved
Comment thread test/gtest/uct/test_md.cc Resolved
Comment thread test/gtest/uct/test_md.cc Resolved
Comment thread test/gtest/uct/test_md.cc Resolved
@svc-nvidia-pr-review

Copy link
Copy Markdown

Residual coverage gaps: hide_registration_error covers the new flags plumbing only on the non-rcache path (GDR_COPY_RCACHE?=no); the rcache path (uct_gdr_copy_rcache_mem_reg_cb) and the newly log-leveled gdr_get_info failure are not exercised. Also, AC_DEFINE([HAVE_GDR_COPY]) is derived from the pre-existing gdrcopy_happy flag so no new configure path needs CI coverage, but the new AC_CHECK_DECLS for gdr_get_attribute/GDR_ATTR_USING_DMA_BUF_MMAP means both the "declared" and "not declared" compile variants only get covered if CI has a gdrcopy >= 2.6 image.

@svc-ucx

svc-ucx commented Oct 15, 2026

Copy link
Copy Markdown

🤖 CI Triage Agent — UCX PR (Tests roce on worker 1) · commit bf81ba5e

TL;DR: The roce on worker 1 job hung for ~69 minutes in uct_hello_world over rc_verbs/mlx5_1:1 and was killed when the Azure agent shut down; the second RoCE HCA (mlx5_1) on swx-rain04 is in a broken state (UMR CQ completions time out, no IPv4 address), so this is a host/device infrastructure failure, not a code regression from PR #12092.

Full analysis

Summary: contrib/test_jenkins.sh → run_uct_hello → uct_hello_world -d mlx5_1:1 -t rc_verbs -i -m host produced no output for ~69 min (12:27:50 → 13:36:35) until the agent cancelled the job; orphan cleanup confirms both uct_hello_world processes (pids 1803416, 1805488) were still alive.

Root cause: The mlx5_1 device on swx-rain04 is non-functional while still reporting PORT_ACTIVE, so the test harness selects it and then blocks forever:

  • Earlier in the same log, ucx_info logged mlx5_1: ibv_poll_cq(UMR CQ, registration, UMR mkey 0x...index 0x470) timed out — that is the 30 s guard in uct_ib_mlx5_devx_umr_post_sync() expiring (corroborated by # create time: 30121.308 ms for the UCP context), followed by ibv_post_send(UMR QP, invalidation, ...) returned 12: Numerical result out of range and <Failed to pack rkey: Input/output error>. All failures are on mlx5_1; mlx5_0 behaved normally throughout.
  • get_rdma_device_ip_addr mlx5_1:1 returned empty → Cannot find IPv4 address for device mlx5_1:1, so the perftest-over-daemon loop skipped it, but run_uct_hello iterates over get_active_ib_devices (which only greps for PORT_ACTIVE) and still ran on mlx5_1:1.
  • The RC connection over the dead HCA never completed; run_client_server_app does a bare wait ${client_pid} with no timeout, so the hang consumed the remaining wall clock. The largest log gap is the entire remaining runtime with zero output — classic hang, not slowness.

PR #12092 (GDRCopy / cudaMallocAsync) cannot be implicated: the same log shows ==== CUDA not available, skipping CUDA device tests ====, i.e. this job was built without CUDA and never exercised the changed code.

Implicated commit: unknown — no code commit implicated; failure is environmental (faulty mlx5_1 HCA on agent swx-rain04, Azure agent shutdown). Nearest relevant code is the unguarded wait in contrib/test_jenkins.sh (last touched by 40a33dc, Thomas Vegas) and the UMR sync-post timeout in src/uct/ib/mlx5/dv/ib_mlx5dv_md.c.

File: contrib/test_jenkins.sh:219 (wait ${client_pid} with no timeout); device selection at buildlib/tools/common.sh:176-194; UMR timeout origin at src/uct/ib/mlx5/dv/ib_mlx5dv_md.c:1447-1453

Suggested fix:

  1. Infra first: take swx-rain04 out of the RoCE pool and reset/reseat mlx5_1 (firmware/port state). A device whose UMR QP never completes and whose netdev has no IPv4 must not be advertised as usable.
  2. Harden device selection: make get_active_ib_devices (or run_uct_hello) skip devices that have no resolvable IP / no valid GID, mirroring the check already used by get_rdma_device_ip_addr — the perftest loop correctly skipped mlx5_1, run_uct_hello did not.
  3. Harden the harness so a dead HCA fails fast instead of burning the job's wall clock: wrap the client/server invocations in run_client_server_app with timeout (e.g. timeout 5m) and treat the timeout as a test failure, so the real error is reported rather than The agent has received a shutdown signal.
  4. Optional: have check_machine() also probe each active port with a quick UMR/rkey sanity check (ucx_info -d style) and fail the job early with a clear message when it times out.
  5. Re-run the PR's roce on worker 1 leg on a healthy agent to confirm it is green.

Related: PR #12092 (the PR under test, not the cause); no existing issue found for the mlx5_1 UMR CQ timeout on this host — worth filing one against CI infra.

@svc-nvidia-pr-review

Copy link
Copy Markdown

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

Comment thread src/uct/cuda/gdr_copy/gdr_copy_md.c Resolved
Comment thread src/uct/cuda/gdr_copy/gdr_copy_md.c Resolved
Comment thread test/gtest/uct/test_md.cc Resolved
@svc-nvidia-pr-review

Copy link
Copy Markdown

Residual coverage gaps: cuda_async_qualification and hide_registration_error exercise only the non-rcache uct_gdr_copy_mem_reg path (GDR_COPY_RCACHE?=no); the uct_gdr_copy_rcache_mem_reg_cb path and the newly log-leveled gdr_get_info failure remain uncovered.

The two AC_CHECK_DECLS compile variants (gdr_get_attribute declared vs. not) are only both covered if CI has both a gdrcopy < 2.6 and a >= 2.6 image; worth confirming in buildlib/tools/builds.sh.

@svc-ucx

svc-ucx commented Oct 18, 2026

Copy link
Copy Markdown

🤖 CI Triage Agent — UCX PR (AddressSanitizer roce on worker 1) · commit a3349d7e

TL;DR: The gtest run aborted because ucp_rkey_pack() returned UCS_ERR_IO_ERROR after a UMR mkey registration on mlx5_1 timed out (30 s busy-poll with no completion), and the gtest ASSERT_UCS_OK inside mapped_buffer's constructor then leaked the mapped memh, which tripped the fatal region->refcount == 0 rcache assert at ucp_cleanup (core dump). Fix the UMR error path (don't re-post on a dead UMR QP, surface wc.status) and make mapped_buffer release the memh when rkey packing fails, so a transport error doesn't become a core dump.

Full analysis

Summary: all/test_ucp_rma_sgl.put_missing_remote_field/0 <all/host> failed in the AddressSanitizer/RoCE job: UMR mkey registration timed out, then UCX fatal-asserted in rcache during ucp_cleanup, aborting make test (Bash exited with code '2').

Root cause: Evidence chain from the log:

  1. 08:47:28.98 test starts; 08:47:59.46 (exactly the 30 s timeout in uct_ib_mlx5_devx_umr_post_sync) → mlx5_1: ibv_poll_cq(UMR CQ, registration, UMR mkey 0x...9890 index 0x240b) timed out. The IBV_WR_BIND_MW work request posted on the dedicated UMR QP never generated a completion.
  2. The timeout error path calls uct_ib_mlx5_devx_umr_mkey_invalidate() on the same (still-outstanding) mkey and posts to the now-wedged UMR QP → ibv_post_send(UMR QP, invalidation, ...) returned 12: Bad address. So the mkey is not cleaned up correctly either.
  3. Registration failure propagates up as UCS_ERR_IO_ERROR to test/gtest/ucp/ucp_test.cc:1288 (ASSERT_UCS_OK after ucp_rkey_pack) inside ucp_test::mapped_buffer's constructor. A gtest ASSERT_* only returns from the ctor — the object is never fully constructed, so ~mapped_buffer() (which calls ucp_mem_unmap) never runs.
  4. The leaked memh keeps its rcache region referenced: rcache.c:670 WARN ucp_rcache: destroying inuse region ... ref 1 md[0]=self md[4]=mlx5_0 md[5]=mlx5_1 ..., then rcache.c:394 Assertion 'region->refcount == 0' failed → ucs_fatal_error → backtrace through ucp_mem_rcache_cleanup / ucp_cleanup → core dump.

The real failure is #1 (UMR QP stall on the RoCE device under ASan); #3/#4 are a test-harness defect that converts a recoverable transport error into a fatal crash of the whole gtest binary. Nothing in this path touches the CUDA/GDRCopy code changed by PR #12092, so the PR looks like an innocent bystander — but the crash is fully reproducible as a job failure whenever the UMR bind times out.

Implicated commit: unknown — no recent commit in src/uct/ib/mlx5/dv/ib_mlx5dv_md.c (latest: [REDACTED:Hex High Entropy String], Thomas Vegas, "UCT/IB: Allow ODP with DDP for FW >= 49.1014") or in the rcache touches this UMR sync path; the PR under test (a3349d7e, CUDA/GDRCopy) is unrelated to the IB UMR code.

File: src/uct/ib/mlx5/dv/ib_mlx5dv_md.c:1447 (30 s poll timeout) and :1548-1552 (bad error path), plus test/gtest/ucp/ucp_test.cc:1288 (leaking ASSERT in constructor)

Suggested fix:

  1. ib_mlx5dv_md.c:1548-1552 — on uct_ib_mlx5_devx_umr_post_sync() failure for "registration", do not call uct_ib_mlx5_devx_umr_mkey_invalidate() (which re-posts on a QP that is already stuck/in error and can recycle a still-bound mkey back into md->umr.mkey_pool). Call uct_ib_mlx5_devx_umr_mkey_destroy() directly, and mark md->umr.qp as unusable so subsequent registrations re-create it instead of blocking another 30 s each.
  2. ib_mlx5dv_md.c:1447-1462 — the busy-poll loop ignores QP errors; also query/log the QP state and wc.status/vendor_err on timeout, and reduce the hard-coded 30 s (make it configurable) so one stall does not consume the job's time budget.
  3. test/gtest/ucp/ucp_test.cc:1282-1289 — make mapped_buffer exception/early-return safe: if ucp_rkey_pack() fails, ucp_mem_unmap(m_memh) before asserting (or move mapping into a factory/SetUp so the dtor always runs). This keeps a UMR/transport error as a single test failure instead of a fatal rcache assert that aborts the entire gtest binary.
  4. Re-run the job to confirm the UMR timeout is intermittent on mlx5_1 for this RoCE/ASan worker (swx-rain03); if it recurs on unrelated PRs, open a tracking issue against the UMR export path rather than blocking UCT/CUDA: Prepare GDRCopy support for cudaMallocAsync #12092.

Related: PR #12092 (build under test, unrelated change); PR #11958 (rcache region refcount/merging work) — no existing issue found for the ibv_poll_cq(UMR CQ, registration) timed out signature, so this is worth filing.

🛡️ This comment had 1 potential secret(s) redacted (Hex High Entropy String). See request_id bb7a96db-7cee-47bb-a6dc-aad7d6f9f3c1 in the triage console for the audit trail.

Prepare guarded runtime/backend/driver checks for async GDRCopy and honor quiet registration error requests. Do not define async memory/copy capability flags, advertise support, or change transport selection.
Reuse shared error-log capture and qualification constants, and group GDRCopy test flags with the existing CUDA settings.
Handle a missing dlerror message before formatting the debug diagnostic, and keep the registration-error test declarations separate from assignment.
@nbellalou
nbellalou force-pushed the nv4741160-async-gdr-qualification branch from a3349d7 to 80c4036 Compare October 18, 2026 14:07
@svc-nvidia-pr-review

Copy link
Copy Markdown

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

Comment thread src/uct/cuda/gdr_copy/gdr_copy_md.c Resolved
Comment thread test/gtest/uct/test_md.cc Resolved
Comment thread src/uct/cuda/gdr_copy/gdr_copy_md.c Resolved
Comment thread test/gtest/uct/test_md.cc Resolved
@svc-nvidia-pr-review

Copy link
Copy Markdown

src/uct/cuda/gdr_copy/gdr_copy_md.c

Inconsistent with the existing optional-API pattern: the whole dladdr(gdr_open) → dlopen(RTLD_NOLOAD) → dlsym → dladdr/dli_fbase comparison block exists to reach a symbol that the build already proved is declared (HAVE_DECL_GDR_GET_ATTRIBUTE) in a library that is already linked (-lgdrapi). A few lines above, gdr_pin_buffer_v2 is called directly under exactly such a HAVE_DECL_* guard. Why not call gdr_get_attribute directly under the HAVE_DECL_* guard, like gdr_pin_buffer_v2 above? The dladdr/dlopen/dlsym dance looks redundant.

Residual coverage gaps: the new flags plumbing is exercised only on the non-rcache path (GDR_COPY_RCACHE?=no); uct_gdr_copy_rcache_mem_reg_cb and the newly log-leveled gdr_get_info failure stay uncovered. The two AC_CHECK_DECLS compile variants (gdr_get_attribute declared vs. not) are both covered only if CI has images with gdrcopy both below and at/above 2.6 — worth confirming in buildlib/tools/builds.sh.

Comment thread src/uct/cuda/base/cuda_util.c Resolved
Comment thread src/uct/cuda/gdr_copy/gdr_copy_md.c Resolved
Log failed CUDA driver-version queries at error level and diagnose optional GDRCopy backend-query lookup failures without changing support decisions.

Keep registration flags consistent with the internal helper and restrict the v2-pin declaration guard to tests that depend on it.

Signed-off-by: Nathan Bellalou <nbellalou@nvidia.com>
@svc-nvidia-pr-review

Copy link
Copy Markdown

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

Comment thread src/uct/cuda/gdr_copy/gdr_copy_md.c Resolved
Comment thread test/gtest/uct/test_md.cc Resolved
Comment thread src/uct/cuda/gdr_copy/gdr_copy_md.c Resolved
@nbellalou
nbellalou requested a review from rakhmets October 21, 2026 08:13
@svc-ucx

svc-ucx commented Oct 21, 2026

Copy link
Copy Markdown

🤖 CI Triage Agent — UCX PR (AddressSanitizer gpu on worker 3) · commit 6e36ee49

TL;DR: The ASAN GPU job failed because exactly one of 10,398 gtests failed — rc_mlx5/uct_atomic_key_reg_rdma_mem_type.fadd64/0, an IB MEMIC (device-memory) atomic test that has no code path in common with this PR's GDRCopy changes; this is a pre-existing flake (MEMIC allocation / device-memory atomic registration), so re-run the job rather than changing PR code.

Full analysis

Summary: make test in build-test/test/gtest exited with Error 1 because rc_mlx5/uct_atomic_key_reg_rdma_mem_type.fadd64/0 (GetParam() = rc_mlx5/mlx5_0:1) failed; all other 10,397 tests passed.

Root cause: From the log (2026-10-21T11:08:18.777Z): [ FAILED ] 1 test, listed below: rc_mlx5/uct_atomic_key_reg_rdma_mem_type.fadd64/0, followed by make: *** [Makefile:4926: test] Error 1. There is no hang — the run completed normally (10398 tests ... 1999095 ms total, full teardown, TOP-20 timing report), so this is a genuine single test assertion, not a wall-clock kill.

That test (test/gtest/uct/test_atomic_key_reg_rdma_mem_type.cc:29-41) allocates an 8-byte UCS_MEMORY_TYPE_RDMA buffer — i.e. mlx5 MEMIC on-device memory — and drives 4 worker threads doing uct_ep_atomic64_fetch(UCT_ATOMIC_OP_ADD) against it. Its only failure points are the ASSERT_UCS_OK(status) inside uct_test::entity::mem_alloc (test/gtest/uct/uct_test.cc:1035) and the UCS_TEST_ABORT in uct_amo_test::worker::run (test/gtest/uct/test_amo.cc:188) — note this test never calls validate_replies(), so a data-correctness mismatch is not possible here. MEMIC allocation is a scarce, device-wide shared resource, which is why this exact file has been hardened three separate times for allocation flakiness (d7d57e17 "Limit MEMIC allocation to prevent out-of-memory test failures", [REDACTED:Hex High Entropy String] "Retry when it cannot allocate MEMIC memory", 69718f6d "Add retries and rand sleep when it cannot allocate MEMIC memory"). The retry loop at uct_test.cc:1005-1033 only retries on UCS_ERR_NO_MEMORY; any other status fails on the first attempt.

Crucially, nothing in this path is touched by the PR. The four commits on nv4741160-async-gdr-qualification (4361f32e, 9d0d2f0f, 80c4036c, 6e36ee49, all Nathan Bellalou) are confined to src/uct/cuda/gdr_copy/gdr_copy_md.c (the uct_gdr_copy_cuda_async_detect / uct_gdr_copy_using_dmabuf dlopen diagnostics at lines 70-145) and test/gtest/uct/test_md.cc. The failing test is an rc_mlx5 IB transport test over MEMIC device memory with IB_DM_COUNT=0; it never opens a gdr_copy MD, never registers CUDA memory, and never reaches uct_gdr_copy_md_query. The gdr_copy-related test suites in this same run (cuda_cpy/test_md.reg_perf/0, cuda_copy/uct_p2p_mix_test.mix_10000/1) all passed.

Caveat: the Azure log retained only the last ~500 lines, so the per-test assertion text for fadd64/0 has scrolled out — I can confirm which test failed and that the PR is not implicated, but not the precise assertion line. Fetching the full raw log would pin down whether it was a UCS_ERR_NO_MEMORY exhaustion or a different status.

Implicated commit: none — not caused by 6e36ee49 (Nathan Bellalou) or any commit in PR #12092. Pre-existing flakiness last touched by 69718f6d (Michal Shalev, "TEST/GTEST/UCT: Add retries and rand sleep when it cannot allocate MEMIC memory").

File: test/gtest/uct/test_atomic_key_reg_rdma_mem_type.cc:29-41 (failing test); test/gtest/uct/uct_test.cc:1005-1035 (MEMIC alloc retry loop)

Suggested fix: Do not change PR code — re-run the "AddressSanitizer gpu on worker 3" job; a single unrelated MEMIC test failure out of 10,398 is an infra flake. If it reproduces, grab the full (untruncated) log to get the assertion text, and harden the test the same way its history suggests: widen the retry condition in uct_test::entity::mem_alloc to also retry on UCS_ERR_NO_RESOURCE/UCS_ERR_IO_ERROR for UCS_MEMORY_TYPE_RDMA, or add a UCS_TEST_SKIP_R when MEMIC allocation is exhausted instead of ASSERT_UCS_OK — MEMIC is a device-wide shared resource and concurrent gtest shards on the same mlx5_0 can legitimately starve it.

Related: PR #12092 (this PR, "UCT/CUDA: Prepare GDRCopy support for cudaMallocAsync"); prior hardening of the same test: 69718f6d, [REDACTED:Hex High Entropy String], d7d57e17, 24976a86 ("Fix heap-buffer overflow in AMO test")

🛡️ This comment had 1 potential secret(s) redacted (Hex High Entropy String). See request_id 02de9f3c-7797-4d2d-afd3-1041378df73e in the triage console for the audit trail.

Comment thread src/uct/cuda/gdr_copy/gdr_copy_md.c Resolved
Comment thread src/uct/cuda/gdr_copy/gdr_copy_md.c Resolved
Comment thread test/gtest/uct/test_md.cc Resolved
Comment thread test/gtest/uct/test_md.cc Resolved
Comment thread test/gtest/uct/test_md.cc Resolved
Comment thread test/gtest/uct/test_md.cc Resolved
Declare test variables near use and construct the cleanup handle after a successful allocation assertion.

Apply the formatting changes reported by CI.
rakhmets
rakhmets previously approved these changes Oct 22, 2026
@svc-nvidia-pr-review

Copy link
Copy Markdown

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

@svc-ucx

svc-ucx commented Oct 22, 2026

Copy link
Copy Markdown

🤖 CI Triage Agent — UCX PR (Tests gpu prebuild) · commit a977cecc

TL;DR: The Tests gpu job died because mpirun (from the hpcx module) aborted immediately — OpenMPI's rsh/ssh launcher could not find its launch agent (plm_rsh_agent: ssh : rsh), i.e. the ubuntu2404_doca31_gpunetio container has no ssh/rsh binary. This is an environment/infrastructure break, unrelated to PR #12092's GDRCopy change; fix by installing openssh-client in the image (or forcing -mca plm isolated / a valid plm_rsh_agent in test_jenkins.sh).

Full analysis

Summary: Step "Build for tests" failed with exit code 243 at the very first mpirun invocation of run_ucx_perftest 1 inside run_mpi_tests.

Root cause: Build and make install / make installcheck all succeeded (examples compiled cleanly, so the PR's code is fine). The job then ran:

mpirun --allow-run-as-root --bind-to none ... -np 2 -x UCX_NET_DEVICES=all -x UCX_TLS=shm .../ucx_perftest ...

using mpirun from /hpc/local/benchmarks/custom_by_michael/hpcx-v2.24-gcc-doca_ofed-ubuntu24.04-cuda13-x86_64/ompi/bin (resolved by the hpcx-ga-gcc module at contrib/test_jenkins.sh:954). OpenMPI aborted in under 100 ms:

The value of the MCA parameter "plm_rsh_agent" was set to a path
that could not be found:
  plm_rsh_agent: ssh : rsh
[swx-rdmz-ucx-gpu-01:39164] [[INVALID],INVALID] FORCE-TERMINATE AT Not found:-13 - error plm_rsh_component.c(335)

ssh : rsh is OpenMPI's default agent list, meaning neither ssh nor rsh exists on PATH inside the rdmz-harbor.rdmz.labs.mlnx/hpcx/x86_64/ubuntu24.04/builder:doca-3.1.0-gpunetio container. The rsh PLM component is selected even for a purely local 2-rank run, so it force-terminates before any UCX code executes. bash -eEx then propagated the failure as exit 243. There is no hang (the whole failure spans <0.1 s) and no UCX-level error — nothing in the log implicates the PR's cudaMallocAsync/GDRCopy work.

Implicated commit: unknown — no UCX source commit is implicated. The breakage is in the CI container image / hpcx-ga-gcc module on swx-rdmz-ucx-gpu-01 (note the non-standard custom_by_michael/hpcx-v2.24-... install path the module resolves to); contrib/test_jenkins.sh has no plm_rsh_agent hardening (last touched by 40a33dc, Thomas Vegas, unrelated).

File: contrib/test_jenkins.sh:969-981 (MPIRUN_COMMON/MPIRUN definitions), container defined at buildlib/pr/main.yml:66-68

Suggested fix:

  1. Primary (infra): add openssh-client to the ubuntu24.04/builder:doca-3.1.0-gpunetio image, or revert the hpcx-ga-gcc module on the GPU agents back to the standard HPC-X install that ships a usable launch agent. Also verify why that module now points at a custom_by_michael/... tree.
  2. Defensive (repo-side), so a missing ssh can't take down the whole GPU lane — for these single-node runs force the local launcher in MPIRUN_COMMON:
    MPIRUN_COMMON="mpirun --allow-run-as-root --bind-to none \
            -mca plm isolated \
            -x UCX_ERROR_SIGNALS -x UCX_HANDLE_ERRORS"
    (or -mca plm_rsh_agent /bin/false). Additionally, have run_mpi_tests probe the launcher before use — e.g. mpirun --allow-run-as-root -np 1 true || { log_warning "mpirun unusable"; return; } — instead of only checking mpirun --version at line 957, which succeeds even when the PLM agent is missing.
  3. Re-run the Tests gpu lane for PR UCT/CUDA: Prepare GDRCopy support for cudaMallocAsync #12092 once the image is fixed; this failure should not block the PR.

Related: PR #12092 (the PR under test, "UCT/CUDA: Prepare GDRCopy support for cudaMallocAsync" — not the cause). No existing issue found for the plm_rsh_agent failure; worth filing one against the GPU builder image.

Comment thread src/uct/cuda/gdr_copy/gdr_copy_md.h Resolved
Comment thread test/gtest/uct/test_md.cc Resolved
@svc-nvidia-pr-review

Copy link
Copy Markdown

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

Comment thread src/uct/cuda/gdr_copy/gdr_copy_md.c Resolved
Comment thread test/gtest/uct/test_md.cc Resolved
Comment thread test/gtest/uct/test_md.cc Resolved
@svc-ucx

svc-ucx commented Oct 22, 2026

Copy link
Copy Markdown

🤖 CI Triage Agent — UCX PR (Tests gpu prebuild) · commit 7ccd3548

TL;DR: The "gpu prebuild" job died because mpirun (HPC-X 2.24 from /hpc/local/.../custom_by_michael/...) aborted instantly — it could not find its launch agent (ssh/rsh are not installed in the ubuntu2404_doca31_gpunetio container) — so the MPI perftest step exited 243; fix it by making the single-node MPI runs launcher-independent (-mca plm isolated / explicit plm_rsh_agent) or by adding openssh-client to the container image.

Full analysis

Summary: Stage "Build for tests" of job Tests gpu prebuild failed with Bash exited with code '243' right after mpirun was invoked from run_mpi_tests → run_ucx_perftest 1.

Root cause: Not a code/PR problem. The build and make install/installcheck all succeeded (examples compiled cleanly). The failure is the very first MPI launch:

+ mpirun --allow-run-as-root --bind-to none ... -np 2 -x UCX_NET_DEVICES=all -x UCX_TLS=shm .../ucx_perftest ...
The value of the MCA parameter "plm_rsh_agent" was set to a path that could not be found:
  plm_rsh_agent: ssh : rsh
[swx-rdmz-ucx-gpu-01:39179] [[INVALID],INVALID] FORCE-TERMINATE AT Not found:-13 - error plm_rsh_component.c(335)

Open MPI's rsh/ssh PLM component (used even for single-node launches) searched its default agent list ssh : rsh in $PATH and found neither — the rdmz-harbor.../ubuntu24.04/builder:doca-3.1.0-gpunetio container has no SSH client installed. mpirun --version (the only sanity gate in run_mpi_tests) still succeeds, so the script proceeds and mpirun aborts with 243, killing the bash -eEx step. There is no hang: timestamps run continuously, the whole failure happens within the same second (17:02:33.4).

Because PR #11896 (AZP/TESTS: Build once per GPU test row...) moved build_for_tests (which calls run_mpi_tests) into this dedicated prebuild job that all 4 GPU workers depend on, this environment gap now fails the entire Tests/gpu row instead of a single worker.

Implicated commit: 390a30e — Alexey Rivkin, "AZP/TESTS: Build once per GPU test row and share the tree with the workers (#11896)" (exposes the issue; the actual defect is the container image / hpcx-ga-gcc module environment, not commit 7ccd354 of this PR)

File: contrib/test_jenkins.sh:971-985 (MPIRUN_COMMON/MPIRUN definition and run_ucx_perftest 1), triggered from contrib/test_jenkins.sh:1517 (build_for_tests → run_mpi_tests); job definition buildlib/pr/tests.yml:32-46, container buildlib/pr/main.yml:66-68

Suggested fix: All CI mpirun invocations are single-node, so remove the dependency on an SSH launch agent — add -mca plm isolated (or -mca plm_rsh_agent "" / --mca plm_rsh_no_tree_spawn 1) to MPIRUN_COMMON in contrib/test_jenkins.sh, e.g.:

MPIRUN_COMMON="mpirun \
        --allow-run-as-root \
        --bind-to none \
        -mca plm isolated \
        -x UCX_ERROR_SIGNALS \
        -x UCX_HANDLE_ERRORS"

Additionally/alternatively: (a) install openssh-client in the hpcx/x86_64/ubuntu24.04/builder:doca-3.1.0-gpunetio image, and (b) harden the gate in run_mpi_tests so it skips MPI tests with a warning when no launch agent exists, e.g. if mpirun --version && command -v ssh, instead of failing the shared prebuild job for every GPU worker. Re-run the PR once the image/launcher is fixed; nothing in commit 7ccd354 needs changing.

Related: PR #11896 (introduced the shared GPU prebuild job); PR under test: #12092

@svc-nvidia-pr-review

Copy link
Copy Markdown

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

Comment thread src/uct/cuda/gdr_copy/gdr_copy_md.c Resolved
Comment thread test/gtest/uct/test_md.cc
dlsym(plugin.get(), "uct_gdr_copy_cuda_async_detect"));
ASSERT_NE(nullptr, detect);

#if HAVE_DECL_GDR_GET_ATTRIBUTE && HAVE_DECL_GDR_ATTR_USING_DMA_BUF_MMAP

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

In cuda_async_qualification, the #if HAVE_DECL_GDR_GET_ATTRIBUTE && HAVE_DECL_GDR_ATTR_USING_DMA_BUF_MMAP block recomputes exactly the same version/attribute/driver checks as uct_gdr_copy_cuda_async_detect() (major/minor >= 2.6, gdr_get_attribute present, cuDriverGetVersion >= UCT_GDR_COPY_CUDA_ASYNC_MIN_DRIVER_VERSION, GDR_ATTR_USING_DMA_BUF_MMAP) and asserts the two agree. The test therefore passes for any logic error in the qualification (wrong version threshold, inverted condition, wrong attribute) and only detects a link/dlsym break — regression tests should fail without the fix, and this duplicates the implementation. Can we assert on observable MD behavior instead of comparing the implementation to a copy of itself?

@svc-nvidia-pr-review

Copy link
Copy Markdown

Residual coverage gap: the flags plumbing in uct_gdr_copy_mem_reg() is exercised only on the non-rcache path (GDR_COPY_RCACHE?=no); uct_gdr_copy_rcache_mem_reg_cb() and the newly log-leveled gdr_get_info failure remain uncovered.

Residual coverage gap: the two AC_CHECK_DECLS compile variants (gdr_get_attribute/GDR_ATTR_USING_DMA_BUF_MMAP declared vs. not) are both covered only if CI has images with gdrcopy both below and at/above 2.6 — worth confirming in buildlib/tools/builds.sh.

@svc-ucx

svc-ucx commented Oct 23, 2026

Copy link
Copy Markdown

🤖 CI Triage Agent — UCX PR (Tests gpu prebuild) · commit 574a0a73

TL;DR: The "gpu prebuild" stage died in run_mpi_tests because mpirun from the loaded hpcx module can't find its rsh/ssh launch agent (plm_rsh_agent: ssh : rsh) inside the ubuntu24.04/builder:doca-3.1.0-gpunetio container — an environment problem unrelated to the PR; fix by installing openssh-client in that image and/or forcing a local launcher (-mca plm isolated) in MPIRUN_COMMON.

Full analysis

Summary: Step "Build for tests" of job gpu prebuild (build 140355) failed with Bash exited with code '243' right after make installcheck, when run_ucx_perftest 1 invoked mpirun.

Root cause: build_for_tests() → run_mpi_tests() loaded the hpcx-ga-gcc module (resolving to /hpc/local/benchmarks/custom_by_michael/hpcx-v2.24-gcc-doca_ofed-ubuntu24.04-cuda13-x86_64/ompi/bin/mpirun) and ran:

mpirun --allow-run-as-root ... -np 2 -x UCX_NET_DEVICES=all -x UCX_TLS=shm .../ucx_perftest ...
--------------------------------------------------------------------------
The value of the MCA parameter "plm_rsh_agent" was set to a path
that could not be found:
  plm_rsh_agent: ssh : rsh
--------------------------------------------------------------------------
[swx-rdmz-ucx-gpu-01:39193] [[INVALID],INVALID] FORCE-TERMINATE AT Not found:-13 - error plm_rsh_component.c(335)

ORTE's rsh PLM is the only launcher available and neither ssh nor rsh exists on the container PATH (/usr/local/nvidia/bin:/usr/local/cuda/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin), i.e. the doca-3.1.0-gpunetio image ships no SSH client. mpirun therefore aborts (exit 243) even for a purely local 2-rank run. The script's guard if mpirun --version passes (the binary runs fine), so the MPI section is not skipped and the whole prebuild job fails. No hang is involved — the log is continuous and the failure occurs ~0.5 s after mpirun starts. Nothing in this PR (GDRCopy/cudaMallocAsync) is touched by the failing path.

Implicated commit: Not a code regression in the PR. Environment/image side (no ssh/rsh in rdmz-harbor.rdmz.labs.mlnx/hpcx/x86_64/ubuntu24.04/builder:doca-3.1.0-gpunetio, referenced at buildlib/pr/main.yml:66-68). The failing path was moved into this new job by 390a30ee "AZP/TESTS: Build once per GPU test row and share the tree with the workers (#11896)", Alexey Rivkin.

File: contrib/test_jenkins.sh:971-985 (MPIRUN_COMMON/run_ucx_perftest 1 inside run_mpi_tests), reached from contrib/test_jenkins.sh:1517 and :1624

Suggested fix:

  1. Preferred infra fix: add openssh-client to the ubuntu24.04/builder:doca-3.1.0-gpunetio image (all MPI-capable CI images), since OMPI 4's plm_rsh requires an agent binary even for single-node runs.
  2. Repo-side hardening in contrib/test_jenkins.sh:
    • add a local launcher to MPIRUN_COMMON, e.g. -mca plm isolated (or -mca plm_rsh_agent $(command -v ssh || echo /bin/true)), since all CI MPI runs are single-node;
    • replace the if mpirun --version capability check with a real launch probe such as mpirun --allow-run-as-root -np 1 true so that an unusable launcher makes the MPI tests be skipped with a warning (echo "==== Not running MPI tests ====") instead of failing the shared prebuild job for every GPU worker.

Related: PR #11896 (390a30ee, introduced the gpu prebuild job that runs build_for_tests/run_mpi_tests); current PR #12092.

Comment thread test/gtest/uct/test_md.cc
Comment on lines +1453 to +1461
void *address;
ucs::handle<void*> buffer;

const int ret = posix_memalign(&address, REG_SIZE, REG_SIZE);
if (ret == 0) {
buffer.reset(address, free);
}

ASSERT_EQ(0, ret);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Maybe coverity will accept something like this:

Suggested change
void *address;
ucs::handle<void*> buffer;
const int ret = posix_memalign(&address, REG_SIZE, REG_SIZE);
if (ret == 0) {
buffer.reset(address, free);
}
ASSERT_EQ(0, ret);
void *address = nullptr;
const int ret = posix_memalign(&address, REG_SIZE, REG_SIZE);
ucs::handle<void*> buffer(address, free);
ASSERT_EQ(0, ret);

@svc-nvidia-pr-review

Copy link
Copy Markdown

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

#endif
}

int uct_gdr_copy_cuda_async_detect(gdr_t gdr_ctx)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

uct_gdr_copy_cuda_async_detect() has no caller in the library — only the gtest reaches it via dlsym. Nothing in uct_gdr_copy_md_query(), mem_reg, or the iface uses it, so the PR adds an exported detection helper plus its whole dladdr/dlopen/dlsym support path with no behavior change (dead code in a shipped module). Can we land it together with the code that consumes the result?

Comment thread test/gtest/uct/test_md.cc
dlsym(plugin.get(), "uct_gdr_copy_cuda_async_detect"));
ASSERT_NE(nullptr, detect);

#if HAVE_DECL_GDR_GET_ATTRIBUTE && HAVE_DECL_GDR_ATTR_USING_DMA_BUF_MMAP

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

cuda_async_qualification recomputes expected with the same runtime-version, gdr_get_attribute, and driver-version checks as the function under test, so the test would still pass if the threshold (e.g. 13050), the comparison, or the ordering were wrong — it only checks the function does not crash. Can we assert a value that does not mirror the implementation?

uct_gdr_copy_mem_reg(uct_md_h uct_md, void *address, size_t length,
const uct_md_mem_reg_params_t *params, uct_mem_h *memh_p)
{
unsigned flags = UCT_MD_MEM_REG_FIELD_VALUE(params, flags, FIELD_FLAGS, 0);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Suggested change
unsigned flags = UCT_MD_MEM_REG_FIELD_VALUE(params, flags, FIELD_FLAGS, 0);
uint64_t flags = UCT_MD_MEM_REG_FIELD_VALUE(params, flags, FIELD_FLAGS, 0);

minor: params->flags is uint64_t, and uct_gdr_copy_mem_rcache_reg() in this file already uses uint64_t.

Comment thread test/gtest/uct/test_md.cc
ASSERT_UCS_OK(register_mem());
}

#endif /* HAVE_DECL_GDR_PIN_BUFFER_V2 */

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: the two new tests are inserted between two #if HAVE_DECL_GDR_PIN_BUFFER_V2 blocks, creating a second identical guard block in the same fixture; pls move the two new tests below the existing ones so one guard block is enough.

@svc-nvidia-pr-review

Copy link
Copy Markdown

Residual coverage gaps: CI loads dev/gdrcopy2.5.1_cuda13.0.2 (buildlib/tools/common.sh:8, buildlib/az-helpers.sh:214), i.e. gdrcopy < 2.6. So HAVE_DECL_GDR_GET_ATTRIBUTE / HAVE_DECL_GDR_ATTR_USING_DMA_BUF_MMAP are 0 in every CI job: uct_gdr_copy_using_dmabuf() compiles to return 0, the dladdr/dlopen/dlsym path is never built, and cuda_async_qualification degenerates to EXPECT_EQ(0, 0). The flags plumbing is still exercised only on the non-rcache path (GDR_COPY_RCACHE?=no); uct_gdr_copy_rcache_mem_reg_cb() and the newly log-leveled gdr_get_info failure remain uncovered.

@nbellalou
nbellalou merged commit 27962e3 into master Oct 25, 2026
167 checks passed
@yosefe
yosefe deleted the nv4741160-async-gdr-qualification branch November 1, 2026 10:30
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.

4 participants