[MoE] MegaMoE A4W4: remove dispatch-pointer scalarization waterfalls and retune bs=512 dispatch CUs - #999
Closed
jhinpan wants to merge 1 commit into
Closed
[MoE] MegaMoE A4W4: remove dispatch-pointer scalarization waterfalls and retune bs=512 dispatch CUs#999jhinpan wants to merge 1 commit into
jhinpan wants to merge 1 commit into
Conversation
…=512 dispatch CUs Every dispatch slot holds one 64-bit pointer at a compile-time constant index and `rdisp` is wave-uniform, so all lanes read the same value. The vector load still left it in VGPRs, and codegen then wrapped *every* buffer access built from those pointers in a scalarization waterfall (readfirstlane / v_cmp_eq_u64 / saveexec loop). Reading the halves with scalar loads makes the descriptor uniform by construction: Stage1 goes from 4275 to 3351 static instructions (-21.6%), with v_readfirstlane -290, v_cmp_eq_u64 -132 and s_and_saveexec -71. Separately, sweeping num_dispatch_cu for the FP4 bucket-512 override puts the bottom of the curve at 64 rather than 160. Measured on 8xMI355X, DeepSeek-V4-Pro A4W4, interleaved A/B, median of 5 rounds: bs=512 0.5602 -> 0.5531 ms (-1.3%, wins 4/5) bs=1024 0.7451 -> 0.7391 ms (-0.8%, wins 5/5, disjoint distributions) A8W4 is unchanged. Accuracy is unchanged for both quantization modes.
Collaborator
Author
|
Closing this. The measured effect is too small to justify review bandwidth: bs=512 is -1.3% but the base and patched distributions overlap (4/5 rounds, p≈0.19), so it is not separable from run-to-run noise; bs=1024 is a clean -0.8% (5/5, disjoint distributions) but 0.8% against a 5% regression is not worth a PR. The diagnosis is the useful part and it now lives on #972: #972 (comment) — the regression is traced to #985, with six hypotheses ruled out by measurement and the remaining evidence pointing at intra-kernel workgroup scheduling rather than any hot instruction sequence. The branch |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation
While benchmarking this branch's A4W4 path on 8×MI355X I found that two shapes miss
the golden latencies committed in
_MEGA_PERF_BASELINE— and that they are exactlythe two shapes
_MEGA_BENCH_PARAMSgates fora4w4:972e1a94)v4_pro:a4w4:512v4_pro:a4w4:1024This is currently invisible to CI:
prepare-mlirfails in theBuild LLVM oncestep,so
testand the multi-GPU jobs are all SKIPPED and thea4w4perf gate never runs.This PR recovers part of that and documents the rest. It does not close the whole
gap — see "What this does not fix" below.
Technical Details
1. Dispatch-table pointers no longer force scalarization waterfalls.
dp()reads a 64-bit pointer out of the dispatch slot table at a compile-time constantindex, and
rdispis wave-uniform, so every lane gets the same value. The vector loadstill leaves it in VGPRs, so codegen wraps every buffer access built from those
pointers in a waterfall loop:
Reading the two halves with
buffer_load(..., is_scalar=True)lands them in SGPRs, sothe descriptor is uniform by construction. Final ISA for the Stage1 kernel:
v_readfirstlane_b32v_cmp_eq_u64_e64s_and_saveexec_b64s_cbranch_execnzs_buffer_load_dwordx2VGPR (108), SGPR (112), LDS (79872) and grid geometry are unchanged.
2.
num_dispatch_curetuned for the FP4 bucket-512 override.Sweeping the knob on
a4w4bs=512 gives a clear minimum at 64, not the 160 currentlyset (
prequant_e2e, ms): 24→0.5787, 32→0.5723, 48→0.5605, 64→0.5523, 88→0.5577,104→0.5594, 128→0.5600, 160→0.5608, 192→0.5696, 224→0.5731.
Note
_select_bounded_stage1already usesdispatch_cu=64for bucket 512 on thedynamic-MTPR path, so this brings the FP4 override in line with it.
grid_mult,use_tile_resource,external_grouping/external_countingandpersist_cuwere swept too and are all within noise at these shapes.Test Plan
v4_pro,--mega-only, accuracy against the FP32 oracle fora4w4(bs 64/512/1024) and
a8w4(bs 512/4096).granularity, medians over 5 rounds, on a node verified idle over a 24 s sampling
window (all 8 GPUs at 0% across 12 samples).
a4w4shape sweep, bs 1 … 32768.Test Result
Interleaved A/B,
a4w4,prequant_e2e(ms), median of 5 rounds:Per round — bs=512 base
0.5585 0.5649 0.5635 0.5602 0.5592, PR0.5511 0.5531 0.5507 0.5612 0.5542; bs=1024 base0.7451 0.7449 0.7460 0.7432 0.7457,PR
0.7408 0.7401 0.7382 0.7375 0.7391(base minimum 0.7432 > PR maximum 0.7408).Against the committed goldens: bs=512 goes from +4.7% to +3.4%, bs=1024 from
+5.7% to +4.8%. Both gate shapes are back under the +5% threshold on the median,
where bs=1024 was previously over it.
A8W4 (bs=4096, interleaved, 3 rounds): within noise, no regression.
Accuracy (unchanged from branch head):
a4w4relL2 2.292e-01 / 2.256e-01 /2.269e-01 at bs 64/512/1024 (floor ~0.28);
a8w4relL2 4.666e-02 / 5.352e-02 atbs 512/4096 (floor ~0.1). All 8 ranks pass.
What this does not fix
The remaining +3.4% / +4.8% over golden is a real regression that entered with
0369a804, the first merge ofmaininto this branch, and the only commit in thatmerge touching
kernels/mega_moe/is #985 (2d65dea1, "Optimize megamoeperformance"). Ladder,
prequant_e2e(ms):a62685deee9fb4fc(last A4W4 commit before the merges)0369a804(first merge of main)9baf8cec,972e1a94(later merges)ee9fb4fcreproduces the golden at bs=512 to within 0.04%, so the measurementenvironment is comparable to the one the goldens were captured on.
This looks like an A8W4-tuned change that A4W4 does not benefit from, which is
consistent with #985 having been validated on A8W4 while A4W4 lived on this branch.
The following were each ruled out by measurement, and are recorded so nobody
repeats them:
kernels/common/buffer_ops.pyand running0369a804on the older wheel reproducesthe regressed numbers; and reverting all of
kernels/mega_moe/while running on thenewer wheel fully recovers them.
mega_moe_config.py. Keeping Optimize megamoe performance #985's config and reverting only the four kernelfiles recovers to 0.5353 / 0.7306.
and buys 0.8–1.3%.
0.0004 vs 0.0005 ms.
SQ_BUSY_CYCLES-1.8%,SQ_WAIT_ANY-2.6%,SQ_WAIT_INST_ANY-5.0%.A build that does strictly less shader work, at the same occupancy, with no rank skew,
yet takes 7.7% longer points at intra-kernel workgroup scheduling / critical path
rather than at any single hot instruction sequence. Resolving that needs per-wave (ATT)
data or knowledge of the intended payload-overlap schedule.
@GwilliamHu — #985's dispatch geometry and skewed-expert scheduling changes are the
remaining suspect; could you take a look at whether the payload-overlap schedule
assumes the A8W4 payload size? A FP4 row is 896 i32 against A8W4's 1792.
@Yaowu-Xiong — the
num_dispatch_cuchange lands in your FP4 override; happy to dropit from this PR if you would rather retune that table as a whole.