Repository navigation
perf(EPv2/gfx1250): retune EP4 topk-9 fp4 combine; un-shadow the topk-9 dispatch row - #737
Merged
Merged
Conversation
…-9 dispatch row ROCm#725 and ROCm#726 each added a (4, 7168, 9, None) key to _DISPATCH_TABLE, so the later dict entry silently replaced the earlier one: ROCm#725's block-256 schedule never took effect, and a bf16-keyed lookup for topk 9 fell back to the 64x16 single-shot default. Merge the two into one entry (keeping ROCm#725's row as the default) and drop the same duplicate from _COMBINE_TABLE. fp4 dispatch at topk 9 now uses 256x8 up to 4096 tokens and 128x16 past it. The fp4 push combine at topk 9 moves to 256x16 up to 2048 tokens and 256x24 up to 16384: in MegaMoE nothing runs beside the combine, so the whole grid pays (1536 tokens: 47.8 -> 28.8 us; 16384: 243.4 -> 156.1 us). bench_ep gains ROUTE=grouped, ATOM's --fake-eplb placement for group-limited routing (DeepSeek) with a shared column pinned to the own rank; ROUTE=ring only matches models without group-limited routing. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…spell out ROUTE=grouped 192x8 holds one token a warp up to 1536 tokens, the decode batch, and beats 256x8 there (33.5 vs 35.3 us, grouped routing); past 1536 it would give warps a second token, so 256x8 keeps 1537..4096. ROUTE=grouped now names every quantity after ATOM's own comments and reads EXPERT_GROUPS / TOPK_GROUPS / SHARED_EXPERTS; the routing it builds is unchanged (checked element for element against the previous version). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The HIP dispatch and combine tables are independent, yet the dispatch table was
keyed by EpDispatchCombineConfig.dtype_str, which names both halves
("fp4_disp_bf16_comb"). On HIP the combine half is always bf16 rows (its wire
format is quant_type's table), so the key now reads "fp4". lookup() maps the
old string to it, so the op layer and out-of-op callers that pass dtype_str get
the same schedules (72 lookups across every device/key/quant compared equal).
FlyDSL's table, which does need both halves, keeps its keys.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Collaborator
Author
|
/ci-rerun |
Contributor
|
Re-running MoRI CI test and CCO CI test against the current main. |
…e_str
HIP tunes dispatch and combine in separate tables: the dispatch half is keyed
by what dispatch transports, the combine half by quant_type. The op layer
still handed it EpDispatchCombineConfig.dtype_str, FlyDSL's key, which names
both halves ("fp4_disp_bf16_comb") and reads as if HIP's dispatch geometry
depended on the combine dtype.
Add EpDispatchCombineConfig.dispatch_dtype_str ("fp4" / "fp8" / "bf16") and
use it for the HIP lookup; dtype_str stays FlyDSL's key. lookup() documents
dtype as the dispatch wire and keeps "fp4_disp_bf16_comb" only as an alias
for callers that pass dtype_str (aiter's MegaMoE). Every HIP lookup returns
the same schedule as before: 5x5 dispatch/combine dtypes x every table key x
every quant type, 450 lookups, 0 differ.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…f16 combine Re-swept on main + this PR (4x gfx1250, EP4, hidden 7168, topk 9, 65 experts a rank): bench_ep.py, HIP graph, per-leg hip events, both halves pinned, 4 to 16384 tokens a rank, random and grouped (ATOM fake-EPLB) routing; every point passed CHECK. Every bucket below is within ~3% of the best under both routings. - fp4 dispatch: 64x8 to 512, 256x8 to 2048, 256x24 to 4096, 256x32 above (16384: 153.4/124.5 us random/grouped, against 128x16's 164.0/124.3). - fp4 push combine: 256x8 to 1024, 256x16 to 2048, 192x24 above (16384: 158.5/132.6 us, against 256x24's 167.8/133.2). - bf16 pull combine, untuned until now (64x8 throughout): 128x8 to 256, 256x8 to 4096, 192x8 above (1536: 60.6/44.4 us against 71.8/69.0; 16384: 484.7/338.3 against 599.0/609.7). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Re-picked every topk-9 bucket by the rule the topk-6 rows already follow: the fewest blocks within 3% of the best under both random and grouped routing, so the CUs a kernel does not need stay free for whatever runs beside it. 256 blocks remain only where nothing smaller comes within 5%. Swept 192x24/192x32 dispatch, 128x8/192x8 fp4 combine and 192x16 bf16 combine as well, and the lower-block candidates under grouped routing. - fp4 dispatch: 64x8 / 128x8 / 192x8 to 512 / 1024 / 1536, 256x8 to 2048, 192x24 to 8192, 192x32 above (1536 takes 192x8, which ties 256x8). - fp4 push combine: 64x8 to 128, 192x8 to 512, 256x8 to 1024, 192x16 to 1536, 256x16 to 2048, 192x24 above. - bf16 pull combine: 64x4 to 64, 64x8 to 128, 128x8 to 256, 256x8 to 1024, 192x8 above. Worst slowdown against the best geometry, 16+ tokens: dispatch 5.4% (16384, grouped), fp4 combine 4.6% (1536, grouped), bf16 combine 6.5% (16, grouped). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Conflicts in hip_tuning_configs.py, resolved to this branch's tables: - topk-9 fp4 dispatch: this branch's sweep (main kept ROCm#726's row under "fp4_disp_bf16_comb"; main also un-shadowed the ROCm#725 row, as this branch did). - topk-6 fp4 dispatch: same buckets, keyed "fp4" as on this branch. - the combine-table comment: main's (EP8 and EP16). Main's new EP16 dispatch row is re-keyed from "fp4_disp_bf16_comb" to "fp4", since lookup() now reads that spelling as "fp4"; under the old key the row would never match. Checked against main over every table key, dispatch dtype and quant type (112 lookups): every key but topk 9 returns what main returns for "bf16", "fp8" and "fp4_disp_bf16_comb". Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… from bench_ep
hip_tuning_configs.py: the topk-9 rows keep their geometry; the sweep tables and
the reasoning around them leave the comments. The bf16 combine row's comment
says what the row is for, since the old one ("mirrors topk 8, only the dispatch
half is retuned") no longer holds.
bench_ep.py: ROUTE=ring and ROUTE=grouped describe the placement they generate,
without naming the serving stack it came from.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
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.
Summary
Tuning tables and HIP lookup key for gfx1250 EP4 topk 9: DeepSeek-R1 with its shared expert dispatched as a ninth column.
quant_type.EpDispatchCombineConfig.dtype_str, which is FlyDSL's key. It names both halves ("fp4_disp_bf16_comb"), so it reads as if HIP's dispatch geometry depended on the combine dtype."bf16"/"fp8"/"fp4". This covers every row, including the mi355x EP8 and gfx1250 EP8/EP16 ones.EpDispatchCombineConfig.dispatch_dtype_str.dtype_strstays FlyDSL's key.lookup()still accepts"fp4_disp_bf16_comb"as an alias, for callers that passdtype_str(aiter's MegaMoE).dtype_strand passingdispatch_dtype_strgive the same result for 700 lookups: 5x5 dispatch/combine dtypes x 7 (device, shape) keys x 4 quant types, 0 differ.dtype_strand this PR givendispatch_dtype_stror the alias.bench_ep.pyalso getsROUTE=grouped: group-limited routing (DeepSeek'sEXPERT_GROUPS=8,TOPK_GROUPS=4), withSHARED_EXPERTS=1trailing column pinned to the token's own rank. UnderROUTE=ringwith topk >= world, every token reaches all 4 ranks. Undergrouped, a token reaches 2-3 ranks and the ranks receive unevenly: 3072/4608/4608/3072 rows at 1536 tokens. Theringcomment no longer describes it as a serving placement.Lookup: main vs this PR (topk 9, gfx1250 EP4)
Geometry is block x warp; "to N" is the bucket's upper token bound.
"fp4"; main's key"fp4_disp_bf16_comb")quant_type="fp4_blockwise")quant_type="none")The bf16/fp8 dispatch rows are unchanged, and so are the fp8 push combine table, topk 6, topk 8, EP8 and EP16.
Measurements
Setup:
76d0b301+ this PR,bench_ep.py, HIP graph.DBN/DWPB/CBN/CWPBfor every point, since an unpinned half falls back to the single-shot default. Each leg is timed with hip events inside the graph.CHECK=1.Worst slowdown of a pick against the best geometry, 16+ tokens a rank:
fp4 dispatch, us (random / grouped), combine pinned at 256x16:
fp4 push combine, us (random / grouped), dispatch pinned at 128x16:
bf16 pull combine, us (random / grouped), dispatch pinned at 128x16. 192x8 is slow at 256-1024 under both routings, which keeps 256x8 there:
Test status
black/ruff(repo versions) and pre-commit pass.lookup()was evaluated offline for every key above.🤖 Generated with Claude Code