Skip to content

feat(rocm): add RDNA3 and RDNA4 runtime foundation - #132

Open
zihaomu wants to merge 8 commits into
FlashML-org:mainfrom
zihaomu:feat/rocm-rdna3-rdna4-foundation
Open

feat(rocm): add RDNA3 and RDNA4 runtime foundation#132
zihaomu wants to merge 8 commits into
FlashML-org:mainfrom
zihaomu:feat/rocm-rdna3-rdna4-foundation

Conversation

@zihaomu

@zihaomu zihaomu commented Aug 24, 2026

Copy link
Copy Markdown

Summary

  • add an independent ROCm source-build foundation for RDNA3 (gfx1100-gfx1103) and RDNA4 (gfx1200, gfx1201);
  • support both traditional /opt/rocm layouts and the modular ROCm SDK shipped by the official ROCm 7.14 PyTorch image;
  • build and load the pinned-memory and CPU-MoE extensions on HIP;
  • make the pinned-host fast-index-copy and Triton activation/norm paths work on ROCm;
  • detect the visible gcnArchName, with explicit environment overrides for cross compilation.

Why this targets main directly

This PR is a standalone, current-main integration. It incorporates the useful work from #23 and the RDNA3 runtime follow-up at bouclem#1, then adds the RDNA4 and ROCm 7.14 changes. It therefore does not require either external feature branch to merge first.

This intentionally overlaps those open PRs so maintainers can review and merge a complete, hardware-tested ROCm foundation without being blocked by a cross-fork base chain.

Attribution

Thank you to both contributors for establishing and validating the earlier ROCm paths.

Validation

Hardware and software:

  • AMD Radeon AI PRO R9700 (gfx1201)
  • PyTorch 2.11.0+rocm7.14.0
  • HIP 7.14.60850
  • AMD Triton 3.7.1

Results:

  • clean python -m pip install -e . --no-build-isolation --no-deps: PASS; both native extensions compiled and loaded;
  • cold TVM-FFI fast-index-copy JIT build: PASS;
  • architecture, pinned/copy, Triton attention, Gemma norm, SwiGLU, and CPU-MoE graph replay tests: 48 passed;
  • python -m pip check: PASS;
  • git diff --check: PASS.

Compatibility

ROCm-specific code is guarded by HIP/ROCm detection and existing CUDA paths are retained. Physical NVIDIA regression testing is not claimed; upstream CUDA CI is requested before merge.

Follow-ups

Kept out of this foundation PR for separate review:

  1. generic TVM-FFI index/store HIP portability;
  2. CUDA-only optional-backend gating;
  3. RCCL tensor-parallel routing;
  4. native GGUF kernels on ROCm/RDNA4;
  5. RDNA-specific performance tuning and full model-serving validation.

bouclem and others added 8 commits August 24, 2026 13:53
- Add hip_compat.h shim mapping CUDA runtime API to HIP equivalents
- Update pinned_tensor.cpp to compile under both nvcc and hipcc
- Add ROCm detection in arch.py (is_rocm, get_rocm_gfx_arch, is_gfx11xx_family)
- Guard NVIDIA arch checks to return None on ROCm
- Skip nvcc version check in _toolchain.py when on ROCm
- Add ROCm build path in setup.py (ROCM_HOME, amdhip64, --offload-arch)
- Add _hip_cflags() in kernel/utils.py for JIT compilation on ROCm
- Add is_rocm() and driver_hip_version() in backend.py
- Add rocm-smi fallback in __main__.py for clangd generation
- Add TODO(ROCm) for NCCL->RCCL, flashinfer/sgl_kernel ROCm builds,
  Triton autotune RDNA3 tuning, PDL equivalent, hiprtc JIT cache
- Add AMD ROCm classifier in pyproject.toml
@zihaomu

zihaomu commented Aug 24, 2026

Copy link
Copy Markdown
Author

Draft follow-ups are now available:

All four are opened as Draft PRs against main. Until this foundation PR merges, their GitHub “Files changed” views temporarily include the #132 foundation commits; each PR body lists its intended incremental review scope. They will remain drafts and be rebased/refreshed as their dependencies land.

@Ewwgoblins

Ewwgoblins commented Aug 25, 2026

Copy link
Copy Markdown

Independent test report: RDNA3 / gfx1100 (RX 7900 XT)

Ran this branch on an RDNA3 card, since the validation above is gfx1201. Short version: the foundation works on gfx1100, I was able to serve models end to end, and the offload architecture measures very well against llama.cpp on this hardware.

Environment

Install

python -m pip install --no-build-isolation -e . — PASS. Both native extensions compiled and loaded. No HSA_OVERRIDE_GFX_VERSION needed. The widened triton>=3.6,<3.8 pin on this branch correctly preserves the image's AMD Triton 3.7.1.

Test suite

