Skip to content

fix(rccl): fixed udma balancing for p2p comms (develop) - #12948

Merged
alex-breslow-amd merged 5 commits into
developfrom
users/asanniko/ROCM-31118-develop
Oct 16, 2026
Merged

alex-breslow-amd merged 5 commits into
developfrom
users/asanniko/ROCM-31118-develop

Conversation

@alexander-sannikov

@alexander-sannikov alexander-sannikov commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

Motivation

Multi-node alltoall on MI355X with AI-NIC regresses at all message sizes in the August RCCL code drop. The root cause is uneven use of the two AINIC uDMA pipelines by P2P QPs.

[internal-env]

Technical Details

  • Moves uDMA pipeline selection out of ncclIbCreateQpIonic into ncclIbCastSelectUDMA and adds RCCL_IB_UDMA_POLICY:
    • 0 (default): current behavior. With QP sharing, QPs alternate by sharing group (or by QP index when there is one group); otherwise every QP of a channel is pinned to one pipeline, assigned alternately as channels are first seen.
    • 1: P2P QPs round-robin across pipelines in creation order; collectives keep the policy 0 behavior.
    • 2: the PD mask is left unchanged, so the driver picks the pipeline.
    • 3: each connection is split across both pipelines; the channel id picks the starting pipeline and consecutive per-device QPs alternate.
  • Adds qpIdx and IbCastQpStripe to ncclIbQpCreateAttr, set on the sender, receiver and AINIC port-recovery QP creation paths.
  • Holds the dedicated nccl_udma_mutex from pipeline selection through ibv_create_qp, because the PD and its uDMA mask are shared by all comms on the device.
  • Warns at init when RCCL_IB_UDMA_POLICY is outside 0-3; such values behave as 0.

The default stays 0 because the new policies regress other workloads, so they are opt-in until they have been evaluated with the customer. This is the develop counterpart of #12390, which targets rccl/drop_2026-08.

Issue Tracking

JIRA ID: ROCM-31118

Test Plan

  • Compile check of the changed translation units in the TheRock ROCm 7.14 container.
  • Multi-node alltoall_perf on MI355X + AI-NIC with each RCCL_IB_UDMA_POLICY value.

Test Result

The compile check passes.

BASE1, BASE2 (both develop 5909ad9), PR (ba423a0)

2 nodes results (mi355+AINIC):

Alltoall (out-of-place busbw, GB/s; deltas are against base1 matched repeat by repeat, with wins out of 8)

build rccl-tests Avg busbw Δ vs base1 16M–256M 1G–8G
base1 61.50 reference 70.89 76.32
base2 (noise floor) 60.92 −0.94% (2/8) −0.66% −1.20%
PR, policy unset 61.60 +0.17% (5/8) −0.54% +1.15%
PR, policy 1 67.23 +9.32% (8/8) +2.80% (8/8) +19.13% (8/8)
PR, policy 2 67.10 +9.11% (8/8) +2.71% (8/8) +18.98% (8/8)
PR, policy 3 67.18 +9.24% (8/8) +2.89% (8/8) +19.15% (8/8)

All_reduce and all_gather (regression check runs)

build all_reduce Avg busbw Δ (wins/8) all_gather Avg busbw Δ (wins/8)
base1 221.44 reference 195.62 reference
base2 (noise floor) 221.00 −0.20% (2/8) 195.73 +0.05% (5/8)
PR, policy unset 221.79 +0.16% (5/8) 195.10 −0.27% (4/8)

4 nodes results (mi355+AINIC):

Alltoall (out-of-place busbw, GB/s; deltas are against base1 matched repeat by repeat, with wins out of 8)

arm Avg busbw 16M–256M 1G–8G
base1 46.34 54.08 54.20
base2 (noise floor) +0.41% (5/7) −0.00% (2/7) +1.20% (5/7)
PR, policy unset −0.68% (2/7) −0.62% (3/7) −1.26% (3/7)
policy 1 +6.11% (7/7) +4.48% (7/7) +9.76% (7/7)
policy 2 +3.92% (7/7) +2.76% (7/7) +6.89% (7/7)
policy 3 +3.32% (5/6) +2.07% (5/6) +7.03% (5/6)

Allreduce/Allgather is flat as for 2N.

Submission Checklist

(AI Asist)

@github-actions

github-actions Bot commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

Undocumented RCCL default-behavior changes

Variable Trigger Old default New default Missing Locations
RCCL_IB_UDMA_POLICY added 0 CHANGELOG, docs projects/rccl/src/transport/net_ib_cast/connect.cc:71
projects/rccl/src/transport/net_ib_cast/connect.cc:86
projects/rccl/src/transport/net_ib_cast/init.cc:29
projects/rccl/src/transport/net_ib_cast/init.cc:665
projects/rccl/src/transport/net_ib_cast/init.cc:667

Paste into projects/rccl/CHANGELOG.md:

  • RCCL_IB_UDMA_POLICY (default 0):

Describe these changes in projects/rccl/docs/api-reference/env-variables.rst, or put [internal-env] in the PR title or body if the variable is not meant for users:

  • RCCL_IB_UDMA_POLICY (default 0)

@therock-pr-bot

therock-pr-bot Bot commented Oct 6, 2026 •

Copy link
Copy Markdown

✅ All Policy Checks Passed

Check Status Details
📝 PR Description ✅ Pass —
⛔ Forbidden Files ✅ Pass —
🧪 Unit Test ⚠️ Warning Error: Source/code files changed without an accompanying unit test.
Expected: add at least one test file named like test_<name>.py / test_<name>.cpp (or <name>_test.*).
Current: code file(s) changed: projects/rccl/src/transport/net_ib_cast/common_cast.h, projects/rccl/src/transport/net_ib_cast/connect.cc, projects/rccl/src/transport/net_ib_cast/connect_cast.h, projects/rccl/src/transport/net_ib_cast/init.cc, projects/rccl/src/transport/net_ib_cast/p2p_resiliency_recovery_ainic.cc; no test file found
🚫 Draft PR 🔜 To Be Enabled —
🚩 Feature Flag 🔜 To Be Enabled —
📊 Code Coverage 🔜 To Be Enabled —

🎉 All policy checks passed!

📖 Need help? See the Policy FAQ for details on every check and how to fix failures.

🙋 Wish to Override Policy?

@therock-pr-bot

therock-pr-bot Bot commented Oct 6, 2026

Copy link
Copy Markdown

🚫 Please fix the failed policies before requesting reviews.

The following policy checks failed:

  • ❌ PR Description

The Not ready to Review label has been added to this PR.
Once all policies pass, the label will be removed automatically.

@alexander-sannikov
alexander-sannikov marked this pull request as ready for review October 6, 2026 19:01
@alexander-sannikov
alexander-sannikov requested review from a team October 6, 2026 19:01

@amd-argus amd-argus Bot left a comment

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.

ARGUS

Bottom line: Worth settling before approval: IB_UDMA_POLICY defaults to 0, so the p2p balancing this PR is named for only arms when a user opts in, and nothing in the tree sets it.

Comment @argus review to re-run, or @argus re-review after pushing.

@amd-argus amd-argus Bot left a comment

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.

ARGUS

Bottom line: Worth settling before approval: connect.cc does not compile at this head. Line 83 redefines ncclIbCastUBMALow instead of defining ncclIbCastUBMAHigh, and line 85 returns the deleted type ncclIbCastUBMA.

Comment @argus review to re-run, or @argus re-review after pushing.

@amd-argus amd-argus Bot left a comment

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.

ARGUS

Bottom line: Worth settling before approval: ncclIbCreateQpIonic now holds the general device mutex across ibv_create_qp, so AINIC QP creation serializes against MR registration on the default path.

Comment @argus review to re-run, or @argus re-review after pushing.

@alex-breslow-amd alex-breslow-amd left a comment

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.

You have a lot of duplicate code with attribute creation spread across multiple files and functions. This should get cleaned up.

@sunguobao

Copy link
Copy Markdown
Contributor

@karthikarum Since you were commenting on my PR re: this issue.. #12275

what you think about this PR, kindly take a look as well? thanks!

@karthikarum

Copy link
Copy Markdown
Contributor

@karthikarum Since you were commenting on my PR re: this issue.. #12275

what you think about this PR, kindly take a look as well? thanks!

Hi @sunguobao
I was discussing aboutt his with Alex and since this PR comprises of all aspects that we wanted to bring-in (as discussed in PR#12275). We can close PR #12275 for now and continue on this PR #12948 for the enhancements.

alexander-sannikov and others added 5 commits October 16, 2026 09:19
The previous commit left connect.cc uncompilable: the high-pipeline
constant was declared under the low name and ncclIbCastSelectUDMA
still returned the removed enum type. Fix both, rename the UBMA
identifiers to UDMA to match the rest of the feature, and warn at
init when RCCL_IB_UDMA_POLICY is outside 0-3 instead of silently
falling back to policy 0.

Co-authored-by: Cursor <cursoragent@cursor.com>
- Name the RCCL_IB_UDMA_POLICY values with enum struct
  ncclIbCastUDMAPolicy (First/Last bound the init range check) and
  document that QP sharing overrides channel affinity.
- Drop qpIndexInDev in favour of qpIdx. A new IbCastQpStripe helper
  computes devIndex and qpIdx and fails with ncclInternalError on a zero
  device count; AINIC port recovery restores qpIdx after
  IbCastQpCreateAttrInitSharing resets it.
- Guard mask selection and ibv_create_qp with a dedicated per-device
  uDMA mutex instead of ncclIbDev::mutex, so QP creation no longer
  serializes against MR registration.
- Warn once per device when ionic_dv_pd_set_udma_mask fails.
- Log the active uDMA policy at init.

Co-Authored-By: Claude <noreply@anthropic.com>
@VadimKutovoi
VadimKutovoi force-pushed the users/asanniko/ROCM-31118-develop branch from accaf7d to 5909ad9 Compare October 16, 2026 08:24
@VadimKutovoi VadimKutovoi reopened this Oct 16, 2026
@VadimKutovoi

Copy link
Copy Markdown
Contributor

@argus re-review

@amd-argus amd-argus Bot left a comment

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.

ARGUS

Bottom line: Nothing new worth raising; still open from earlier: connect.cc:93. Worth clearing before approval.

Comment @argus review to re-run, or @argus re-review after pushing.

@amd-arozanov amd-arozanov left a comment

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.

The PR description is outdated after ba423a0: qpIndexInDev was removed in favor of qpIdx and IbCastQpStripe, and QP creation now uses the dedicated nccl_udma_mutex instead of the general device mutex. Please update these two bullets before merge?

@alex-breslow-amd alex-breslow-amd left a comment

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.

Two questions about whether the opt-in policies balance the MI355X single-QP alltoall config, plus two nits. The Test Result section still says performance numbers will come after the runs. Since the default stays at 0 and the opt-in policies are the whole fix, could you add those numbers before merge?

@alex-breslow-amd alex-breslow-amd left a comment •

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.

Accepting to unblock. Please consider the comments in the review and put up a follow-up PR given that this needs to move fast. This version as is is acceptable for now.

@alex-breslow-amd
alex-breslow-amd merged commit a208276 into develop Oct 16, 2026
87 of 132 checks passed
@alex-breslow-amd
alex-breslow-amd deleted the users/asanniko/ROCM-31118-develop branch October 16, 2026 21:17
@systems-assistant

Copy link
Copy Markdown
Contributor

TheRock Submodule Bump Activity

Newest first

VadimKutovoi added a commit that referenced this pull request Nov 3, 2026
## Motivation

Follow-up to #12948 (`RCCL_IB_UDMA_POLICY`), addressing the review
comments that were left after it merged:
documentation for the new variable, a guard on the policy enum range,
one shared validity check, a consistency
check in AINIC QP recovery, and the QP-count requirement of
`SplitConnection`.

## Technical Details

One commit per review item:

- **Count sentinel for `ncclIbCastUDMAPolicy`** (`common_cast.h`):
`Last` is now `Count - 1`, with `static_assert`s
that `First == ChannelAffinity == 0` and `Last == SplitConnection`.
Adding a policy without updating the asserts
fails to compile. Nothing `switch`es over the enum, so `Count` cannot
trigger `-Wswitch`.
- **Shared range check**: `ncclIbCastUDMAPolicyIsValid()` in
`common_cast.h`, used by both `init.cc` (WARN +
fallback) and `ncclIbCastGetUDMAPolicy()` in `connect.cc`. No behavior
change.
- **Recovery `devIndex` check** (`p2p_resiliency_recovery_ainic.cc`):
the device index from `IbCastQpStripe` must
match `localQp->devIndex`; otherwise WARN and return
`ncclInternalError`. Connect sets `devIndex` from the same
stripe, so this cannot fire today; it catches the striping assumption
behind `qpIdxInDev` breaking later.
- **`SplitConnection` QP-count note** (comments only): the default
`NCCL_IB_QPS_PER_CONNECTION` of 2 already
splits a connection. With one QP per device per connection
(`NCCL_IB_QPS_PER_CONNECTION=1`, or
`RCCL_IB_QPS_PER_P2P=1` for P2P) `qpIdx` is always 0 and the policy
reduces to channel affinity by channel-id
  popcount parity. RMA comms also use one QP.
- **Docs**: `RCCL_IB_UDMA_POLICY` entry in
`docs/api-reference/env-variables.rst` and a CHANGELOG "Added" bullet.
Policy 0 pins each channel's send QPs, and separately its receive QPs,
to one pipeline per device. Policy 1
round-robins P2P QPs on one per-device counter. Policy 3's default of
two QPs per connection is enough;
  splitting is lost with one QP per connection and on RMA comms.

Default behavior (`RCCL_IB_UDMA_POLICY` unset = 0) is unchanged. A
per-direction round-robin counter for policy 1
was tried and dropped: it did not improve performance.

## Issue Tracking

JIRA ID: ROCM-31118

## Test Plan

- Compile check of the changed translation units (`connect.cc`,
`init.cc`, `p2p_resiliency_recovery_ainic.cc`, and
  through them `common_cast.h`) on develop `df181d33333`.
- Negative compile check: adding a policy value before `Count` without
updating the asserts fails the build.
- `rccl_check_default_behavior.py --base-ref <develop>`: passes.

## Test Result

- Compile: 0 errors, no new warnings in the touched files.
- Env-var check: "No undocumented RCCL or NCCL environment-variable
changes."

For reference, #12948's validation on TW (MI355X + AINIC, 8 reps,
interleaved arms, 144/144 runs clean per
stage) ran with the default 2 QPs per connection, where this PR does not
change the assignment. Policy unset was
flat vs develop on alltoall/all_reduce/all_gather at 2N and 4N. alltoall
Avg busbw: 2N +9.3% (policy 1, 8/8),
4N +6.0% (policy 1, 8/8); policies 2 and 3 +3.6% at 4N.

## Submission Checklist

- [x] Look over the contributing guidelines at
https://github.com/ROCm/rocm-systems/blob/develop/CONTRIBUTING.md.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants