Repository navigation
fix(rccl/gin): reject Anvil GIN peers outside the LSA team - #13429
Conversation
✅ All Policy Checks Passed
📖 Need help? See the Policy FAQ for details on every check and how to fix failures. |
There was a problem hiding this comment.
ARGUS
Findings
5 more finding(s), not posted inline
projects/rccl/src/gin/gin_plugin_anvil_sdma.cc:752(Low) Anvil LSA refusal runs at bind, after ncclGinDevCommSetup chose the backend, so backend fallback cannot runprojects/rccl/CHANGELOG.md:59(Low) CHANGELOG entry ties the new init failure to NCCL_GIN_TYPE=7 only, not the unset-type case where Anvil is selectedprojects/rccl/test/gin/GinAnvilPlugin_test.cpp:551(Low) No passing bind test has comm->rank, GIN rank and lsaSelf differ, so swapped indices in the helper go undetectedprojects/rccl/test/gin/GinAnvilPlugin_test.cpp:1008(Low) ConnCheck_UsesLsaTeamForBootstrap now uses an identity lsaRanks list, so it cannot tell LSA-team from world bootstrapprojects/rccl/test/gin/GinAnvilPlugin_test.cpp:1002(Low) ConnCheck_UsesLsaTeamForBootstrap inlines startTwoRankGin's body only to pass ginRank=1
Bottom line: Looks approval ready.
Comment @argus review to re-run, or @argus re-review after pushing.
) This PR is the **RCCL half** of the CPX GIN fix; the rocSHMEM half is #12841, now merged to `develop` as `c34c1b1f56`. `CODEOWNERS` assigns `projects/rocshmem/` to `@ROCm/rocshmem-reviewers` and `projects/rccl/` to `@ROCm/rccl-reviewers`/`@ROCm/rccl-leads`, so the change is split by owner. This half is 996 insertions across 11 files, all under `projects/rccl/`. **Rebased onto `develop` after #12841 merged.** `gin_anvil_sdma_factory.cc` calls `disconnectDevice()` and its test calls `oamMapEngineNeedsFold()` and `pciFunctionBus()`, all added by #12841, which also adds `anvil_engine_map.hpp` to RCCL's `--rocshmem-gin` copy list. That dependency is now satisfied by `develop` itself, so the branch carries only the 11 RCCL commits and no rocSHMEM files. **Replaces #12603.** Review history lives there: four rounds of Argus review ending in LGTM, with all 37 threads resolved. #12603 was opened from a fork where `RCCL PR gate` can never pass on its own. ## Summary GIN Anvil SDMA (`NCCL_GIN_TYPE=7`) failed to initialize on MI300X in CPX mode. Four defects stacked on top of each other, each masking the next. Two are in RCCL and are fixed here; the two Anvil defects were fixed in #12841. **Note on the JIRA title:** the ticket says GIN Type 6, but Anvil SDMA is `NCCL_GIN_TYPE=7` on this branch (`6` is rocSHMEM GDA). All verification used `NCCL_GIN_TYPE=7`. 1. **The RCCL GIN gate rejected every CPX partition** (`init.cc`). `fillInfo` stamps `mloPart = fn` on every CPX partition, but the `hasMloPart` carve-out only exempted partition 0, so ranks on partitions 1-7 set `comm->hasMloPart` and the gate turned GIN off. That dropped `symmetricSupport`, which routed `ncclCommWindowRegister` into `windowRegisterNonSym` and produced `hipIpcGetMemHandle failed: invalid argument`. Fix: `NCCL_GIN_MLOPART`, mirroring `NCCL_NET_GDR_MLOPART` at `graph/paths.cc:522`. The parameter is tri-state. By default a partitioned communicator keeps GIN on a single node and loses it across several: only the single-node shape has been run, and past one node admitting a partition additionally reaches the hierarchical Copy Engine path that `ncclHierCeAllowed` gates on `nNodes > 1` and `symmetricSupport` together. `1` admits partitions on any number of nodes, which is the opt-in a multi-node partitioned deployment needs; `0` restores the pre-parameter exclusion. A refused multi-node partitioned communicator names the override through `NCCL_DEBUG=INFO`, and the `GIN/RMA support` line from #11133 now reports `nNodes` beside `mloPart`. The condition is lifted into `ginGateAllows()` so it can be asserted directly. 2. **`windowRegisterNonSym` had no cuMem path** (`dev_runtime.cc`). Even with the gate fixed, the fallback only implemented legacy IPC, and GIN requires `NCCL_CUMEM_ENABLE=1`. Probe with `cuMemRetainAllocationHandle` and import through `ncclP2pImportShareableBuffer`; legacy IPC still covers genuine `cudaMalloc` buffers. Teardown branches per peer on `ipcPeerIsCuMem`. A window spanning several segments is refused outright, since the exchange publishes one handle and one size. ### Argus High findings fixed - **Resume could not re-match the import.** The import previously passed `ncclMemOffload` with the exporter's device VA as `ownerPtr`. Resume matches an imported entry against the owner-published list, which `mem_manager.cc:806` builds only from entries with `numExportedPeers > 0`, and that counter is incremented solely by `ncclP2pAllocateShareableBuffer`. `windowRegisterNonSym` exports a user buffer it never allocated, so no owner entry exists and the match at `:894` failed into `ncclSystemError`. Now imported as `ncclMemPersist` with a null owner, matching `transport/net.cc:699-701`. `ownerPtr` became dead and was removed from the record along with its two duplicated `static_assert`s. - **A failed GIN create destroyed another communicator's queues.** `gin_anvil_sdma_create`'s failure path called `anvil.disconnect()`, which clears the process-global channel map. Each communicator gets a fresh `ginState` and the connect loop deliberately reuses queues a previous create left behind, so a second create hitting the budget refusal destroyed the first's queues while their handles were already live on the GPU. Now it records the destinations it newly connected and releases only those via `disconnectDevice()`. ### Fold tests `AnvilOamMapEngine.*` asserts when the CPX fold runs, not which engine it picks. That choice is rocSHMEM's contract and differs between #12841 (even engines only) and #13237 (every engine), so it is pinned only by rocSHMEM's `anvil_engine_map_gtest`. ## Rebase onto `develop` The rebase from the old #12841 tip (`b47b4f7ccf`) onto `develop` (`c34c1b1f56`) had one conflict, in `init.cc`'s GIN/RMA log. #11133 replaced the conditional `symmetricSupport ... crossNicSupport` INFO line, which this PR had extended with `hasMloPart` and `nNodes`, with an always-on `GIN/RMA support` line that already reports `mloPart`. The resolution keeps #11133's line, adds `nNodes` to it, and keeps the `NCCL_GIN_MLOPART` multi-node hint after it. Every other file's change is identical to the pre-rebase branch. ## Test plan - [x] **Host tests on the rebased head (`fbf8a6d3c3`): 6,068 passed, 0 failed, 5 skipped** (the pre-existing `SymKernelMaskTest` skips), run through `test/host/run_host_tests.sh` in the CI image `rocm/dev-ubuntu-22.04:7.2`. Includes all `InitMicrotest.GinGate_*` and `WindowRegisterNonSym*` cases. Everything below was taken before the rebase (previous head `84a64a92dc`, before #12841 merged). Since then the only code changes on this branch are the fold-test trim above and the log-line resolution. - [x] Host tests on the split branch: 4,912 passed, 0 failed, 5 skipped across 10 binaries, with no compile errors. Run on `dell300x-ccs-aus-k13-09`. - [x] New coverage `WindowRegisterNonSymCuMemTest.VmmWindow_ExportsHandleAndImportsPeers` asserts the import is `ncclMemPersist` with null owners for both peers, plus `.RetainFails_FallsBackToLegacyIpc`, `.MultiSegmentWindow_FailsRegistrationWithoutGathering` and `.LaterSegmentAddressRangeFails_FailsRegistrationWithoutGathering`. - [x] `ginGateAllows()` asserted directly in `init-test.cc` across seven cases: an explicit `0` and `1` on both one and two nodes, the unpartitioned carve-out, and the three default cases (partitioned/one node admitted, partitioned/multi-node refused, unpartitioned/multi-node admitted). Mutating the node term to `return true` fails only `GinGate_MloPartDefaultRefusesPartitionAcrossNodes`, so the new branch is load-bearing. - [x] Gate confirmed on CPX hardware by A/B on `dell300x-ccs-aus-k13-09` (8 ranks, two OAMs, `NCCL_LSA_TEAM_SIZE=4`): `NCCL_GIN_MLOPART=1` reports `globalGinSupport 1` and `=0` reports `globalGinSupport 0`, with `hasMloPart 1` in both. `symmetricSupport` could not be exercised there: that host's driver fails the `HIP_VERSION >= 7.2.0` cuMem check, so `cuMemEnable` is 0 and `symmetricSupport` is 0 whatever the gate decides. - [x] 8-rank CPX reduce-scatter across two OAMs on `dell300x-ccs-aus-k13-09`: `Out of bounds values : 0 OK` at every size, no `hipIpcGetMemHandle` failures, no queue-create failures, no init abort. This run predates #12867 and needed `NCCL_MULTI_RANK_GPU_ENABLE=1` (see below). - [x] `install.sh -l --rocshmem-gin` builds clean (0 errors). - [x] `RCCL env-var changelog`: `NCCL_GIN_MLOPART` is described on the RCCL env-var page, so the check passes instead of asking for `[internal-env]`. - [x] The remaining `AnvilOamMapEngine.*` and `AnvilPciFunctionBus.*` cases (10 tests) compiled standalone against `anvil_engine_map.hpp` from both the #12841 tip (`b47b4f7ccf`) and #13237 (`a674a04501`): all pass on both. The removed fold-result expectations fail 5 of 8 on #12841 and pass on #13237. ## CPX partition identity (AICOMRCCL-2749): fixed by #12867 During CPX verification, `init.cc` refused a multi-rank CPX communicator with "Multiple Ranks are using the same GPU/Partition", because every CPX partition of one OAM reports the same `gpuUuid`. #12867 (merged) fixed the duplicate-GPU guard by also comparing `busId`, which carries the partition's PCI function. The 8-rank run above predates that fix. ## Follow-ups (not in this PR) 1. `NCCL_GIN_MLOPART` gate host assertion at the real call site. The init rung still cannot reach `init.cc`'s connect block: `ncclTopoComputeP2pChannels`, `rcclCommSetP2pShiftSize`, `ncclProfilerPluginInit`, `ncclTransportCheckP2pType` and `ncclProxyCreate` are fail-loud in between. 2. Multi-segment VMM window support in `windowRegisterNonSym`, which needs per-segment handles in `ExchangeEntry`. 3. RCCL-side graceful fallback when a GIN backend fails to connect, so an over-subscribed mesh disables GIN instead of failing `ncclCommInitRank`. #13235 is the rocSHMEM-side fallback and does not cover RCCL. 4. Anvil signal path indexes peers by GIN team rank instead of LSA team position (`signal nRanks=8 != devr->lsaSize=4`): #13429 (AICOMRCCL-2706). 5. `rccl-UnitTestsGinAnvilSdmaFactory` is appended to `RCCL_TEST_EXECUTABLES` but never registered anywhere that runs, unlike the sibling GPU targets at `test/CMakeLists.txt:522` and `:552`. An `add_test()` is not the fix: `test/CMakeLists.txt:42-46` records that nothing in RCCL CI runs ctest, so it would never gate. The gap predates this PR and lives outside its files. JIRA ID: AICOMRCCL-2387 --------- Co-authored-by: Cursor <cursoragent@cursor.com>
8a97123 to
2cb35ac
Compare
There was a problem hiding this comment.
ARGUS
Bottom line: Worth settling before approval: Anvil refuses non-LSA GIN peers at signal bind, after the backend is chosen, so with NCCL_GIN_TYPE unset a multi-node init fails instead of falling back to proxy or GDA (gin_plugin_anvil_sdma.cc:815).
Comment @argus review to re-run, or @argus re-review after pushing.
pr-rocm-systems-13429-oci-rccl-pr-smokeBuilds
FailuresNo failing tests in this run. 15 tests skipped. |
pr-rocm-systems-13429-ruby64-rccl-pr-smokeBuilds
FailuresNo failing tests in this run. 15 tests skipped. |
There was a problem hiding this comment.
ARGUS
Bottom line: Looks approval ready. Signal-free Anvil contexts still put outside the LSA window (gin_plugin_anvil_sdma.cc:1032). That gap predates this PR and is worth its own ticket.
Comment @argus review to re-run, or @argus re-review after pushing.
pr-rocm-systems-13429-oci-rccl-pr-smokeBuilds
FailuresNo failing tests in this run. 15 tests skipped. |
pr-rocm-systems-13429-ruby64-rccl-pr-smokeBuilds
FailuresNo failing tests in this run. 15 tests skipped. |
|
RCCL-Reviewers: this still needs one more approval from that team. @abouteiller's approval already covers rccl-leads and one of the two RCCL-Reviewers approvals. The bind-time LSA check stays in this PR. Unset |
|
Thanks @amd-argus for the Oct 16 review (summary). Here's where each of the remaining low-severity findings stands. The bind-time refusal at
None of these change runtime behavior, so I'm keeping this PR scoped to the LSA check. Thanks again for the careful review. |
0891a02 to
7237ae7
Compare
pr-rocm-systems-13429-oci-rccl-pr-smokeBuilds
FailuresNo failing tests in this run. 15 tests skipped. |
pr-rocm-systems-13429-ruby64-rccl-pr-buildBuilds
FailuresNo failing tests in this run. 183 tests skipped. pr-rocm-systems-13429-ruby64-rccl-pr-smokeBuilds
Failures
15 tests skipped. |
|
@ROCm/rccl-ci requesting an override of the required RCCL PR gate check, for the same reason as #14216. It fails only because of This PR is approved and depends on #14216, which merges first. |
7237ae7 to
278652b
Compare
pr-rocm-systems-13429-oci-rccl-pr-buildBuilds
FailuresNo failing tests in this run. 189 tests skipped. pr-rocm-systems-13429-oci-rccl-pr-smokeBuilds
Failures
15 tests skipped. |
pr-rocm-systems-13429-ruby64-rccl-pr-smokeBuilds
FailuresNo failing tests in this run. 15 tests skipped. |
pr-rocm-systems-13429-oci-rccl-pr-buildBuilds
FailuresNo failing tests in this run. 189 tests skipped. pr-rocm-systems-13429-oci-rccl-pr-smokeBuilds
Failures
15 tests skipped. |
pr-rocm-systems-13429-oci-rccl-pr-smokeBuilds
FailuresNo failing tests in this run. 15 tests skipped. |
pr-rocm-systems-13429-ruby64-rccl-pr-smokeBuilds
FailuresNo failing tests in this run. 15 tests skipped. |
ginAnvilRegisterLsaSignals builds the signal peer table as lsaSelf + (pe - ginRank) * bigSize for every GIN peer. The table is indexed by GIN peer, but each entry is a slot in this rank's LSA window, so it is only valid for peers that are members of the LSA team. When the GIN team is wider than the LSA team (MI300X CPX with 8 ranks and NCCL_LSA_TEAM_SIZE=4, or any RAIL team with more than one rank), entries for the other peers point past either end of the mapped window. The plugin warned and continued, skipped the connectivity check, and left the device to signal through those addresses. Check every GIN peer against lsaRankList before binding, using the RAIL stride for the GIN-to-world mapping, and fail registration with ncclInvalidUsage naming the first peer outside the team. JIRA ID: AICOMRCCL-2706 Co-authored-by: Cursor <cursoragent@cursor.com>
…l spans The check now runs in ginAnvilRegisterSignalSpan, once per resource-window bind. expectSignalsUnbound checks every logical context of the handle, and BindSignals_SpanBaseProbeSizedForWorldRanks uses a one-host rail team so it still passes registration while the world stays wider than the GIN team. Co-authored-by: Cursor <cursoragent@cursor.com>
The symmetric GIN kernels address the rail team, whose peers are all outside the LSA team. Anvil SDMA reaches a peer only through its slot in the local LSA window, so it can never serve them, and requesting them made Anvil's LSA team check fail ncclCommInitRank for applications that never use GIN. Init now records an unsupported GIN backend and leaves the GIN requirement and kernels out, as NCCL_SYM_GIN_KERNELS_ENABLE=0 does. Co-authored-by: Cursor <cursoragent@cursor.com>
278652b to
126528d
Compare
pr-rocm-systems-13429-oci-rccl-pr-buildBuilds
FailuresNo failing tests in this run. 189 tests skipped. pr-rocm-systems-13429-oci-rccl-pr-smokeBuilds
Failures
15 tests skipped. |
pr-rocm-systems-13429-ruby64-rccl-pr-smokeBuilds
FailuresNo failing tests in this run. 15 tests skipped. |
pr-rocm-systems-13429-oci-rccl-pr-buildBuilds
FailuresNo failing tests in this run. 189 tests skipped. pr-rocm-systems-13429-oci-rccl-pr-smokeBuilds
Failures
15 tests skipped. |
pr-rocm-systems-13429-oci-rccl-pr-buildBuilds
FailuresNo failing tests in this run. 189 tests skipped. pr-rocm-systems-13429-oci-rccl-pr-smokeBuilds
Failures
15 tests skipped. |
pr-rocm-systems-13429-ruby64-rccl-pr-smokeBuilds
FailuresNo failing tests in this run. 15 tests skipped. |
pr-rocm-systems-13429-oci-rccl-pr-smokeBuilds
FailuresNo failing tests in this run. 15 tests skipped. |
pr-rocm-systems-13429-ruby64-rccl-pr-smokeBuilds
FailuresNo failing tests in this run. 15 tests skipped. |
Conflict resolutions:
- CHANGELOG: develop cut 10.1.0 and 10.2.0, so move this branch's
entries into the unreleased 10.3.0 section, drop the duplicated
{fmt} line, and keep develop's hipcc entry. The IB verbs-skip entry
now names Anvil-SDMA as GIN type 7, which the code checks.
- GinAnvilPlugin_test: keep QueryFabricA2ALaneGuards and
RegMrSym_FabricRefcountAndExchangeFail, and take develop's G20
BindSignals_GinPeerPastLsaWindowFailsRegistration (#13429 replaced
the ConnCheck_Skipped* cases).
Co-authored-by: Cursor <cursoragent@cursor.com>
TheRock Submodule Bump ActivityNewest first
|
This PR is rebased onto
develop(e7cb4b477a, head126528dfdf; only the CHANGELOG context changed since the tested head7237ae7b96) after #12751, and the check lives in that PR'sginAnvilRegisterSignalSpan. Merge #14216 first: withNCCL_GIN_TYPEunset on a multi-node communicator, Anvil can still be the selected backend until #14216 drops it there, and this check would then failncclDevCommCreatefor Device API users instead of the communicator falling back to the GIN proxy. #12841 and #12742 from the CPX stack have merged; this PR does not depend on #13235 or #13237 and can merge in any order with them. The defect was found while fixing AICOMRCCL-2387 and is follow-up 4 on #12742. The CPX hardware runs below used the CPX stack so that Anvil could initialize on partitions.Motivation
On MI300X CPX with 8 ranks and
NCCL_LSA_TEAM_SIZE=4, the Anvil SDMA GIN backend (NCCL_GIN_TYPE=7) publishes signal addresses that are not mapped on the device. At init it only warns:It then skips the connectivity check and keeps going.
The signal binding path (
ginAnvilBuildSignalPeerAddrs, called fromginAnvilRegisterSignalSpanandginAnvilBindContextSignals) builds the peer signal table aslsaSelf + (pe - ginRank) * bigSizefor every GIN peer. The device indexes this table by GIN peer (remoteSignalAddr,resolveRemotePeerVa), but each entry is a slot in this rank's LSA window. That is only correct for peers in the same LSA team, where GIN position and LSA slot agree. On rank 0, entries for GIN peers 4–7 point past the end of the window. On rank 4, entries for peers 0–3 point before its start.The ticket suggests rebasing the table on the LSA origin and extent. That would move the in-team peers' entries off their real slots, so this PR does not do that. Writing 0 for out-of-team peers is not safe either:
signalPeerreturns silently on a null address, so the wait would hang, andginAnvilResolvePeerVaturns a null base into0 + offset.The same problem affects any
NCCL_GIN_CONNECTION_RAILGIN team with more than one rank. Its peers are on other hosts and never have a slot in the local window.This PR makes these configurations fail at registration with a clear error. The symmetric kernels, which request GIN internally and whose GIN peers are always rail peers outside the LSA team, now skip GIN on Anvil, so applications that never ask for GIN are not affected.
Technical Details
src/gin/gin_plugin_anvil_sdma.cc:ginAnvilFirstSignalPeerOutsideLsa(comm, nRanks, ginRank). For each GIN peer, it computes the LSA slot that the table entry points at. It accepts the peer only when that slot is inside[0, lsaSize)andlsaRankList[slot]is the peer's world rank. The GIN-to-world mapping uses the same stride asteamRankToGinRank:contiguousRanksPerHostunder RAIL, otherwise 1.ginAnvilRegisterSignalSpancalls the helper before it builds the peer table or registers the span in the IPC table. It runs once per resource-window bind, so it covers every logical context of every pending GIN context. If a peer fails, it logs aWARNnaming the peer, GIN rank and size,lsaSelfandlsaSize. The warning tells the user to setNCCL_LSA_TEAM_SIZEto cover the GIN team or select anotherNCCL_GIN_TYPE. Registration then returnsncclInvalidUsage, whichncclGinAnvilBindResourceWindowSignalspropagates to the caller that created the device communicator (see the next list).test/gin/GinAnvilPlugin_test.cpp:expectSignalsUnbound. It checks that a failed registration leftsignalsandsignal_remote_addrsnull in every logical context of the handle, added nothing to the IPC table, and ran no connectivity check.ConnCheck_SkippedWhenLsaSizeMismatchis nowBindSignals_GinPeerPastLsaWindowFailsRegistration.BindSignals_GinPeerBeforeLsaWindowFailsRegistration: the CPX case seen from the second LSA team (rank 2 of 4,lsaSize2).ConnCheck_SkippedOnRailConnectionis nowBindSignals_RailGinTeamFailsRegistration. In its layout, the rail peer's slot is inside the window but holds the wrong world rank, so the test only passes if the RAIL stride is applied.ConnCheck_UsesLsaTeamForBootstrapused a reversedlsaRankslist that no real communicator produces. It now uses rank 1 withlsaSelf1 and checks that the bootstrap uses the intra-node rank and peer list.connectCollnow takes the GIN rank.BindSignals_SpanBaseProbeSizedForWorldRanks(added by fix(gin): de-alias Anvil signals across logical contexts #12751) used a two-rank RAIL GIN team, which now fails registration. It now uses one host of 8 ranks, where the rail team is this rank alone, so the world (8 ranks) is still wider than the GIN team (1 rank) and the probe buffer sizing is still tested.src/sym_kernels.cc,src/include/sym_kernels.h:ncclSymkState::ginBackendUnsupported.ncclSymkInitOncesets it when the symmetric kernels need GIN (LSA team smaller than the communicator) andncclGetRailedGinTypereportsNCCL_GIN_TYPE_ANVIL_SDMA. In that case it logs anINFOline and does not add the GIN requirement to its internal device communicator, so Anvil signals are never bound during init.ncclSymkMasktreats GIN as unavailable when the flag is set. Because the mask keeps only GIN kernels when GIN is needed, this disables the symmetric kernels for that communicator, the same asNCCL_SYM_GIN_KERNELS_ENABLE=0; collectives use the regular kernels.ncclGinSetDefaultBackendruns beforencclSymkInitOnceininit.cc, so the backend is known when the flag is computed.test/host/sym-kernels-test.cc: replacesncclGetRailedGinTypewith a hook.SymKernelMicrotest.GinBackendUnsupported_OnlyForAnvilSdmachecks that only Anvil sets the flag (Anvil, proxy, none).SymKernelMaskTest.NeedGinTrue_GinBackendUnsupported_EverythingClearedchecks that the mask is empty when GIN is needed and the flag is set.CHANGELOG.md: added a "Resolved issues" entry. It notes thatncclDevCommCreatecalls requesting GIN in these configurations used to succeed and now fail, and that the symmetric kernels no longer use GIN with Anvil, so communicator init and collectives are unaffected.Behavior changes reviewers should know about:
NCCL_GIN_TYPE=7andNCCL_LSA_TEAM_SIZEsmaller than the communicator,ncclDevCommCreatecalls that request GIN used to succeed and now fail withncclInvalidUsageand the new warning.ncclCommInitRankand collectives are unaffected: the symmetric kernels skip GIN on Anvil (seesym_kernels.ccabove), so for these communicators they are disabled instead of failing init. On hardware, a plainall_gather_perfin this setup passes on this PR (see Test Result).NCCL_GIN_TYPEunset, Anvil can be one of several active backends and ranks ahead of the GIN proxy.ncclGinDevCommSetupfalls back between backends, but signal binding happens after that choice and has no fallback. fix(rccl/gin): drop Anvil SDMA backend on multi-node communicators #14216 drops Anvil on multi-node communicators so the proxy is chosen there; merge it first. On a single node with a narrowed LSA team, a Device API communicator that selected Anvil now fails instead of signaling through unmapped addresses. This has not been run multi-node.Related:
comm->topo->nHosts > 1.ginAnvilBuildSignalPeerAddrs/ginAnvilRegisterSignalSpan. The rebase carries the check intoginAnvilRegisterSignalSpanand removes the old warnings there; the second commit adapts the tests to per-context signal spans. The branch is now three commits; an attempt to refuse out-of-team peers increateContext, and its revert, were dropped.regMrSym(RegisterVmmwithlsaSelf/lsaSize) has the same index-space mismatch. The stride path inresolveRemotePeerVausually bypasses it, and this PR does not change it.Issue Tracking
JIRA ID: AICOMRCCL-2706
Test Plan
rccl-UnitTestsGinAnvilPlugin --gtest_filter='*BindSignals*:*ConnCheck*', then the fullrccl-UnitTestsGinAnvilPluginsuite. RequiresENABLE_ROCSHMEM_GINand ROCm 6.4 or later.rccl-UnitTestsMicroSymKernels(host microtests).alltoall_perfandall_gather_perfwithNCCL_GIN_TYPE=7, on CPX ranks split across two OAMs (MI355X and MI300X) and on SPX (MI300X), each on this PR's library and on a baseline library with the plugin file fromdevelop:-D 3runs to complete with the data check passing.-D) with a narrowed LSA team: expect them to pass, with the symmetric-kernel skip logged on every rank.Test Result
On MI355X with Linux 6.8, Anvil passes
alltoall_perf -D 3andall_gather_perf -D 3data checks when the GIN and LSA teams match, in SPX with 8 ranks and in CPX with 4. When the LSA team is narrowed, this PR failsncclDevCommCreateon every rank with the new warning, and plain collectives pass. On the same layout, the baseline skips the connectivity check and then hangs or fails. The MI300X host repeats the failure-path results.With the symmetric-kernel skip (
developdaf7ef33e4, head7237ae7b96)Same MI355X host and build as the next section, SPX, 8 ranks, this PR's library only. Logs are under
~/pr13429/logs-port2.rccl-UnitTestsGinAnvilPlugin: 48 of 48 passed.rccl-UnitTestsMicroSymKernels: 69 of 69 passed, including the two new tests.alltoall_perf -D 3,NCCL_LSA_TEAM_SIZE=8all_gather_perf -D 3,NCCL_LSA_TEAM_SIZE=8alltoall_perf -D 3,NCCL_LSA_TEAM_SIZE=4ncclDevCommCreategroup fails (common.cu:2705,invalid usage) with the new warning on all 8 ranksall_gather_perf -D 3,NCCL_LSA_TEAM_SIZE=4all_gather_perf,NCCL_LSA_TEAM_SIZE=4ncclCommInitRankat the previous head)all_gather_perf -R 2,NCCL_LSA_TEAM_SIZE=4alltoall_perf -R 2,NCCL_LSA_TEAM_SIZE=4Example lines:
The sections below are from earlier heads, before the symmetric-kernel skip. Where they say "Fails in
ncclCommInitRank", this head passes instead.After the rebase onto
develop(1ba7048298, head2cb35ac234)Built on the MI355X host below (gfx950, ROCm 10.1.0, Linux 6.8.0-101) with
install.sh --rocshmem-gin, then-DBUILD_TESTS=ON -DGIN_ANVIL_UNIT_TESTS=ON. The baseline library usesgin_plugin_anvil_sdma.ccfromdevelop(1ba7048298), which includes #12751. Logs are under~/pr13429/logs-porton that host.rccl-UnitTestsGinAnvilPlugin --gtest_filter='*BindSignals*:*ConnCheck*': 30 of 30 passed.rccl-UnitTestsGinAnvilPlugin: 48 of 48 passed.SPX, 8 ranks, one per GPU:
alltoall_perf,NCCL_LSA_TEAM_SIZE=8all_gather_perf,NCCL_LSA_TEAM_SIZE=8alltoall_perf,NCCL_LSA_TEAM_SIZE=4invalid usageon all 8 ranks, new warningall_gather_perf,NCCL_LSA_TEAM_SIZE=4all_gather_perf,NCCL_LSA_TEAM_SIZE=4ncclCommInitRank, new warningall_gather_perf,NCCL_LSA_TEAM_SIZE=4,NCCL_SYM_GIN_KERNELS_ENABLE=0alltoall_perf,NCCL_LSA_TEAM_SIZE=4,NCCL_SYM_GIN_KERNELS_ENABLE=0ncclDevCommCreategroup (common.cu:2705), new warningThe CPX cases were not re-run after the rebase, because the host was in SPX and changing its partition mode would disturb other users. The tables below are from the pre-rebase head.
Before the rebase
Unit tests pass (MI300X host below, ROCm 7.2.0, built at
9e444f3ab5withinstall.sh --rocshmem-gin, then-DBUILD_TESTS=ON -DGIN_ANVIL_UNIT_TESTS=ON):rccl-UnitTestsGinAnvilPlugin --gtest_filter='*BindSignals*:*ConnCheck*': 23 of 23 passed, including the three newBindSignals_*FailsRegistrationtests.rccl-UnitTestsGinAnvilPlugin: 37 of 37 passed.Each hardware case ran twice: on this PR's library, and on a baseline library built from the same tree with
gin_plugin_anvil_sdma.ccfromdevelop(2a4afbe5c4). Common settings wereNCCL_GIN_TYPE=7,NCCL_CUMEM_ENABLE=1and-R 2 -D 3, unless a row says "plain" (no-D). Runs were killed at 300 s.MI355X:
smci355-ccs-aus-m03-178× MI355X (gfx950), NPS1, Linux 6.8.0-101, amdgpu 7.1-dev, ROCm 10.1.0, built at
8a97123fff. No kernel-gate bypass was needed. Logs are under~/pr13429/logson that host.SPX, 8 ranks, one per GPU (this PR's tree only):
alltoall_perf,NCCL_LSA_TEAM_SIZE=8lsaSize=8), conn-check OK on all 8 ranks, 0 wrong valuesall_gather_perf,NCCL_LSA_TEAM_SIZE=8alltoall_perf,NCCL_LSA_TEAM_SIZE=4invalid usageon all 8 ranks, new warningCPX, 4 ranks (this PR plus the CPX stack: #12841, #13235, #13237 and #12742 at their 2026-10-14 heads, when the even-engine change was still in #13237). Ranks 0–1 are on two partitions of one OAM and ranks 2–3 on two partitions of another (
HIP_VISIBLE_DEVICES=0,1,8,9,NCCL_MULTI_RANK_GPU_ENABLE=1):alltoall_perf, LSA team unsetall_gather_perf, LSA team unsetalltoall_perf,NCCL_LSA_TEAM_SIZE=2invalid usageon all 4 ranks, new warningall_gather_perf,NCCL_LSA_TEAM_SIZE=2all_gather_perf,NCCL_LSA_TEAM_SIZE=2ncclCommInitRank, new warningall_gather_perf,NCCL_LSA_TEAM_SIZE=2,NCCL_SYM_GIN_KERNELS_ENABLE=0alltoall_perf,NCCL_LSA_TEAM_SIZE=2,NCCL_SYM_GIN_KERNELS_ENABLE=0ncclDevCommCreategroup (common.cu:2705), new warningExample warning (rank 2, on the second OAM):
The baseline prints the warnings from the ticket on the same run, for example
signal nRanks=4 != devr->lsaSize=2 (rank 0)andctx->rank=2 != devr->lsaSelf=0 (signal peer indexing may be wrong).MI300X:
banff-cyxtera-cx56-58× MI300X (gfx942), NPS1, Linux 5.15, amdgpu 6.16.13, ROCm 10.1. Logs are under
~/pr13429/logs-r10on that host. On this host, RCCL turns cuMem off below Linux 6.8, and without cuMem rccl-tests skips every-D 3run. These runs therefore add an experiment-only patch that skips that kernel gate (RCCL_EXP_SKIP_KERNEL_GATE=1). On this kernel, cuMem peer mappings are broken, so the matched-team runs fail the connectivity check on both libraries. The failure path still shows, because the new check runs before any peer is signaled.NCCL_RMA_DISABLE=1was used whenever the LSA team was narrowed, because the RMA proxy's memory registration fails on this host before GIN is reached.NCCL_LSA_TEAM_SIZE=4,alltoall_perfinvalid usageon all 8 ranks with the new warningall_gather_perfNCCL_LSA_TEAM_SIZE=3,alltoall_perfNCCL_LSA_TEAM_SIZE=4, plainall_gather_perfncclCommInitRankNCCL_SYM_GIN_KERNELS_ENABLE=0NCCL_LSA_TEAM_SIZE=4,alltoall_perf,NCCL_SYM_GIN_KERNELS_ENABLE=0ncclDevCommCreategroupNCCL_LSA_TEAM_SIZE=4, plainall_gather_perf,NCCL_GIN_TYPEunsetgin_host_proxy.cc:477), before Anvil bindsNotes
SDMA queue budget exhausted: 7 queue(s) taken by this process + 1 requested, limit 8; on MI355X the driver returnsNO_MEMORYfor the 8th queue). That happens inconnect, before signal binding, on this PR and on the baseline alike. On MI355X it happens withNCCL_LSA_TEAM_SIZE=8too, whether the 8 partitions are on one OAM, split 4+4, or spread one per OAM. The 4-rank (MI355X) and 6-rank (MI300X) layouts stand in for it. The limit of 8 is the even-engine CPX budget, which fix(rocshmem): make Anvil SDMA usable on MI300X CPX and QPX, DPX up to two OAMs #12841 now ships; fix(rocshmem): skip GPU-unreachable SDMA doorbell slots in Anvil (ROCM-32598 workaround) #13237's slot-aware budget raises it to 12, and the 8-rank layout has not been retried with that budget.anvil_engine_map.hpp. fix(rocshmem): make Anvil SDMA usable on MI300X CPX and QPX, DPX up to two OAMs #12841 now includes it.Submission Checklist