pytest tests -q -m "not slow"1331 passed, 20 failed, 24 skipped, 11 deselected (211.60 s).

  • 16 × tests/kernels/test_dsv4_sparse_attn.py (the whole file) — RuntimeError: PassManager::run failed at triton/backends/amd/compiler.py:273. AMD Triton cannot compile that kernel on gfx1100. This file is not in the validation list above, so I believe this is new. Happy to open a separate issue if you would prefer it tracked.
  • 3 × flashinfer absenttest_cache_budget.py (×2), test_offload.py::test_adjust_config_converts_moe_cache_rate_to_cache_size. Expected, installed without [accel]; presumably fix(rocm): gate CUDA-only optional backends on ROCm #134.
  • 1 × test_gemma4_fused_ops.py::test_gemma4_router_uses_sgl_kernel_topk_softmax_semanticsTensor-likes are not equal!. May also be sgl_kernel absence; not chased.

ft bench bw on gfx1100

ceilings: CPU STREAM read 47.1 | PCIe linear H2D 28.42  D2H 28.56 GB/s  (threshold 2.0x)
  bf16   47.4/28.6 = 1.66x -> offload     nvfp4  44.2/28.6 = 1.55x -> offload
  mxfp4  35.9/28.6 = 1.26x -> offload     ds_fp4 45.6/28.6 = 1.59x -> offload
  fp8    n/a (CPU MoE has no fp8_block weight path)

Serving — works, and the offload numbers are the interesting part

openai/gpt-oss-20b (12.8 GiB safetensors, MXFP4). This model FITS in 20 GB, which lets me compare all four configurations on one card. Method: HTTP API, 512 tokens, --ignore-eos, warmup discarded, page cache pre-warmed, n=3, sub-1% variance throughout.

engine / backend decode tok/s
llama.cpp (Vulkan) -ngl 99 -fa on 193.5
llama.cpp (Vulkan) --cpu-moe 25.5
FreeToken --moe-backend fused 100.8
FreeToken --moe-backend offload 91.2
FreeToken --moe-backend hybrid (forced) 71.8

Two things stand out:

  1. The offload penalty is the story. llama.cpp loses 86.8% moving experts off the card (193.5 → 25.5). FreeToken loses 9.5% (100.8 → 91.2). In the offloaded regime FreeToken is 3.58× faster than llama.cpp on the same model and card.
  2. ft bench bw's hybrid heuristic is correct here, and I verified it by overriding it. It recommended offload (1.65×, under the 2.0 threshold); forcing hybrid costs 21%. Also worth recording: hybrid runs on gfx1100, so that path is functional on ROCm.

Qwen/Qwen3.6-35B-A3B-FP8 (35 GB, does NOT fit 20 GB)moe_backend='offload', cache_type='hybrid_radix', VRAM 19.90 → 2.02 GiB, ~3 min load: 37.8 tok/s. For scale, my own earlier llama.cpp measurements of Qwen3.6-35B-A3B on this card were 115.9 tok/s for Q4_K_M resident and 28.25 tok/s for Q4_K_M with --n-cpu-moe 32. So FreeToken serves a 75% larger, higher-precision checkpoint 34% faster than llama.cpp manages on the smaller Q4 once it has to offload. Different quantisations, so treat that one as indicative; the gpt-oss-20b table above is exact.

Since "full model-serving validation" is an open follow-up here and #136 says serving is out of scope, I hope this is useful.

One design observation

auto selected offload for gpt-oss-20b even though it fits the card, costing 9.5% for nothing. Per docs/models.md that is intended (dense → fused, MoE → offload always), and fused is documented as "never auto-selected" — but on a card where the MoE fits, auto picks the slower path. A fit check before defaulting to offload might be worth considering.

Host-RAM ceiling, for anyone sizing a box

Offload pins expert memory, so host RAM is the real limit. On 62 GiB total / 45 GiB available, a 35 GB model consumed ~31 GB pinned and dropped available RAM to 14 GB — at which point sshd could no longer fork, while the box stayed up and port 22 stayed open. Extrapolating, ~50 GB models need ~46 GB pinned and are out of reach on this machine. Not a bug, just a sizing note.

Not tested (deliberately)

The GGUF path. On #132 alone it fails in kernel/gguf.py: --expt-relaxed-constexpr and -ccbin are passed unconditionally in extra_cuda_cflags and reach hipcc/clang++, which reject them. After locally gating those on torch.version.hip the next failure is thrust/complex.h not found — the modular ROCm SDK wheels in that image ship no rocThrust. Both look like exactly what #136 covers, and #136 depends on #133 which I did not apply, so I did not pursue it and am not filing anything for it.


Happy to re-run any of this, or to test the follow-up PRs on gfx1100 if a second architecture is useful to you. Thanks for doing this work — the RDNA3 scope in #132 is what made it worth trying. (and I Hope i did this correctly! its my first comment!)

@zihaomu

zihaomu commented Aug 26, 2026

Copy link
Copy Markdown
Author

Hi @Ewwgoblins Thank you for your detailed report, it was very helpful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants