[Triton/Gluon] moe_gemm_a4w4 num_warps 8 -> 4 for block_m != 16 tile - #5189
Conversation
🏷️ CI GuideRuns automatically on every PR:
Extended tests (opt-in via labels):
PR title tags & labels: |
|
Triton tests didn't run! Let's not merge this before CI runs properly. |
74088f5 to
a1b4ac8
Compare
Rebased on top of |
There was a problem hiding this comment.
🟡 Changes recommended
The gfx950 tuning affects other architectures and should be moved into architecture-specific JSON dispatch.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
Adjusts the MoE A4W4 Triton fallback to reduce register spilling on gfx950.
Changes:
- Reduces non-16
block_mlaunches from 8 to 4 warps.
File summaries
| File | Description |
|---|---|
aiter/ops/triton/moe/moe_op_gemm_a4w4.py |
Changes the fallback warp count. |
Review details
- Files reviewed: 1/1 changed files
- Comments generated: 1
- Review effort level: Balanced
💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Motivation
moe_gemm_a4w4spills registers on gfx950. Theblock_m != 16branch ofget_kernel_config_triton()launches ablock_n=512, block_k=256tile withnum_warps=8, and at a large M that overruns the VGPR budget: the compiled kernel carries 68 bytes of scratch on both M4096 shapes measured. Spilling costs roughly 17% there.Dropping to 4 warps gives each wave enough registers to keep everything live. The spills no longer show and the op gets faster across the shapes, with none being slower than before.
Worth noting this op has no tuned config at all on gfx950 --
_get_a4w4_dispatch()looks for{arch}-A4W4.jsonand onlygfx1250-A4W4.jsonships, so it falls back to the hardcoded tile above.Note: There is also no Triton 3.4 baseline to compare against. Therefore "regression" below means slower than the current fallback (shipped), not slower than 3.4.
Technical Details
Only the
block_m != 16branch is affected;block_m == 16already used 4 warps and is unchanged (confirmed by measurement below).Sweep evidence: 18 candidates were measured across all 6 shapes (
num_warps,block_n,block_k,num_stages,waves_per_eu,matrix_instr_nonkdim,kpack,xcd_swizzle, and combinations).num_warps=4was the only one that beat the baseline without regressing a shape or spilling; every other parameter for adjusting either spilled on the M4096 shapes, failed to compile, or regressed a shape by up to 1.44x.Test Plan
rocprofv3 --kernel-trace, first and last 10% dropped, mean of the middle 80%. 250 iters -> 200 kept, 7 reps, median.VGPR_CountandScratch_Sizeread from the same trace so the spill claim is measured, not inferred.Shapes from
model_benchmarking_tool/model_shapes.json(moe_op_gemm_a4w4):E=256, Dim1=7168, Dim2=4096, TopK=8and
E=384, same dimsacross an M sweep of 128 / 1024 / 4096. All 6 shapes measured, including the two in the untouched
block_m == 16branch.Test Result
Geomean 0.9179x across all 6 shapes. Worst case 1.0000x -- no shape regresses.
The two M128 rows are in the
block_m == 16branch and land at 1.0000x / 0.9995x, confirming the change does not reach them.Register pressure
Per-wave VGPR rises because half as many waves share the same budget -- that is the point. With 8 warps the allocator could not fit the working set and spilled; with 4 it fits, and scratch goes to zero.
Correctness
op_tests/triton_tests/moe/test_moe_gemm_a4w4.py: 224 passed, 0 failed, 384 skipped -- byte-identical to the unmodified baseline (224/384 either way), so the skips are pre-existing arch gating, not caused by this change.Lint:
black --checkandruff checkclean.Submission Checklist