Skip to content

moe gemm optimization - #4730

Open
yadaish wants to merge 22 commits into
mainfrom
dev/yadai_cluster_exp_v2_rebase
Open

moe gemm optimization#4730
yadaish wants to merge 22 commits into
mainfrom
dev/yadai_cluster_exp_v2_rebase

Conversation

@yadaish

@yadaish yadaish commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Motivation

Technical Details

Test Plan

Test Result

Submission Checklist

HaonanWang98 and others added 9 commits August 10, 2026 15:09
…fetch,

configurable wave grid, and main-loop scheduling

Squashes the dev/yadai_cluster_exp_v2 line of work into a single commit on top
of main. Five files, no overlap with anything main has changed since the
branch point.

Workgroup-cluster multicast (cluster_n)
  cluster_n > 1 launches (cluster_n, 1, 1) workgroup clusters whose peers share
  a tile's A rows and differ only in n_tile, so one A / A-scale tensor_load can
  serve the whole cluster. A non-zero workgroup_mask turns the load into
  CLUSTER_LOAD_ASYNC, which rendezvouses with the peers itself -- no cluster
  barrier is emitted, and on a 1-D cluster with a contiguous mask none is
  needed. The DeepGEMM contiguous-M swizzle runs on cluster granularity, with
  n_tile reassembled from the cluster-local id. Selected host-side by
  _pick_cluster_n (env AITER_FLYDSL_MXFP4_CLUSTER_N, default off, "auto" picks
  the largest supported degree dividing the N-tile count); a partially filled
  cluster would stall, so only divisors are usable.

Cross-tile prefetch (next_stage)
  Computes a k-tile's last k128 while lds-loading the next tile's first one.
  Env AITER_TDM_NEXT_STAGE_PREFETCH, default on; it only engages when
  num_buffers leaves a TDM in flight after the rotated wait, so there is no
  force-on. The k-tile loop is a rolled scf.for, so the tile boundary cannot
  carry a Python value across iterations: one k128 of A/B/scales lives in two
  fixed rmem slots alternating on ksl parity, shared by the within-tile
  prefetch and the cross-tile carry rather than kept as a separate structure.
  The carry targets slot 0, so it precedes the subtile's WMMA except when that
  WMMA reads slot 0 itself (a single-k128 tile), where it follows instead.

Configurable wave grid
  grouped_moe_gfx1250 gains m_warp / n_warp (and gemm2 overrides), validated by
  get_wmma_m_rep(). The WMMA M-repeat fixes the preshuffled A-scale layout the
  quant kernels must produce, so it has to be derived from the wave tile rather
  than from tile_m whenever m_warp > 1.

Main-loop depctr and epilogue scheduling
  Five changes, each measured on t256x256x256 with --ep-mode fake --const-init 0:
  - mma_group keyed on stage1_act (4 with activation, 8 without): gemm2 -5.0%.
  - LDS addresses split into a per-lane region base plus a compile-time offset
    that folds into the ds 16-bit offset: field, with lds_addr_keepalive()
    pinning the bases so the allocator cannot reuse a live base as a later
    ds_load destination: depctr_vm_vsrc 5 -> 0.
  - Bases hoisted and pinned at the tile top: depctr_va_vdst 6 -> 1. Any
    dependence window crossing a WMMA needs va_vdst(0), a full matrix-pipe
    drain, so the fix is to keep the window from crossing one.
  - One scheduling region per k128 plus FENCE_COVER_MMA / FENCE_READ_FRONT,
    putting WMMA between the last ds_load and the tail fence: -3.8%.
  Net main loop 358 -> 344 instructions, s_wait_alu 4 -> 3, no spills.
  - buf_ptr_opaque() on the drain tail's carry target, hiding its LDS stage
    base from constant folding. Unrolled, the base is a literal and the backend
    re-associates (base + lane) + off into (base + off) + lane, spending one
    v_add and one depctr wait per ds_load instead of sharing a base register
    with 16-bit offset: immediates -- 63 address registers against the main
    loop's 8. Applied to the carry target only: the buffer a tile computes from
    must stay foldable or it reads wrong LDS. Epilogue 4596 -> 4499, s_wait_alu
    325 -> 271, -2.1%.

Retuned tuned_grouped_fmoe.csv for the new configuration space.
…g-pong from zan/a8w4_pipeline

- C staging pads the row pitch to STORE_N+16 on the bf16 passthrough path.
  Unpadded the pitch is a multiple of 32 dwords, so the 16 rows one
  ds_store_b128 writes all land on one bank (16-way); +16 cols spreads them
  to 4-way, the b128 floor. The TDM store reads the padded width and lets the
  per-dim OOB extent clamp the inner axis, so pad cols never reach global.
- The post-compute drain's last tile emits no fence; the previous tile's
  rotated fence already covers the only buffer it reads.
- vgpr_keepalive() pins each row's b128 store data across the next row's cvt
  batch, forcing fresh registers and removing the WAR vm_vsrc wait.

4130 -> 3955 us (t256x256x256 cn=4, random activations).
@yadaish
yadaish requested a review from a team August 13, 2026 09:10
@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:gfx1250-ffm-triton Run the five-shard gfx1250 FFM Triton test suite
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 4730 --add-label <label>

yadaish and others added 2 commits August 13, 2026 18:04
Co-authored-by: zanzhang <zanzhang@amd.com>
Co-authored-by: zanzhang <zanzhang@amd.com>
@yadaish
yadaish force-pushed the dev/yadai_cluster_exp_v2_rebase branch from bd98c6b to 8c5245e Compare August 13, 2026 10:04
@zufayu
zufayu requested a review from coderfeli August 14, 2026 01:31
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