fix: work around Triton buffer-store miscompile and ROCm compiled-training NaNs - #962
Open
WangLingxun wants to merge 2 commits into
Open
fix: work around Triton buffer-store miscompile and ROCm compiled-training NaNs#962WangLingxun wants to merge 2 commits into
WangLingxun wants to merge 2 commits into
Conversation
WangLingxun
force-pushed
the
fix/gfx942-triton-bufops-war
branch
3 times, most recently
from
August 12, 2026 11:33
f791a77 to
18071e1
Compare
WangLingxun
force-pushed
the
fix/gfx942-triton-bufops-war
branch
from
August 13, 2026 07:18
18071e1 to
cedd6b4
Compare
WangLingxun
marked this pull request as ready for review
August 13, 2026 07:21
WangLingxun
requested review from
Xiaoming-AMD,
limou102 and
wenxie-amd
as code owners
August 13, 2026 07:21
WangLingxun
force-pushed
the
fix/gfx942-triton-bufops-war
branch
3 times, most recently
from
August 13, 2026 08:27
9269d33 to
b74383c
Compare
The AMD Triton backend can redefine a buffer_store_dwordx4's data VGPRs before the store has read them, with no s_waitcnt vmcnt in between. The store then writes whatever the clobbering instruction left there. Nothing faults and nothing warns; a few percent of the kernel's output elements are simply garbage. Inductor's SwiGLU backward fusion trips this and poisons the w1/w2/w3 weight gradients, so TorchTitan training NaNs out on the second step. Compile every kernel normally, scan the emitted AMDGCN, and recompile only the affected kernels with buffer ops off. Also require finite loss and grad-norm metrics in E2E tests and auto_benchmark so a diverged run cannot look successful.
Preserve eager precision-cast semantics in Inductor graphs, keep DeepSeek MoE blocks on TorchTitan's mixed compile strategy, and route gfx942 DeepSeek FP8 MLA backward through aiter CK instead of the invalid fmha_v3 ASM path. Also bind grouped-MM patches to the imported module so CI no longer depends on import order.
WangLingxun
force-pushed
the
fix/gfx942-triton-bufops-war
branch
from
August 20, 2026 06:41
6b3de69 to
64c3261
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Two classes of silent ROCm compiled-training failures showed up while validating this branch:
Triton buffer-store miscompile. The AMD Triton backend can emit a
buffer_store_dwordx4whose data VGPRs are redefined by a later instruction with no intervenings_waitcnt vmcnt, so the store writes whatever the clobbering instruction left in those registers. Nothing faults and nothing warns; a few percent of the kernel's output elements are simply garbage. Inductor's SwiGLU backward fusion trips this and poisons the MLP weight gradients, which diverges TorchTitan training. Megatron runs the same inductor-generated kernels, but there the corruption tends to stay inside the normal numeric range, so a finite loss curve does not prove a clean run.TorchTitan compiled-training NaNs / invalid backward. Independently of Triton, ROCm Inductor graphs drop eager precision-cast truncation, DeepSeek MoE whole-block compilation poisons step-1 loss, and gfx942
aiter.fmha_v3_bwdincorrectly accepts DeepSeek MLA (qk=192,v=128) then launches an ASM kernel with incomplete metadata.What changed
Triton per-kernel buffer-ops WAR (
primus/core/patches/triton_bufops_war_patches.py). Wrapstriton.compile, scans each kernel's emitted AMDGCN for the hazard, and recompiles only the affected kernels with buffer ops disabled. Keying on the machine code means there is no kernel or architecture allowlist to maintain. Registered for both torch backends at thebuild_argsphase, gated only on being a ROCm GPU; non-HIP kernels are skipped per compile.AMDGCN_USE_BUFFER_OPS=0is deliberately not set globally: the hazardous kernels lose nothing without buffer addressing, but the Primus-Turbo grouped-GEMM kernels spill without it and carry no hazard, so the global switch costs ~18% on MoE recipes for kernels that never needed fixing. Per-kernel selection measured 299.9 vs 299.0 TFLOP/s per GPU ondeepseek_v2_lite-BF16, against 244.6 with the global switch.The patch also appends to
TORCH_COMPILE_CACHE_KEY_TAG, since on an FX graph cache hit inductor never callstriton.compile— without invalidation a cache filled before this lands would keep serving hazardous binaries.Divergence detection.
tests/utils.pynow requires every logged loss and grad norm to be finite, because a numerically diverged run still exits 0 and still prints the completion marker.tools/auto_benchmark/metrics.pymarks a run with non-finite metrics invalid instead of publishing its throughput.TorchTitan ROCm numerical workarounds.
emulate_precision_castsbefore compile so FSDP BF16 llama/qwen graphs keep eager truncation. This is a ROCm 2.12 BF16 issue, not a carry-over of upstream pytorch#150859.fullgraph=True, DeepSeek MoE blocks stay eager. Whole-block MoE compile was putting EP dispatch/combine and FSDP hooks into one Inductor graph and producing step-1 NaN.qk=192/v=128) through aiter's generic CK path instead of the invalidfmha_v3ASM dispatch. Forward is unchanged; measured ~204–206 TFLOP/s vs the original v26.5 CK-only path at ~198.Tests. Hazard criterion and ROCm gate for the Triton WAR, finite-metric parser coverage for both backends' log formats, plus unit tests for precision-casts registration, dense-only MoE compile, gfx942 MLA CK routing, and Turbo converter gating. All unit tests are static: no GPU, no Triton.
Docs. A workarounds section in
performance-tuning.mdand one row inenvironment-variables.md.Test plan