Skip to content

fix(rocm): reuse staged moe alignment on Triton 3.8 - #691

Merged
jason-fxz merged 2 commits into
FlashML-org:mainfrom
LZ-QWQ:fix/rocm-moe-align
Oct 15, 2026
Merged

jason-fxz merged 2 commits into
FlashML-org:mainfrom
LZ-QWQ:fix/rocm-moe-align

Conversation

@LZ-QWQ

@LZ-QWQ LZ-QWQ commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

Summary

On ROCm with Triton 3.8, the existing histogram align can be miscompiled, producing invalid routing buffers that may cause incorrect MoE outputs or illegal GPU memory accesses. The existing grouped-MoE test in test_fused_moe.py reproduces an illegal memory access before this fix. The compiler fix is Triton #11246.

This PR proposes a simple workaround: reuse the existing moe_align_block_size_triton on ROCm with Triton 3.8.x. Other platform/version dispatch remains unchanged. This temporary workaround can be removed once Triton 3.8 is no longer supported.

Related: #541, #587, #687. Both existing proposals add Torch fallbacks; this alternative reuses the staged Triton implementation without adding another implementation or configuration option.

Performance

Radeon AI PRO R9700 (gfx1201), ROCm 10.1, Torch 2.14. Actual Qwen/Qwen3.8-Flash-Next-FP8 prefill routes from all 48 layers, K=10, E=512, block=64.

Cells report mean ± SD (us/call) across 48 layers. Each layer averages all its chunks, using the median of three independent run medians per chunk (10 warmups, 30 samples/run, 5 graph replays/sample). ± describes variation across the measured layer values, not a confidence interval.

Implementation Triton M128 M1024 M4096
Staged Triton (this PR) 3.8 185.73 ± 5.03 199.55 ± 2.71 237.83 ± 0.41
Torch (#587) 3.8 120.96 ± 0.81 157.81 ± 7.55 264.54 ± 33.01
Torch (#687) 3.8 153.59 ± 0.81 192.24 ± 7.04 299.70 ± 31.49
Histogram Triton 3.9 preview 33.00 ± 0.10 36.25 ± 0.11 47.83 ± 0.35

M128 has one chunk per layer. The 8192-token requests provide all eight M1024 or both M4096 chunks per layer. The 3.9 preview uses a ROCm 10.2 wheel in the same Torch/ROCm environment and is an experimental reference, not an end-to-end speedup or a supported framework upgrade.

The staged fallback has mixed performance against Torch on 3.8. The purpose is a minimal correctness workaround while preserving the substantially faster histogram path on fixed compilers. Full Triton 3.9 migration remains separate because other kernels use its removed block-pointer API.

Validation

PYTHONPATH=python python -m pytest -q tests/moe/test_fused_moe.py
  • Triton 3.8: 37 passed.
  • Triton 3.9 preview: 37 passed.

Tests are unchanged. The existing grouped-MoE test fails before the fix and passes afterward on ROCm with Triton 3.8.

cc @zihaomu

@github-actions github-actions Bot added the amd label Oct 15, 2026
Comment thread python/freetoken/moe/fused.py Outdated
Comment on lines +93 to +95
# Avoid the ROCm Triton 3.8 histogram-mask miscompile until 3.9.
# https://github.com/triton-lang/triton/pull/11246
if Version(triton.__version__) < Version("3.9"):

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The miscompile is 3.8-only: tensor cmpi was not folded before triton#9805, and triton#11577 confirms 3.7.1 is unaffected. pyproject.toml still allows triton>=3.6, so < 3.9 also sends 3.6/3.7 to the slower staged path. Could you gate on 3.8.x only and mark the branch as temporary?

Suggested change
# Avoid the ROCm Triton 3.8 histogram-mask miscompile until 3.9.
# https://github.com/triton-lang/triton/pull/11246
if Version(triton.__version__) < Version("3.9"):
# FIXME: remove once Triton 3.8 is unsupported. Its AMD backend folds compares on tl.histogram results to false.
# https://github.com/triton-lang/triton/pull/11246
if Version(triton.__version__).release[:2] == (3, 8):

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Thanks!

@LZ-QWQ LZ-QWQ changed the title fix(rocm): reuse staged moe alignment below Triton 3.9 fix(rocm): reuse staged moe alignment on Triton 3.8 Oct 15, 2026
@jason-fxz
jason-fxz merged commit 0bca88f into FlashML-org:main Oct 15, 2026
1 check passed
zhangnju added a commit to zhangnju/FreeToken that referenced this pull request Oct 15, 2026
…Cm compile)

Slimmed from the original torch2.14/triton3.8 enablement now that upstream main
landed its own ROCm support (setup.py IS_ROCM, native gpu_sync_hip.cpp, torch 2.14,
FlashML-org#691 moe_align). These three are the RDNA fixes main still lacks:

- qsa/attend.py: query the device's shared_memory_per_block and shrink the KV tile
  when it won't fit, instead of assuming the GB300's 228KB LDS -> RDNA (64KB/CU) no
  longer overflows LDS. ROCm-gated; NVIDIA tiles byte-identical.
- gguf/dispatch.h: ROCm's __shfl_xor_sync needs a 64-bit warp mask
  (amd_warp_sync_functions static_assert); the vLLM/sgl donor passes uint32. Widen
  to uint64_t on HIP.
- gguf.py: --expt-relaxed-constexpr and -ccbin are nvcc-only; ROCm compiles hipified
  sources with clang++ which rejects them.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants