Skip to content

[TRITON] gfx1201: gemm_a8w8 tuning configs (Mistral-3 / Qwen3 shapes)#3234

Closed
carlushuang wants to merge 3 commits into
mainfrom
carhuang/gfx1201_silu_and_mul_and_a8w8_configs_rebased
Closed

[TRITON] gfx1201: gemm_a8w8 tuning configs (Mistral-3 / Qwen3 shapes)#3234
carlushuang wants to merge 3 commits into
mainfrom
carhuang/gfx1201_silu_and_mul_and_a8w8_configs_rebased

Conversation

@carlushuang

Copy link
Copy Markdown
Collaborator

Rebase of #3168 onto current main (d9e660b). Same single commit, same diff; just resolves the few upstream commits that landed after #3168 was opened. Original PR left open as historical reference.

Summary

Two small additions that let aiter run on RDNA4 (gfx1201, RX 9070 XT family) without the calling project having to maintain its own kernel/config replicas.

  1. aiter.ops.triton.activation.silu_and_mul — a triton implementation of the existing HIP silu_and_mul, with the same (out, x) signature so callers can dispatch by arch without changing call sites. The HIP kernel does not compile on RDNA4: its inner activation_kernels.cu uses v_pk_mul_f32, an instruction that exists only on CDNA (gfx9*) and gfx1250. (Note: superseded upstream by silu_mul_fused kernel #2578 silu_mul_fused which is now merged; ATOM consumers should use fused_silu_mul going forward.)

  2. 5 gfx1201-GEMM-A8W8*.json tuning configs for the per-tensor FP8 gemm_a8w8 triton kernel. Without these, gemm_config_utils falls through to the cross-arch default (GROUP_SIZE_M=4), which leaves 75% of M-dim launch slots idle on RDNA4 at decode bs=1..32. Each config is hand-tuned on RX 9070 XT for one of the four projection shapes used by Mistral-3-8B / Qwen3-8B-FP8 (qkv, o, gate_up, down).

Headline numbers (gfx1201, RX 9070 XT, ROCm 7.x)

silu_and_mul triton vs torch fallback (the only other option on gfx1201):

Shape (M, 2H) Triton Torch Δ
(8, 28672) 9.1us 10.0us -9%
(32, 28672) 9.2us 13.2us -30%
(1024, 28672) 153us 205us -25%

gemm_a8w8 per-shape configs vs the cross-arch default at decode bs=1:

Shape Default Tuned
qkv 163us 33us
o 45us 28us
gate_up 229us 211us
down 107us 36us

Test plan

  • silu_and_mul: bf16 + fp16, 2H non-power-of-2 included; relative err <1% vs F.silu(a)*b (triton accumulates in fp32, so it is in fact more accurate than the bf16 reference)
  • gemm_a8w8: get_gemm_config(\"GEMM-A8W8\", M, N, K) returns the new specialized blocks for all 4 (N, K); kernel output 0 abs-err vs BF16 reference (dequant FP8 then matmul) at bs in {1, 8, 32}
  • No regression risk for other archs — both additions are arch-specific files / new symbols; nothing existing is renamed or removed
  • Re-verified end-to-end (2026-05-16) on RX 9070 XT with ROCm/ATOM PR [gfx1201] Mistral-3 + Qwen3-8B-FP8 on RDNA4 via native triton attention ATOM#811: Mistral-3-8B gsm8k 5-shot n=200 = 0.79/0.79, Qwen3-8B-FP8 gsm8k 5-shot n=50 = 0.90/0.90, TPOT 17.4 ms / 17.6 ms respectively

Context

Used by ROCm/ATOM in ROCm/ATOM#811 (gfx1201 / Mistral-3-8B + Qwen3-8B-FP8 enablement; supersedes ROCm/ATOM#749). Once this PR lands and the aiter pin in ATOM is bumped, ATOM can delete its _silu_mul_triton and _gfx1201_gemm_a8w8_config replicas.

…hapes

Drops 5 JSON configs into aiter/ops/triton/configs/gemm/:

- gfx1201-GEMM-A8W8.json                     (default)
- gfx1201-GEMM-A8W8-N=6144-K=4096.json       (Mistral-3 / Qwen3 qkv_proj)
- gfx1201-GEMM-A8W8-N=4096-K=4096.json       (o_proj)
- gfx1201-GEMM-A8W8-N=28672-K=4096.json      (gate_up_proj for Mistral-3)
- gfx1201-GEMM-A8W8-N=4096-K=14336.json      (down_proj for Mistral-3)

Without a per-arch config file, aiter/ops/triton/utils/gemm_config_utils
falls through to the cross-arch default, which on gfx1201 selects
GROUP_SIZE_M=4. That is a reasonable choice on CDNA where 4 M-tiles of
work fit naturally per workgroup, but it leaves 75% of the M-dim launch
slots idle on RDNA4 at decode bs=1..32 (only 1 real M-tile per call).

Each shape is hand-tuned on RX 9070 XT (cold-cache, 30-iter bench).
Headline kernel-time deltas vs the cross-arch default at decode bs=1:

  qkv      163us -> 33us
  o         45us -> 28us
  gate_up  229us -> 211us
  down     107us -> 36us

The "any" key plus matching M_LEQ behavior in get_gemm_config means a
single tuned entry per (N, K) covers our full BS=1..32 sweep. Verified
correct against the BF16 reference (dequant FP8 then matmul) at 0.0
abs error for all 4 shapes at bs in {1, 8, 32}.
@carlushuang carlushuang requested a review from a team May 16, 2026 11:07
@github-actions

Copy link
Copy Markdown
Contributor

🏷️ CI Guide

Runs automatically on every PR:

  • ✅ Pre-checks (submodule verification, code formatting)
  • ✅ Aiter op tests (gfx942 + gfx950)
  • ✅ Triton tests on MI35X (only when aiter/ops/triton/** or related paths are changed)

Extended tests (opt-in via labels):

Label Tests
ci:triton-300x Run an additional Triton test job on MI300X in PRs; main branch always runs both MI35X and MI300X
ci:sglang SGLang integration tests: DeepSeek-R1-MXFP4 accuracy, Qwen 3.5 accuracy
ci:atom ATOM benchmark: DeepSeek-R1-0528, GPT-OSS-120B
ci:atom_full ATOM accuracy suite for PR and main models from ATOM models_accuracy.json
ci:vllm vLLM benchmark: GPT-OSS-120B, DeepSeek-R1-0528, Kimi-K2.5
ci:all All standard extended tests (excludes ci:atom_full)

Only add ci:atom_full for FlyDSL or Triton upgrades.
Add labels via the sidebar or gh pr edit 3234 --add-label <label>

@brunomazzottiamd brunomazzottiamd 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.

LGTM!

carlushuang added a commit that referenced this pull request May 26, 2026
Adds 5 triton tuning JSONs for the plain GEMM-A8W8 (non-blockscale)
kernel on gfx1201, covering Mistral-3 / Qwen3 shapes:
  - GEMM-A8W8.json (default M-bracket table)
  - GEMM-A8W8-N=4096-K=4096.json (qkv/o projection)
  - GEMM-A8W8-N=6144-K=4096.json (qkv for Qwen3 GQA)
  - GEMM-A8W8-N=4096-K=14336.json (down projection)
  - GEMM-A8W8-N=28672-K=4096.json (gate+up projection)

Same tuning artifact source as the gfx1201-GEMM-A8W8_BLOCKSCALE_PRESHUFFLED
config added in the previous commit (and the existing gfx1201-GEMM-A8W8_BLOCKSCALE
configs already on main). Bundled here because both belong to the gfx1201
triton GEMM family used by ATOM PR ROCm/ATOM#811.

Folds in the JSON content previously split out as PR #3234 (closed).
@carlushuang

Copy link
Copy Markdown
Collaborator Author

Superseded by #3343 — the 5 GEMM-A8W8 tuning JSONs are folded into that PR alongside the gemm_a8w8_blockscale HIP→triton fallback and the GEMM-A8W8_BLOCKSCALE_PRESHUFFLED config. Single PR for all gfx1201 triton a8w8 GEMM enablement. Original LGTM from @brunomazzottiamd carried over via the JSON content (unchanged).

valarLip pushed a commit that referenced this pull request Jun 22, 2026
…lain + blockscale_preshuffled) (#3343)

* gemm_a8w8_blockscale[_bpreshuffle]: HIP -> triton fallback for non-CDNA

The prebuilt HIP CK modules module_gemm_a8w8_blockscale and
module_gemm_a8w8_blockscale_bpreshuffle ship code objects only for
gfx94x/95x. On other arches (e.g. gfx1201 RDNA4 in rocm/atom-dev:latest)
the HIP kernel launch SIGSEGVs with 'No compatible code objects found
for the device' -- no catchable exception, so we must allowlist arches
BEFORE calling the HIP path.

Added _hip_blockscale_supported() that returns True only for the four
prebuilt CDNA arches. When False, both public wrappers route to their
triton equivalents in aiter.ops.triton.gemm.basic.gemm_a8w8_blockscale:

  * gemm_a8w8_blockscale (non-preshuffle) -> triton non-preshuffle.
    x_scale layout matches (row-major). Direct dispatch.

  * gemm_a8w8_blockscale_bpreshuffle -> triton preshuffle. The (N, K)
    weight has been (16, 16)-shuffled the same way the triton kernel
    expects; a reshape view to (N//16, K*16) satisfies the kernel's
    shape assertion. x_scale is column-major (the preshuffle convention),
    direct fit. An explicit fallback config is passed because the
    gfx1201-GEMM-A8W8_BLOCKSCALE_PRESHUFFLED.json tuning file does not
    yet exist on main.

uint8-storage weight (the d_dtypes['fp8'] convention from before #3332)
is viewed as float8_e4m3fn so triton's tl.dot accepts it; if the weight
is already float8_e4m3fn the view is a no-op.

Verified on gfx1201 against F.linear(bf16) gold across Qwen3-8B-FP8 layer
shapes (qkv 1/8/16384x4096->6144, o, gate_up, down) for both paths:
relative error 3.0-3.6%, at the FP8 quant-noise floor.

* configs: add gfx1201 GEMM-A8W8_BLOCKSCALE_PRESHUFFLED.json

Needed because ATOM's atom/model_ops/linear.py:gemm_a8w8_blockscale_preshuffle_impl
calls the triton preshuffle wrapper directly (bypassing the HIP wrapper
my new fallback adds to). Without this file the triton wrapper raises
"Required config file doesn't exist" at first per_1x128 layer call.

Starting values copied from gfx1201-GEMM-A8W8_BLOCKSCALE.json (the
non-preshuffle variant, real gfx1201 tuning). Same M-bracket structure,
same block sizes -- the preshuffle kernel reads the same parameter
names. Suboptimal but correct: the preshuffle memory access pattern
likely prefers different BLOCK_SIZE_N / waves_per_eu values, so dedicated
preshuffle tuning is a TODO once a tuning run is available.

Only one file -- ATOM's two test models (Mistral-3-8B per-Tensor and
Qwen3-8B-FP8 per-1x128) hit only this preshuffle kernel; the
non-preshuffle config already exists on main, and the other GEMM
families (A16W16, AFP4WFP4, batched, fused, etc.) are not invoked
by these models.

* configs: add gfx1201 GEMM-A8W8 (non-blockscale) tuning configs

Adds 5 triton tuning JSONs for the plain GEMM-A8W8 (non-blockscale)
kernel on gfx1201, covering Mistral-3 / Qwen3 shapes:
  - GEMM-A8W8.json (default M-bracket table)
  - GEMM-A8W8-N=4096-K=4096.json (qkv/o projection)
  - GEMM-A8W8-N=6144-K=4096.json (qkv for Qwen3 GQA)
  - GEMM-A8W8-N=4096-K=14336.json (down projection)
  - GEMM-A8W8-N=28672-K=4096.json (gate+up projection)

Same tuning artifact source as the gfx1201-GEMM-A8W8_BLOCKSCALE_PRESHUFFLED
config added in the previous commit (and the existing gfx1201-GEMM-A8W8_BLOCKSCALE
configs already on main). Bundled here because both belong to the gfx1201
triton GEMM family used by ATOM PR ROCm/ATOM#811.

Folds in the JSON content previously split out as PR #3234 (closed).

* gemm_a8w8: condense gfx1201 triton-fallback comments

Tighten the verbose arch-gate / fallback comments (no logic change).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
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.

2 participants