Repository navigation
Conversation
LL can deadlock single-node gfx1200/gfx1201 collectives: the LL FIFO polls in prims_ll.h use non-temporal loads without the acquire ordering that the Simple protocol uses on gfx120x. Automatic selection still picked LL for small Broadcast/Reduce/AllGather/ReduceScatter/AllReduce calls unless NCCL_P2P_DISABLE=1 was set; every collective in PyTorch's FSDP state-dict test (4 B to 60.6 KB per rank) selected LL on gfx1201. Select Simple for automatic single-node gfx120x collectives. NCCL_PROTO still overrides the choice, and multi-node behavior, including the NCCL_P2P_DISABLE override, is unchanged. JIRA ID: ROCM-29721 Refs: #5480 Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
✅ 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.
🟡 Changes recommended
The rearchitected enqueue path bypasses this override and can still automatically select unsafe LL protocols.
1 open finding
What changed in this PR
Defaults single-node gfx120x collectives to Simple protocol to avoid LL deadlocks.
Changes:
- Forces Simple for automatic single-node gfx120x selection.
- Updates protocol-selection microtests.
- Documents the fix in the changelog.
| File | Description |
|---|---|
projects/rccl/src/rccl_wrap.cc |
Applies the Simple protocol fallback. |
projects/rccl/test/host/wrap-test.cc |
Tests single- and multi-node gfx120x behavior. |
projects/rccl/CHANGELOG.md |
Records the resolved hang. |
🧠 Review effort: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
…CM-29721-gfx12-rccl-deadlock Co-authored-by: Cursor <cursoragent@cursor.com> # Conflicts: # projects/rccl/CHANGELOG.md
Add UpdateCollectiveProtocol_Gfx120xUserOverrideKeepsLL so NCCL_PROTO=LL must survive on single-node gfx1200/gfx1201; the gfx950 override test could not catch the gfx120x arm ignoring NCCL_PROTO. Use a struct of cases in Gfx120xSingleNodeDefaultsSimple instead of parallel arrays, and stop calling gfx120x LL functional in the NCCL_P2P_DISABLE comment, which now only matters for multi-node. JIRA ID: ROCM-29721 Co-authored-by: Cursor <cursoragent@cursor.com>
|
@argus re-review |
|
@jinchen62 I can't trigger on this PR yet -- your association here reads as |
There was a problem hiding this comment.
ARGUS
Findings
1 finding(s) that could not be posted as inline comments
projects/rccl/src/rccl_wrap.cc:124(Low) rcclGetProtoForGfx120x has no production caller left after this change; only the microtests reach itrcclGetProtoForGfx120xat rccl_wrap.cc:124 has no production caller after this change: the single call site was the one replaced at rccl_wrap.cc:186, and the only remaining references are the microtests at wrap-test.cc:179-223. Its siblingrcclGetProtoForGfx110xis still live at rccl_wrap.cc:196, so the two read as symmetric but are not. Since the plan is to keep the table until theprims_ll.hloads are fixed, could you put that note on the function itself, so the next reader can tell it is intentionally dormant rather than in use?
Bottom line: Looks approval ready. All three prior findings are fixed; what is left is a follow-up question on whether multi-node gfx120x was deliberately left on LL.
Comment @argus review to re-run, or @argus re-review after pushing.
Add Broadcast and Reduce cases at 4 B per rank to Gfx120xSingleNodeDefaultsSimple, so routing only the small-cutoff funcs back to rcclGetProtoForGfx120x() now fails the test. Note on rcclGetProtoForGfx120x() that it has no production caller while single-node gfx120x defaults to Simple, and is kept to re-enable LL once the prims_ll.h loads are fixed. JIRA ID: ROCM-32656 Co-authored-by: Cursor <cursoragent@cursor.com>
|
Re the |
|
@argus re-review |
|
@jinchen62 I can't trigger on this PR yet -- your association here reads as |
alex-breslow-amd
left a comment
There was a problem hiding this comment.
Can you test the 10.2 RCCL? This is likely fixed in 10.2 after #10670.
|
@alex-breslow-amd The failure is already on a 10.2 nightly: Bilal's runs used My 2x gfx1201 host can't reproduce the hang on any build, so it can't settle this. Current develop (with #10670) and From the code, I don't expect #10670 to cover this: on gfx1200/gfx1201, |
|
also watching this. just ran into the same thing, and your flag worked instantly. removed the deadlock. /edit - my setup is 9600s, but same architecture id. running rocm 10.1/7.2.4 for A/B testing, qwen 3.8 with 4 GPUs. NCCL_PROTO=Simple is exactly what moved the needle. what other flags are passable? curious. especially for GPU-GPU comms to experiment with latency differences |
|
@xeacottx Thanks, that's a useful data point: another 4-GPU gfx120x setup hitting the same deadlock, fixed by Could you post the On other settings: the environment variables are documented in env.rst, with tuning notes in performance_and_tuning.rst. For GPU-to-GPU latency, the main knobs are |
|
thank you for getting back to me @jinchen62 let me give this a go tomorrow or friday. but with 10.1, the version that loaded was... i think 2.30.7. prior to that 7.2.4 i was using 2.27.0 and didn't experience any weirdness |
|
Closing this for now. Bilal's results on the 4x gfx1201 host showed the That leaves no 10.2 reproducer for an LL hang on gfx120x. One note on #10670: before it, gfx1201 polled with two 64-bit non-temporal loads, but the 10.1.0a20260822 nightly (Clang 23) already fused them into a single |

JIRA ID : ROCM-32656
Motivation
PyTorch FSDP can hang in RCCL collectives on multi-GPU gfx1201 hosts. On a 4x gfx1201 host running a recent ROCm 10.2 nightly,
TestStateDict.test_fsdp(test/distributed/checkpoint/test_state_dict.py) timed out after 300 s during distributed backward in 3 of 3 runs. #5480 reports the same signature (all GPUs spinning at 100%, no progress) for vLLM TP=2 on dual gfx1201, andNCCL_PROTO=Simpleis the confirmed workaround.Technical Details
rcclUpdateCollectiveProtocol()sends single-node gfx1200/gfx1201 collectives throughrcclGetProtoForGfx120x(), which picks LL for small messages (per rank: Broadcast <= 1.5 KiB, Reduce <= 8 KiB, AllGather/ReduceScatter <= 96 KiB, AllReduce <= 16 KiB). The only existing guard forces Simple whenNCCL_P2P_DISABLE=1is set, so both P2P/IPC paths and topology-routed SHM paths (for example GPUs without direct P2P, orNCCL_P2P_LEVEL=PIX) still get LL.prims_ll.h(readLL,readLLBeginAll,readLLFinish) use plain non-temporal loads. They have neither the acquire ordering that Simple uses on gfx120x (loadStepValueinprims_simple.h), nor the cache-bypassing load gfx11 uses, nor the system-scope load gfx1250 uses.NCCL_PROTOoverride, multi-node gfx120x behavior (including theNCCL_P2P_DISABLEoverride), tuner-plugin and PAT selections (they skip this function), send/recv protocol selection, and all other architectures.rcclGetProtoForGfx120x()and its cutoff table are kept, and still unit-tested, so LL can be re-enabled once theprims_ll.hloads are fixed for gfx120x.NCCL_PROTO=Simple. Not benchmarked in this PR.projects/rccl/CHANGELOG.md.Issue Tracking
GitHub issue: #5480
JIRA ID: ROCM-32656
Test Plan
rccl-UnitTestsMicro):UpdateCollectiveProtocol_Gfx120xSingleNodeDefaultsSimple: gfx1200 and gfx1201 AllGather, ReduceScatter and AllReduce at sizes the old selector mapped to LL now select Simple.UpdateCollectiveProtocol_Gfx120xMultiNodeP2pDisableForcesSimple(wasGfx120xDelegatesThenP2pDisableForcesSimple) now runs multi-node, the only case where theNCCL_P2P_DISABLEoverride still applies.rcclGetProtoForGfx120x()call fails the single-node test, and disabling theNCCL_P2P_DISABLEoverride fails the multi-node test.librccl.sodropped into a public PyTorch/ROCm nightly environment:NCCL_P2P_LEVEL=PIX(SHM),NCCL_P2P_DISABLE=1, and 4 ranks on 2 GPUs withNCCL_MULTI_RANK_GPU_ENABLE=1(mixed P2P/IPC and SHM).NCCL_PROTO=LLoverride check.TestStateDict.test_fsdp: one run withNCCL_DEBUG=INFO NCCL_DEBUG_SUBSYS=COLL,TUNING, plus 5 plain runs.Test Result
NCCL_PROTO=LLstill selects LL.test_fsdp(4 B to 60.6 KB per rank). With this patch none select LL, and the test passes 6/6.NCCL_PROTO=Simplehas the same effect on collectives as this patch.Submission Checklist