Skip to content

Add opus fp8 mxscale BMM kernels for gfx950 - #4320

Merged
valarLip merged 8 commits into
ROCm:mainfrom
yzhou103:fp8-mxscale-bmm
Aug 12, 2026
Merged

valarLip merged 8 commits into
ROCm:mainfrom
yzhou103:fp8-mxscale-bmm

Conversation

@yzhou103

@yzhou103 yzhou103 commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Motivation

Adds the opus fp8 e8m0 mxscale (block-scale) batched GEMM (BMM) path for
gfx950, exposed as aiter.batched_gemm_a8w8_mxscale. The per-kid device
kernels and host launchers are fully code-generated (mirroring the opus_gemm
module), and dispatch is driven by a tuned CSV with padded-M / M-split /
heuristic fallbacks. Also includes a round of dead-kernel and naming cleanup.

# mmajor DSV4 layout: x [M, G, K] fp8, wo_a [G, N, K] fp8 (batch-major, zero-copy),
# x_scale [M, G, K/128], w_scale [G, N/128, K/128], out optional [M, G, N].
aiter.batched_gemm_a8w8_mxscale(x, wo_a, x_scale, w_scale, dtype=torch.bfloat16)

Technical Details

Reuses the shared opus GEMM gfx950 backend; every kid is codegen'd into its own _C{void,bf16,fp32}.device.cu (device symbol) + inlined host launcher, no hand-written adapters.
Table-driven kid -> launcher dispatch (opus_bmm_a8w8_mxscale_tune_dispatch) instead of a large switch.
Kernel families: fused, pipeline, minterleave, mouter / mouter_tunable, wave8n2, wave4m2_selfload, plus OOB-masked sub-tiles (311/313/320/321/324/640/650/653).

Dispatch logic (kernelId=None)
Exact tuned CSV hit → use its kid + splitK.
Padded-M: round M up to the nearest tuned bucket in the same (g,n,k) family; accepted only for OOB-masked sub-tiles (run the real smaller M with no pad/copy).
M-split: for large tile-unaligned M, split into an aligned strong-tile bulk (157/150) + a <256-row OOB-safe tail. Gated on total bulk work g*m >= 8192 (measured break-even), not on g alone.
Heuristic single-kid fallback otherwise.

Test Plan

op_tests/test_opus_a8w8_bmm.py: correctness (fp8 vs bf16 einsum, err 0) across g∈{2,8}, m=1..16384, both m-major and batch-first layouts, and per-family kids.

Test Result

together with #4428

gfx950 x8, DeepSeek-V4-Pro (kv_cache_dtype=fp8, -tp 8, expert parallel).
WOA=1 is the fp8 e8m0 mxscale batched-GEMM path this PR touches, WOA=0 the
existing bf16 dequant + einsum baseline.

Accuracy — gsm8k 5-shot, 1319 problems, flexible-extract / strict-match, stderr ±0.006 on every row:

config WOA=0 WOA=1
TP8 0.9530 / 0.9538 0.9545 / 0.9538
DP-attention 0.9568 / 0.9568 0.9545 / 0.9553
DP-attention + MTP 0.9500 / 0.9507 0.9530 / 0.9538

The whole spread is 0.9500-0.9568, about one stderr, so the mxscale path is indistinguishable from the baseline.

Throughputbenchmark_serving, random 8192 in / 1024 out, range ratio 0.8, concurrency 128, 1280 prompts, --ignore-eos. Medians over 2-3 rounds per arm:

config WOA=0 tok/s WOA=1 tok/s delta TPOT delta
TP8 18143.7 18436.1 +1.61% -1.59%
DP-attention 19814.0 19956.7 +0.72% -1.28%
DP-attention + MTP 27190.5 27870.9 +2.50% -1.55%

Submission Checklist

@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 4320 --add-label <label>

@yzhou103

Copy link
Copy Markdown
Contributor Author
image

@yzhou103 yzhou103 changed the title Add opus fp8 mxscale flatmm split-K BMM kernels for gfx950 Add opus fp8 mxscale BMM kernels for gfx950 Jul 27, 2026
@yzhou103
yzhou103 marked this pull request as ready for review July 27, 2026 09:27
@yzhou103
yzhou103 requested review from a team and Copilot July 27, 2026 09:27

Copilot AI 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.

Pull request overview

This PR adds gfx950-only OPUS fp8 (e8m0) mxscale batched GEMM/BMM support as a self-contained kernel + codegen + Python-binding stack, plus tuned configs and a new op_test to validate DeepSeek-V4-style wo_a layouts.

Changes:

  • Introduces new gfx950 OPUS BMM frontends (C++ + pybind) and Python wrappers for fp8 e8m0 mxscale flatmm split-K dispatch (tuned CSV + heuristic fallback).
  • Extends OPUS codegen/instance plumbing to emit and name the new BMM kernel families and generate the int-kid tuning lookup.
  • Adds a new regression/perf op_test and a model-specific tuned CSV; updates the config-collision guard to include the new config family.

Reviewed changes

Copilot reviewed 23 out of 23 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
op_tests/tuning_tests/test_config_shape_collision.py Adds the new mxscale batched-GEMM config family to the shape-collision guard suite.
op_tests/test_opus_a8w8_bmm.py New correctness + perf sweep covering mxscale BMM paths (including batch-major round trip).
csrc/pybind/opus_gemm_pybind.cu Registers the new OPUS BMM pybind entry point.
csrc/opus_gemm/opus_gemm_common.py Extends instance metadata/naming and adds curated gfx950 mxscale BMM kernel lists for codegen/tuning.
csrc/opus_gemm/opus_bmm.cu Adds the host-side gfx950 mxscale BMM dispatcher/front-end and split-K reduce explicit instantiations.
csrc/opus_gemm/opus_bmm_bake.cu Adds a currently-disabled experimental/placeholder TU (needs cleanup before merge).
csrc/opus_gemm/include/opus_bmm.h New public C++ header declaring the OPUS mxscale BMM entry point.
csrc/opus_gemm/include/gfx950/splitk_reduce_gfx950.cuh Adds a BMM-specific split-K reduce kernel template for the fp32 workspace → final Y cast/store.
csrc/opus_gemm/include/gfx950/opus_gemm_traits_a8w8_scale_gfx950.cuh Adds split-K kargs + new mxscale flatmm split-K traits used by the BMM kernel families.
csrc/opus_gemm/include/gfx950/opus_gemm_traits_a16w16_gfx950.cuh Minor comment/style changes for consistency.
csrc/opus_gemm/include/gfx950/opus_gemm_pipeline_a8w8_scale_gfx950.cuh Removes the old monolithic kernel body (now provided via the new pipeline header mapping).
csrc/opus_gemm/include/gfx950/opus_bmm_pipeline_a8w8_mxscale_gfx950.cuh New combined pipeline header providing scaled MFMA helpers + BMM/GEMM scale kernels used by gfx950 codegen.
csrc/opus_gemm/include/gfx950/opus_bmm_launchers_a8w8_mxscale_gfx950.cuh Adds host-only common checks and forward decls for BMM kernel templates (currently needs signature fixes).
csrc/opus_gemm/gen_instances.py Extends instance generation to support BMM mxscale tags and emits a BMM kid→launcher tuning map.
csrc/include/rocm_ops.hpp Adds the pybind macro for opus_bmm_a8w8_mxscale_flatmm_splitk.
aiter/ops/opus/bmm_op.py New Python raw binding + tuned CSV lookup/heuristic wrapper for mxscale BMM.
aiter/ops/opus/init.py Exposes the new BMM ops under aiter.ops.opus.
aiter/ops/batched_gemm_op_a8w8.py Adds backend-neutral public entry batched_gemm_a8w8_mxscale (currently selecting OPUS backend).
aiter/jit/optCompilerConfig.json Adds opus_bmm.cu to the OPUS JIT module build sources.
aiter/jit/core.py Registers the new config env var/path and improves tuned→untuned name derivation + dedup key robustness.
aiter/configs/model_configs/dsv4_batched_gemm_a8w8_blockscale_mxscale_tuned.csv Adds DeepSeek-V4-tuned mxscale batched-GEMM/BMM entries for gfx950.
Comments suppressed due to low confidence (1)

csrc/opus_gemm/include/gfx950/opus_bmm_launchers_a8w8_mxscale_gfx950.cuh:25

  • The forward declaration for gemm_a8w8_mxscale_flatmm_splitk_mouter_kernel is missing the SKIP_SCALE_WAIT bool template parameter (the real kernel is template<typename Traits, typename D_OUT, bool SKIP_SCALE_WAIT=false>). Generated launchers for kids that set skip_scale_wait=True will fail to compile against this header.
template<typename Traits, typename D_OUT>
__global__ void gemm_a8w8_mxscale_flatmm_splitk_mouter_kernel(opus_gemm_scale_splitk_kargs_gfx950 kargs);

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +22 to +23
template<typename Traits, typename D_OUT, bool DIRECT_ONLY>
__global__ void gemm_a8w8_mxscale_flatmm_splitk_kernel(opus_gemm_scale_splitk_kargs_gfx950 kargs);
@@ -200,7 +200,7 @@ __global__ void splitk_reduce_kernel(
c_idx + g * STEP);
});
} else if (n_base < N) {
// Tail path: decompose valid [1, VEC-1] into descending
// Tail path: decompose valid ? [1, VEC-1] into descending
Comment thread op_tests/test_opus_a8w8_bmm.py
Comment thread csrc/opus_gemm/opus_bmm_bake.cu Outdated
@zufayu
zufayu requested review from amd-ruitang3, demonsan and valarLip and removed request for amd-ruitang3 July 28, 2026 01:44
@zufayu zufayu added the ci:all label Jul 28, 2026
@yzhou103

Copy link
Copy Markdown
Contributor Author

preload sfa+sfb and vec load opt:
image

demonsan
demonsan previously approved these changes Aug 5, 2026
yzhou103 added a commit to yzhou103/aiter that referenced this pull request Aug 6, 2026
test_mxscale_bmm_batch_first logged only us/err; add the roofline columns
test_mxscale_bmm already emits so the two tables compare. Addresses the
Copilot review note on ROCm#4320.

Co-authored-by: Cursor <cursoragent@cursor.com>
- gfx950 kernel family with codegen'd launchers, split-K and split-K reduce
- dispatch for tile-unaligned M: padded-M lookup, sub-tile gating, M-split fallback
- tuned-row lookup in the a8w8 batched family layer, libtype-dispatched and lru_cached
- kid -> M alignment derived from codegen, asserted at build time and in the op test
- self-contained tuner plus the DeepSeek-V4 tuned CSV

gsm8k 5-shot exact_match 0.953 on DeepSeek-V4-Pro (tp8, fp8 kv, mxscale on).

Co-authored-by: Cursor <cursoragent@cursor.com>
yzhou103 and others added 2 commits August 6, 2026 13:48
Guard the tuned lookup behind a functional custom op while keeping focused dispatch and tileN regression coverage.

Co-authored-by: Cursor <cursoragent@cursor.com>
@demonsan
demonsan self-requested a review August 7, 2026 03:32
demonsan
demonsan previously approved these changes Aug 7, 2026
yzhou103 and others added 2 commits August 6, 2026 23:28
Remove the remaining comment-only formatting differences from this PR.

Co-authored-by: Cursor <cursoragent@cursor.com>
@valarLip
valarLip merged commit b5c5912 into ROCm:main Aug 12, 2026
47 of 49 checks passed
demonsan added a commit that referenced this pull request Aug 13, 2026
Conflicts came from main's new a8w8_mxscale BMM family (#4320) landing in the
same two files this branch edits, and both sides were purely additive:

* opus_gemm_common.py OpusGemmInstance: keep this branch's fuse_* axes next to
  main's mxscale BMM axes; both groups are defaulted trailing fields.
* gen_instances.py manifest emit: keep both signature templates and fold the
  gfx1250 6-arg workspace choice into main's A16W16_TUNE_TAGS branch, after the
  BMM branch (the tag sets are disjoint, so the order is free).

Verified after the merge: 496 gfx1250 kids with none in the fuse band, tuner
candidate counts unchanged, and codegen over gfx950+gfx942+gfx1250 emits both
the 44 BMM and the 63 workspace launcher declarations.

Co-authored-by: Cursor <cursoragent@cursor.com>
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.

5 participants