CUDA: size routed MoE MMQ N-tiles from typical expert width on RDNA3 - #24546
CUDA: size routed MoE MMQ N-tiles from typical expert width on RDNA3#24546ravel7524 wants to merge 7 commits into
Conversation
|
Here is an additional sweep extending the prior Hardware/software: AMD Radeon Pro W7800 (
Across the tested 128 expert models, the gain persists at long context for smaller ubatches, and the larger ubatches are effectively neutral rather than regressing. I can do additional long context benchmarking for 256 expert models |
|
@jiachengjason would you be able to benchmark this PR on your RDNA4 GPU when you have time? Since you tested #23685 on RDNA4, having the same kind of validation here would be very helpful. If you know anyone who could also test on RDNA2 or CDNA, that would be great as well. No pressure. |
|
@IMbackK when you have time, could you sanity check whether this RDNA3 routed MoE MMQ selector direction looks reasonable? The PR is scoped to gfx1100/RDNA3 and uses measured W7800 results; I mainly want to know if the shape is acceptable or if you would prefer a different architecture gating/config style. |
|
Do you expect this to work well on RDNA3.5 / Strix Halo as well? Happy to test! |
|
Yes, the PR’s RDNA3 predicate also includes RDNA3.5 / Strix Halo, so the routed-width selector should be active there. I expect the same general direction, although the performance magnitude may differ from gfx1100. Testing would be very helpful, ideally the same base vs PR prefill and decode comparison used in the PR. |
…24546) Upstream PR ggml-org#24546 (ravel7524, open) sizes routed-MoE MMQ N-tiles from the typical expert width instead of the worst case. That is the same problem the static J_max=48 cap from Findings ggml-org#8/ggml-org#9 solves, approached from the other end: the cap clamps the search ceiling, the picker fixes the search objective. This commit swaps the cap for the picker so the two can be A/B'd on gfx1151. The PR does not apply as written - it patches mmq_x/mmq_x_max/ mmq_get_granularity_host in mul_mat_q_case, all deleted by PR ggml-org#24127, the same refactor that forced the Finding ggml-org#5 -> ggml-org#9 re-port. Re-authored onto mul_mat_q_switch_J's config-table search and scoped to RDNA3.5: gfx1151 is the only arch we can measure, and narrowing the predicate keeps the A/B single-variable. Upstream's predicate already covers RDNA3.5 via GGML_CUDA_CC_IS_RDNA3, and the author confirmed on 2026-07-04 that Strix Halo should benefit, but nobody has ever tested it there. On the routed-MoE path ncols_max is ne12 - the worst case of one expert receiving every token - so the search never reaches ntiles==1 and simply runs to whatever ceiling it is given. The picker instead tiles from ncols_dst/nchannels_x, the width a typical expert covers. launch_mul_mat_q still builds the grid from ncols_max, so worst-case coverage is unchanged. - mmq.cuh: replace the RDNA3.5 MoE J_max=48 clamp with the typical-width picker; J_max is now a uniform 128 and the search terminates on its own. - mmq-table-check.cpp: pick_J mirrors the selection loop, so update it in lockstep or the check silently becomes a rubber stamp. Adds the routed-MoE arg shape from mmq.cu and a crossover case. For Qwen 3.6 35B-A3B (256 experts, 8 active) at the production ub=2048 the typical width is 2048*8/256 = 64, so this is a 48 -> 64 change at our operating point - narrow enough that it may land in noise. Verified host-side without ROCm: MoE J=64, dense J=128, no aborts across all 21 types. Above ub=4096 the typical width reaches 128, the picker disengages and the search runs to J=128 where the cap held 48. Findings ggml-org#5/ggml-org#8 only ever measured the typical=64 regime, so that is untested on this chip; production ub=2048 cannot reach it. See strix-halo/mmq-moe-ncols-picker.md for the bench plan and the keep/revert criteria. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Benched b47bb31e1 against 05e837f on gfx1151 (ROCm 7.14.0, canonical Qwen 3.6 35B-A3B Q4_K_XL matrix). The picker is not distinguishable from the static cap at the production operating point: pp512 @ d=0 1428.13 -> 1388.93 (-2.7%) pp512 @ d=2048 1299.39 -> 1316.26 (+1.3%) pp512 @ d=8192 1135.42 -> 1142.23 (+0.6%) pp512 @ d=16384 971.25 -> 977.36 (+0.6%) Correctness was clean first (790/790 MUL_MAT_ID, 1134/1134 MUL_MAT), so the grid does still cover ncols_max while the tile is sized from the typical width. The tg128 control fell ~1.6% at every depth. This change cannot move tg - decode goes through MMVQ where ncols_dst==1, so the picker never runs - which makes that a session drift between two builds measured on different days, the same contamination Finding ggml-org#9 hit. The conclusion survives it either way: raw, pp is -2.7% to +1.3%; calibrated against the drift, -1.2% to +2.9%. Every depth is inside the host's ~2% noise floor, so the effect is smaller than this rig can resolve, and the d=0 -2.7% is no more real than the d=2048 +1.3%. So: at ub=2048, J=48 and J=64 are the same speed. The doc predicted this before the numbers existed ("narrow enough that it may well land in noise"), which is the only reason that reading is credible rather than post-hoc. Reverting to the static cap because it is the validated status quo, not because it won. Worth reporting on ggml-org#24546: the picker is neutral on RDNA3.5, on the exact model and ubatch its sweep claims +7.57% for on gfx1100. The PR is gated on GGML_CUDA_CC_IS_RDNA3, which covers both. gfx1151's table is I=64/ nthreads=128 vs gfx1100's I=128/nthreads=256 - our tiles are already half-width, so there is much less worst-case over-sizing left to recover. That is the data ravel7524 asked for on 2026-07-03. Doc kept with the numbers and the untested ub>=4096 crossover regime recorded. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
I think this is a reasonable idea, but it would have to be updated for the changes in #24127 |
9ab2b07 to
3087cea
Compare
|
I adapted the implementation to the MMQ configuration changes from #24127 and I provisionally enabled the selector for NVIDIA Volta and newer so those architectures can be benchmarked. |
…ols_min_cc support
|
I tested it on CDNA 1 and it seams that its not entirely a win in all cases.
|
IMbackK
left a comment
There was a problem hiding this comment.
Dont bother cleaning this up if its not uniformly performance positive at least on rdna3
…configuration files
|
missclick |
9c9bcc8 to
7d8bc65
Compare
|
Merged |
|
Ok, I will remove the "merge ready" label for now. Let us know when your A/B tests are complete. |
No regressions larger than 0.83% were observed. Results at and beyond the expected ubatch crossover were effectively neutral, while smaller ubatches showed consistent gains; tg128 also remained neutral. |
|
Independent validation on multi-GPU RDNA3 (gfx1101) with a 512-expert MoE. Short version: I reproduce large prefill gains, I see no correctness change, and four of your five failing checks cannot be caused by this PR — I could not reproduce the fifth either. Setup
Results
Decode is untouched, as expected. On pp2048 and pp8192 the standard deviation is under 0.4 %, so the gain is well outside the noise. This is on a different die from your W7800 (gfx1101 vs gfx1100) and across 6 GPUs with Correctness
The set of case descriptors is identical between the two runs. I am not claiming a byte-identical log — the async No regression on the routed-MoE path here. I also checked end-to-end generation, since
The long one matters because the short prompts barely exercise the changed path — at a few dozen tokens the prefill is one small ubatch, whereas the 5048-token prompt runs just under ten full CI triageThis is probably the more useful part, and it argues that most of the red is not yours.
Both pass on master ( More importantly, three of your five failing checks are on backends this PR cannot reach. The diff is confined to That left two hypotheses:
I then tested hypothesis 2 directly, using the trick from ikawrakow/ik_llama.cpp#2339 — you do not need an NVIDIA GPU to compile for one. I built the
No compile error under Going further, I compared the generated device code. Raw Same instruction count, same addresses, same scheduling; So the entire device-code footprint of this PR on NVIDIA is one line number inside an error path that only runs when a template specialisation is skipped. For Worth requesting a CI re-run — I do not think there is anything here to fix. Note for anyone reproducing from the
|
|
Sorry @ggerganov, forgot to ping you, benchmark results are positive and the additional comment confirms the results |
|
I ran an independent Windows/gfx1151 backport experiment based on the typical-expert-width MMQ configuration idea in this PR. Environment: Windows 11, AMD Ryzen AI Max+ 395 / Radeon 8060S ( Important limitation: this was implemented in an older MMQ scanner, so it is not a test of the current PR HEAD and was not rebased after PR #26284. Operator correctness after making the loader, kernel and write-back wave counts consistent:
Operator median improvements for typical expert width 16:
Q4_K_M model-level Prefill at
The broad configuration initially regressed
The final scoped candidate passed Q4_K These results support testing a narrowly scoped gfx1151/ |
|
Tested on Windows 11, ROCm 7.1, Radeon 8060S (gfx1151).
One thing worth flagging: in the current source, gfx1151 sets |
IMbackK
left a comment
There was a problem hiding this comment.
Is still beneficial against and when rebated on latest master.
Details
| GPU | Model | Microbatch size | Test | t/s master | t/s mmqx-rdna3-routed-moe-tiling | Speedup |
|---|---|---|---|---|---|---|
| RX 7900 XTX | gemma4 26B.A4B Q6_K | 8 | pp2048 | 430.12 | 430.35 | 1.00 |
| RX 7900 XTX | gemma4 26B.A4B Q6_K | 64 | pp2048 | 1058.57 | 1553.66 | 1.47 |
| RX 7900 XTX | gemma4 26B.A4B Q6_K | 512 | pp2048 | 2502.63 | 3197.90 | 1.28 |
| RX 7900 XTX | gemma4 26B.A4B Q6_K | 1024 | pp2048 | 3316.65 | 3773.25 | 1.14 |
| RX 7900 XTX | gpt-oss 20B MXFP4 MoE | 8 | pp2048 | 636.17 | 635.05 | 1.00 |
| RX 7900 XTX | gpt-oss 20B MXFP4 MoE | 64 | pp2048 | 1594.12 | 2116.75 | 1.33 |
| RX 7900 XTX | gpt-oss 20B MXFP4 MoE | 512 | pp2048 | 3846.41 | 4696.47 | 1.22 |
| RX 7900 XTX | gpt-oss 20B MXFP4 MoE | 1024 | pp2048 | 4809.61 | 4831.44 | 1.00 |
| RX 7900 XTX | lfm2moe 8B.A1B F16 | 8 | pp2048 | 402.41 | 402.97 | 1.00 |
| RX 7900 XTX | lfm2moe 8B.A1B F16 | 64 | pp2048 | 2451.46 | 2449.18 | 1.00 |
| RX 7900 XTX | lfm2moe 8B.A1B F16 | 512 | pp2048 | 6072.19 | 6058.35 | 1.00 |
| RX 7900 XTX | lfm2moe 8B.A1B F16 | 1024 | pp2048 | 8385.86 | 8395.05 | 1.00 |
| RX 7900 XTX | lfm2moe 8B.A1B Q4_0 | 8 | pp2048 | 1413.81 | 1417.80 | 1.00 |
| RX 7900 XTX | lfm2moe 8B.A1B Q4_0 | 64 | pp2048 | 3433.56 | 4559.60 | 1.33 |
| RX 7900 XTX | lfm2moe 8B.A1B Q4_0 | 512 | pp2048 | 9144.60 | 10884.34 | 1.19 |
| RX 7900 XTX | lfm2moe 8B.A1B Q4_0 | 1024 | pp2048 | 11583.59 | 11661.76 | 1.01 |
| RX 7900 XTX | lfm2moe 8B.A1B Q4_K_M | 8 | pp2048 | 1003.92 | 1012.50 | 1.01 |
| RX 7900 XTX | lfm2moe 8B.A1B Q4_K_M | 64 | pp2048 | 3185.46 | 4461.54 | 1.40 |
| RX 7900 XTX | lfm2moe 8B.A1B Q4_K_M | 512 | pp2048 | 8429.84 | 10221.60 | 1.21 |
| RX 7900 XTX | lfm2moe 8B.A1B Q4_K_M | 1024 | pp2048 | 10737.57 | 10826.09 | 1.01 |
| RX 7900 XTX | lfm2moe 8B.A1B Q5_K_M | 8 | pp2048 | 985.99 | 989.12 | 1.00 |
| RX 7900 XTX | lfm2moe 8B.A1B Q5_K_M | 64 | pp2048 | 3128.37 | 4400.83 | 1.41 |
| RX 7900 XTX | lfm2moe 8B.A1B Q5_K_M | 512 | pp2048 | 8249.88 | 9973.57 | 1.21 |
| RX 7900 XTX | lfm2moe 8B.A1B Q5_K_M | 1024 | pp2048 | 10564.36 | 10640.39 | 1.01 |
| RX 7900 XTX | lfm2moe 8B.A1B Q6_K | 8 | pp2048 | 852.31 | 860.02 | 1.01 |
| RX 7900 XTX | lfm2moe 8B.A1B Q6_K | 64 | pp2048 | 2257.27 | 3378.81 | 1.50 |
| RX 7900 XTX | lfm2moe 8B.A1B Q6_K | 512 | pp2048 | 5863.58 | 7124.40 | 1.22 |
| RX 7900 XTX | lfm2moe 8B.A1B Q6_K | 1024 | pp2048 | 7587.75 | 7671.78 | 1.01 |
| RX 7900 XTX | lfm2moe 8B.A1B Q8_0 | 8 | pp2048 | 1020.85 | 1024.86 | 1.00 |
| RX 7900 XTX | lfm2moe 8B.A1B Q8_0 | 64 | pp2048 | 3461.44 | 4352.49 | 1.26 |
| RX 7900 XTX | lfm2moe 8B.A1B Q8_0 | 512 | pp2048 | 9130.16 | 11053.51 | 1.21 |
| RX 7900 XTX | lfm2moe 8B.A1B Q8_0 | 1024 | pp2048 | 11759.62 | 11835.76 | 1.01 |
| RX 7900 XTX | qwen35 27B Q5_K_M | 8 | pp2048 | 98.13 | 98.63 | 1.01 |
| RX 7900 XTX | qwen35 27B Q5_K_M | 64 | pp2048 | 557.11 | 558.72 | 1.00 |
| RX 7900 XTX | qwen35 27B Q5_K_M | 512 | pp2048 | 758.67 | 762.83 | 1.01 |
| RX 7900 XTX | qwen35 27B Q5_K_M | 1024 | pp2048 | 776.35 | 778.11 | 1.00 |
| Backend | GGML op | Op parameters | TFLOPS master | TFLOPS mmqx-rdna3-routed-moe-tiling | Speedup |
|---|---|---|---|---|---|
| ROCm0 | MUL_MAT_ID | type_a=f16,type_b=f32,n_mats=128,n_used=8,b=0,m=768,n=1,k=2048 | 0.85 | 0.89 | 1.04 |
| ROCm0 | MUL_MAT_ID | type_a=f16,type_b=f32,n_mats=128,n_used=8,b=0,m=768,n=128,k=2048 | 5.07 | 5.13 | 1.01 |
| ROCm0 | MUL_MAT_ID | type_a=f16,type_b=f32,n_mats=128,n_used=8,b=0,m=768,n=256,k=2048 | 6.49 | 6.39 | 0.98 |
| ROCm0 | MUL_MAT_ID | type_a=f16,type_b=f32,n_mats=128,n_used=8,b=0,m=768,n=32,k=2048 | 1.64 | 1.76 | 1.07 |
| ROCm0 | MUL_MAT_ID | type_a=f16,type_b=f32,n_mats=128,n_used=8,b=0,m=768,n=4,k=2048 | 0.91 | 0.83 | 0.91 |
| ROCm0 | MUL_MAT_ID | type_a=f16,type_b=f32,n_mats=128,n_used=8,b=0,m=768,n=512,k=2048 | 7.07 | 7.13 | 1.01 |
| ROCm0 | MUL_MAT_ID | type_a=f16,type_b=f32,n_mats=128,n_used=8,b=0,m=768,n=64,k=2048 | 2.94 | 2.83 | 0.96 |
| ROCm0 | MUL_MAT_ID | type_a=f16,type_b=f32,n_mats=128,n_used=8,b=0,m=768,n=8,k=2048 | 0.80 | 0.83 | 1.04 |
| ROCm0 | MUL_MAT_ID | type_a=f16,type_b=f32,n_mats=32,n_used=4,b=0,m=1792,n=1,k=2048 | 0.87 | 0.89 | 1.02 |
| ROCm0 | MUL_MAT_ID | type_a=f16,type_b=f32,n_mats=32,n_used=4,b=0,m=1792,n=128,k=2048 | 6.07 | 6.66 | 1.10 |
| ROCm0 | MUL_MAT_ID | type_a=f16,type_b=f32,n_mats=32,n_used=4,b=0,m=1792,n=256,k=2048 | 8.04 | 8.04 | 1.00 |
| ROCm0 | MUL_MAT_ID | type_a=f16,type_b=f32,n_mats=32,n_used=4,b=0,m=1792,n=32,k=2048 | 2.78 | 2.71 | 0.98 |
| ROCm0 | MUL_MAT_ID | type_a=f16,type_b=f32,n_mats=32,n_used=4,b=0,m=1792,n=4,k=2048 | 0.88 | 0.94 | 1.07 |
| ROCm0 | MUL_MAT_ID | type_a=f16,type_b=f32,n_mats=32,n_used=4,b=0,m=1792,n=512,k=2048 | 14.21 | 14.20 | 1.00 |
| ROCm0 | MUL_MAT_ID | type_a=f16,type_b=f32,n_mats=32,n_used=4,b=0,m=1792,n=64,k=2048 | 4.77 | 4.73 | 0.99 |
| ROCm0 | MUL_MAT_ID | type_a=f16,type_b=f32,n_mats=32,n_used=4,b=0,m=1792,n=8,k=2048 | 0.85 | 0.85 | 1.01 |
| ROCm0 | MUL_MAT_ID | type_a=f32,type_b=f32,n_mats=128,n_used=8,b=0,m=768,n=1,k=2048 | 0.87 | 0.89 | 1.03 |
| ROCm0 | MUL_MAT_ID | type_a=f32,type_b=f32,n_mats=128,n_used=8,b=0,m=768,n=128,k=2048 | 0.76 | 0.75 | 0.98 |
| ROCm0 | MUL_MAT_ID | type_a=f32,type_b=f32,n_mats=128,n_used=8,b=0,m=768,n=256,k=2048 | 1.01 | 0.95 | 0.94 |
| ROCm0 | MUL_MAT_ID | type_a=f32,type_b=f32,n_mats=128,n_used=8,b=0,m=768,n=32,k=2048 | 0.33 | 0.35 | 1.04 |
| ROCm0 | MUL_MAT_ID | type_a=f32,type_b=f32,n_mats=128,n_used=8,b=0,m=768,n=4,k=2048 | 0.46 | 0.48 | 1.04 |
| ROCm0 | MUL_MAT_ID | type_a=f32,type_b=f32,n_mats=128,n_used=8,b=0,m=768,n=512,k=2048 | 1.78 | 1.81 | 1.02 |
| ROCm0 | MUL_MAT_ID | type_a=f32,type_b=f32,n_mats=128,n_used=8,b=0,m=768,n=64,k=2048 | 0.55 | 0.58 | 1.06 |
| ROCm0 | MUL_MAT_ID | type_a=f32,type_b=f32,n_mats=128,n_used=8,b=0,m=768,n=8,k=2048 | 0.49 | 0.47 | 0.97 |
| ROCm0 | MUL_MAT_ID | type_a=f32,type_b=f32,n_mats=32,n_used=4,b=0,m=1792,n=1,k=2048 | 0.89 | 0.88 | 0.99 |
| ROCm0 | MUL_MAT_ID | type_a=f32,type_b=f32,n_mats=32,n_used=4,b=0,m=1792,n=128,k=2048 | 1.51 | 1.49 | 0.99 |
| ROCm0 | MUL_MAT_ID | type_a=f32,type_b=f32,n_mats=32,n_used=4,b=0,m=1792,n=256,k=2048 | 2.68 | 2.67 | 1.00 |
| ROCm0 | MUL_MAT_ID | type_a=f32,type_b=f32,n_mats=32,n_used=4,b=0,m=1792,n=32,k=2048 | 1.05 | 1.02 | 0.97 |
| ROCm0 | MUL_MAT_ID | type_a=f32,type_b=f32,n_mats=32,n_used=4,b=0,m=1792,n=4,k=2048 | 0.51 | 0.61 | 1.20 |
| ROCm0 | MUL_MAT_ID | type_a=f32,type_b=f32,n_mats=32,n_used=4,b=0,m=1792,n=512,k=2048 | 4.32 | 4.14 | 0.96 |
| ROCm0 | MUL_MAT_ID | type_a=f32,type_b=f32,n_mats=32,n_used=4,b=0,m=1792,n=64,k=2048 | 1.27 | 1.27 | 1.00 |
| ROCm0 | MUL_MAT_ID | type_a=f32,type_b=f32,n_mats=32,n_used=4,b=0,m=1792,n=8,k=2048 | 0.51 | 0.51 | 1.01 |
| ROCm0 | MUL_MAT_ID | type_a=iq2_xs,type_b=f32,n_mats=128,n_used=8,b=0,m=768,n=1,k=2048 | 0.87 | 0.89 | 1.03 |
| ROCm0 | MUL_MAT_ID | type_a=iq2_xs,type_b=f32,n_mats=128,n_used=8,b=0,m=768,n=128,k=2048 | 2.58 | 7.93 | 3.07 |
| ROCm0 | MUL_MAT_ID | type_a=iq2_xs,type_b=f32,n_mats=128,n_used=8,b=0,m=768,n=256,k=2048 | 4.87 | 11.11 | 2.28 |
| ROCm0 | MUL_MAT_ID | type_a=iq2_xs,type_b=f32,n_mats=128,n_used=8,b=0,m=768,n=32,k=2048 | 1.79 | 2.40 | 1.34 |
| ROCm0 | MUL_MAT_ID | type_a=iq2_xs,type_b=f32,n_mats=128,n_used=8,b=0,m=768,n=4,k=2048 | 1.65 | 1.74 | 1.06 |
| ROCm0 | MUL_MAT_ID | type_a=iq2_xs,type_b=f32,n_mats=128,n_used=8,b=0,m=768,n=512,k=2048 | 9.06 | 15.63 | 1.73 |
| ROCm0 | MUL_MAT_ID | type_a=iq2_xs,type_b=f32,n_mats=128,n_used=8,b=0,m=768,n=64,k=2048 | 2.20 | 3.87 | 1.76 |
| ROCm0 | MUL_MAT_ID | type_a=iq2_xs,type_b=f32,n_mats=128,n_used=8,b=0,m=768,n=8,k=2048 | 1.08 | 1.07 | 0.99 |
| ROCm0 | MUL_MAT_ID | type_a=iq2_xs,type_b=f32,n_mats=32,n_used=4,b=0,m=1792,n=1,k=2048 | 1.32 | 1.32 | 1.00 |
| ROCm0 | MUL_MAT_ID | type_a=iq2_xs,type_b=f32,n_mats=32,n_used=4,b=0,m=1792,n=128,k=2048 | 4.99 | 11.13 | 2.23 |
| ROCm0 | MUL_MAT_ID | type_a=iq2_xs,type_b=f32,n_mats=32,n_used=4,b=0,m=1792,n=256,k=2048 | 9.48 | 16.40 | 1.73 |
| ROCm0 | MUL_MAT_ID | type_a=iq2_xs,type_b=f32,n_mats=32,n_used=4,b=0,m=1792,n=32,k=2048 | 3.12 | 3.75 | 1.20 |
| ROCm0 | MUL_MAT_ID | type_a=iq2_xs,type_b=f32,n_mats=32,n_used=4,b=0,m=1792,n=4,k=2048 | 1.65 | 1.70 | 1.03 |
| ROCm0 | MUL_MAT_ID | type_a=iq2_xs,type_b=f32,n_mats=32,n_used=4,b=0,m=1792,n=512,k=2048 | 18.59 | 21.45 | 1.15 |
| ROCm0 | MUL_MAT_ID | type_a=iq2_xs,type_b=f32,n_mats=32,n_used=4,b=0,m=1792,n=64,k=2048 | 4.20 | 7.23 | 1.72 |
| ROCm0 | MUL_MAT_ID | type_a=iq2_xs,type_b=f32,n_mats=32,n_used=4,b=0,m=1792,n=8,k=2048 | 1.23 | 1.16 | 0.95 |
| ROCm0 | MUL_MAT_ID | type_a=mxfp4,type_b=f32,n_mats=32,n_used=4,b=0,m=2880,n=1,k=2880 | 3.20 | 3.20 | 1.00 |
| ROCm0 | MUL_MAT_ID | type_a=mxfp4,type_b=f32,n_mats=32,n_used=4,b=0,m=2880,n=4,k=2880 | 4.86 | 4.86 | 1.00 |
| ROCm0 | MUL_MAT_ID | type_a=mxfp4,type_b=f32,n_mats=32,n_used=4,b=0,m=2880,n=512,k=2880 | 24.47 | 31.41 | 1.28 |
| ROCm0 | MUL_MAT_ID | type_a=mxfp4,type_b=f32,n_mats=32,n_used=4,b=0,m=2880,n=8,k=2880 | 4.43 | 4.61 | 1.04 |
| ROCm0 | MUL_MAT_ID | type_a=q4_0,type_b=f32,n_mats=128,n_used=8,b=0,m=768,n=1,k=2048 | 1.35 | 1.41 | 1.04 |
| ROCm0 | MUL_MAT_ID | type_a=q4_0,type_b=f32,n_mats=128,n_used=8,b=0,m=768,n=128,k=2048 | 3.39 | 11.61 | 3.43 |
| ROCm0 | MUL_MAT_ID | type_a=q4_0,type_b=f32,n_mats=128,n_used=8,b=0,m=768,n=256,k=2048 | 6.25 | 16.16 | 2.59 |
| ROCm0 | MUL_MAT_ID | type_a=q4_0,type_b=f32,n_mats=128,n_used=8,b=0,m=768,n=32,k=2048 | 2.15 | 3.79 | 1.76 |
| ROCm0 | MUL_MAT_ID | type_a=q4_0,type_b=f32,n_mats=128,n_used=8,b=0,m=768,n=4,k=2048 | 4.87 | 5.07 | 1.04 |
| ROCm0 | MUL_MAT_ID | type_a=q4_0,type_b=f32,n_mats=128,n_used=8,b=0,m=768,n=512,k=2048 | 12.03 | 17.68 | 1.47 |
| ROCm0 | MUL_MAT_ID | type_a=q4_0,type_b=f32,n_mats=128,n_used=8,b=0,m=768,n=64,k=2048 | 3.09 | 6.46 | 2.09 |
| ROCm0 | MUL_MAT_ID | type_a=q4_0,type_b=f32,n_mats=128,n_used=8,b=0,m=768,n=8,k=2048 | 6.12 | 6.23 | 1.02 |
| ROCm0 | MUL_MAT_ID | type_a=q4_0,type_b=f32,n_mats=32,n_used=4,b=0,m=1792,n=1,k=2048 | 1.44 | 1.46 | 1.01 |
| ROCm0 | MUL_MAT_ID | type_a=q4_0,type_b=f32,n_mats=32,n_used=4,b=0,m=1792,n=128,k=2048 | 6.71 | 17.51 | 2.61 |
| ROCm0 | MUL_MAT_ID | type_a=q4_0,type_b=f32,n_mats=32,n_used=4,b=0,m=1792,n=256,k=2048 | 12.84 | 21.70 | 1.69 |
| ROCm0 | MUL_MAT_ID | type_a=q4_0,type_b=f32,n_mats=32,n_used=4,b=0,m=1792,n=32,k=2048 | 3.90 | 6.66 | 1.71 |
| ROCm0 | MUL_MAT_ID | type_a=q4_0,type_b=f32,n_mats=32,n_used=4,b=0,m=1792,n=4,k=2048 | 5.34 | 5.18 | 0.97 |
| ROCm0 | MUL_MAT_ID | type_a=q4_0,type_b=f32,n_mats=32,n_used=4,b=0,m=1792,n=512,k=2048 | 24.57 | 28.93 | 1.18 |
| ROCm0 | MUL_MAT_ID | type_a=q4_0,type_b=f32,n_mats=32,n_used=4,b=0,m=1792,n=64,k=2048 | 6.06 | 12.65 | 2.09 |
| ROCm0 | MUL_MAT_ID | type_a=q4_0,type_b=f32,n_mats=32,n_used=4,b=0,m=1792,n=8,k=2048 | 6.47 | 6.59 | 1.02 |
| ROCm0 | MUL_MAT_ID | type_a=q4_K,type_b=f32,n_mats=128,n_used=8,b=0,m=768,n=1,k=2048 | 0.91 | 0.96 | 1.05 |
| ROCm0 | MUL_MAT_ID | type_a=q4_K,type_b=f32,n_mats=128,n_used=8,b=0,m=768,n=128,k=2048 | 3.30 | 12.38 | 3.76 |
| ROCm0 | MUL_MAT_ID | type_a=q4_K,type_b=f32,n_mats=128,n_used=8,b=0,m=768,n=256,k=2048 | 6.11 | 16.18 | 2.65 |
| ROCm0 | MUL_MAT_ID | type_a=q4_K,type_b=f32,n_mats=128,n_used=8,b=0,m=768,n=32,k=2048 | 2.82 | 4.10 | 1.45 |
| ROCm0 | MUL_MAT_ID | type_a=q4_K,type_b=f32,n_mats=128,n_used=8,b=0,m=768,n=4,k=2048 | 2.64 | 2.72 | 1.03 |
| ROCm0 | MUL_MAT_ID | type_a=q4_K,type_b=f32,n_mats=128,n_used=8,b=0,m=768,n=512,k=2048 | 11.77 | 23.02 | 1.96 |
| ROCm0 | MUL_MAT_ID | type_a=q4_K,type_b=f32,n_mats=128,n_used=8,b=0,m=768,n=64,k=2048 | 3.09 | 6.80 | 2.20 |
| ROCm0 | MUL_MAT_ID | type_a=q4_K,type_b=f32,n_mats=128,n_used=8,b=0,m=768,n=8,k=2048 | 2.02 | 1.85 | 0.92 |
| ROCm0 | MUL_MAT_ID | type_a=q4_K,type_b=f32,n_mats=32,n_used=4,b=0,m=1792,n=1,k=2048 | 1.84 | 1.86 | 1.01 |
| ROCm0 | MUL_MAT_ID | type_a=q4_K,type_b=f32,n_mats=32,n_used=4,b=0,m=1792,n=128,k=2048 | 6.58 | 19.32 | 2.94 |
| ROCm0 | MUL_MAT_ID | type_a=q4_K,type_b=f32,n_mats=32,n_used=4,b=0,m=1792,n=256,k=2048 | 12.44 | 26.08 | 2.10 |
| ROCm0 | MUL_MAT_ID | type_a=q4_K,type_b=f32,n_mats=32,n_used=4,b=0,m=1792,n=32,k=2048 | 5.09 | 7.06 | 1.39 |
| ROCm0 | MUL_MAT_ID | type_a=q4_K,type_b=f32,n_mats=32,n_used=4,b=0,m=1792,n=4,k=2048 | 2.75 | 2.83 | 1.03 |
| ROCm0 | MUL_MAT_ID | type_a=q4_K,type_b=f32,n_mats=32,n_used=4,b=0,m=1792,n=512,k=2048 | 23.96 | 29.67 | 1.24 |
| ROCm0 | MUL_MAT_ID | type_a=q4_K,type_b=f32,n_mats=32,n_used=4,b=0,m=1792,n=64,k=2048 | 6.11 | 13.81 | 2.26 |
| ROCm0 | MUL_MAT_ID | type_a=q4_K,type_b=f32,n_mats=32,n_used=4,b=0,m=1792,n=8,k=2048 | 2.41 | 2.63 | 1.09 |
| ROCm0 | MUL_MAT_ID | type_a=q6_K,type_b=f32,n_mats=128,n_used=8,b=0,m=768,n=1,k=2048 | 1.31 | 1.34 | 1.03 |
| ROCm0 | MUL_MAT_ID | type_a=q6_K,type_b=f32,n_mats=128,n_used=8,b=0,m=768,n=128,k=2048 | 2.02 | 8.37 | 4.14 |
| ROCm0 | MUL_MAT_ID | type_a=q6_K,type_b=f32,n_mats=128,n_used=8,b=0,m=768,n=256,k=2048 | 3.79 | 11.79 | 3.11 |
| ROCm0 | MUL_MAT_ID | type_a=q6_K,type_b=f32,n_mats=128,n_used=8,b=0,m=768,n=32,k=2048 | 1.78 | 2.48 | 1.39 |
| ROCm0 | MUL_MAT_ID | type_a=q6_K,type_b=f32,n_mats=128,n_used=8,b=0,m=768,n=4,k=2048 | 1.94 | 2.03 | 1.04 |
| ROCm0 | MUL_MAT_ID | type_a=q6_K,type_b=f32,n_mats=128,n_used=8,b=0,m=768,n=512,k=2048 | 7.47 | 15.10 | 2.02 |
| ROCm0 | MUL_MAT_ID | type_a=q6_K,type_b=f32,n_mats=128,n_used=8,b=0,m=768,n=64,k=2048 | 1.89 | 4.47 | 2.37 |
| ROCm0 | MUL_MAT_ID | type_a=q6_K,type_b=f32,n_mats=128,n_used=8,b=0,m=768,n=8,k=2048 | 1.18 | 1.34 | 1.13 |
| ROCm0 | MUL_MAT_ID | type_a=q6_K,type_b=f32,n_mats=32,n_used=4,b=0,m=1792,n=1,k=2048 | 1.26 | 1.38 | 1.10 |
| ROCm0 | MUL_MAT_ID | type_a=q6_K,type_b=f32,n_mats=32,n_used=4,b=0,m=1792,n=128,k=2048 | 3.98 | 11.99 | 3.01 |
| ROCm0 | MUL_MAT_ID | type_a=q6_K,type_b=f32,n_mats=32,n_used=4,b=0,m=1792,n=256,k=2048 | 7.42 | 16.34 | 2.20 |
| ROCm0 | MUL_MAT_ID | type_a=q6_K,type_b=f32,n_mats=32,n_used=4,b=0,m=1792,n=32,k=2048 | 3.03 | 4.21 | 1.39 |
| ROCm0 | MUL_MAT_ID | type_a=q6_K,type_b=f32,n_mats=32,n_used=4,b=0,m=1792,n=4,k=2048 | 2.15 | 2.13 | 0.99 |
| ROCm0 | MUL_MAT_ID | type_a=q6_K,type_b=f32,n_mats=32,n_used=4,b=0,m=1792,n=512,k=2048 | 14.78 | 18.03 | 1.22 |
| ROCm0 | MUL_MAT_ID | type_a=q6_K,type_b=f32,n_mats=32,n_used=4,b=0,m=1792,n=64,k=2048 | 3.60 | 8.56 | 2.38 |
| ROCm0 | MUL_MAT_ID | type_a=q6_K,type_b=f32,n_mats=32,n_used=4,b=0,m=1792,n=8,k=2048 | 1.59 | 1.53 | 0.96 |
| ROCm0 | MUL_MAT_ID | type_a=q8_0,type_b=f32,n_mats=128,n_used=8,b=0,m=768,n=1,k=2048 | 1.28 | 1.33 | 1.04 |
| ROCm0 | MUL_MAT_ID | type_a=q8_0,type_b=f32,n_mats=128,n_used=8,b=0,m=768,n=128,k=2048 | 3.43 | 9.96 | 2.90 |
| ROCm0 | MUL_MAT_ID | type_a=q8_0,type_b=f32,n_mats=128,n_used=8,b=0,m=768,n=256,k=2048 | 6.40 | 16.13 | 2.52 |
| ROCm0 | MUL_MAT_ID | type_a=q8_0,type_b=f32,n_mats=128,n_used=8,b=0,m=768,n=32,k=2048 | 1.96 | 3.14 | 1.60 |
| ROCm0 | MUL_MAT_ID | type_a=q8_0,type_b=f32,n_mats=128,n_used=8,b=0,m=768,n=4,k=2048 | 2.82 | 2.87 | 1.02 |
| ROCm0 | MUL_MAT_ID | type_a=q8_0,type_b=f32,n_mats=128,n_used=8,b=0,m=768,n=512,k=2048 | 12.16 | 17.79 | 1.46 |
| ROCm0 | MUL_MAT_ID | type_a=q8_0,type_b=f32,n_mats=128,n_used=8,b=0,m=768,n=64,k=2048 | 3.23 | 5.47 | 1.69 |
| ROCm0 | MUL_MAT_ID | type_a=q8_0,type_b=f32,n_mats=128,n_used=8,b=0,m=768,n=8,k=2048 | 2.72 | 2.58 | 0.95 |
| ROCm0 | MUL_MAT_ID | type_a=q8_0,type_b=f32,n_mats=32,n_used=4,b=0,m=1792,n=1,k=2048 | 1.35 | 1.36 | 1.01 |
| ROCm0 | MUL_MAT_ID | type_a=q8_0,type_b=f32,n_mats=32,n_used=4,b=0,m=1792,n=128,k=2048 | 6.66 | 16.99 | 2.55 |
| ROCm0 | MUL_MAT_ID | type_a=q8_0,type_b=f32,n_mats=32,n_used=4,b=0,m=1792,n=256,k=2048 | 12.76 | 19.17 | 1.50 |
| ROCm0 | MUL_MAT_ID | type_a=q8_0,type_b=f32,n_mats=32,n_used=4,b=0,m=1792,n=32,k=2048 | 3.42 | 5.27 | 1.54 |
| ROCm0 | MUL_MAT_ID | type_a=q8_0,type_b=f32,n_mats=32,n_used=4,b=0,m=1792,n=4,k=2048 | 3.89 | 3.90 | 1.00 |
| ROCm0 | MUL_MAT_ID | type_a=q8_0,type_b=f32,n_mats=32,n_used=4,b=0,m=1792,n=512,k=2048 | 24.59 | 31.39 | 1.28 |
| ROCm0 | MUL_MAT_ID | type_a=q8_0,type_b=f32,n_mats=32,n_used=4,b=0,m=1792,n=64,k=2048 | 6.17 | 10.11 | 1.64 |
| ROCm0 | MUL_MAT_ID | type_a=q8_0,type_b=f32,n_mats=32,n_used=4,b=0,m=1792,n=8,k=2048 | 4.23 | 4.85 | 1.15 |
Overview
This PR improves routed MoE prefill performance on RDNA3 by changing how llama.cpp chooses MMQ N-tile sizes. Instead of using the worst case expert width, it estimates the typical routed expert width and uses that when it is smaller than the RDNA3 maximum tile width. The launch grid still uses the original worst case width, so output coverage and correctness are preserved. The change is limited to host side tile selection in
mul_mat_q_caseand does not modify structs, call sites, launch parameters, or device kernels. Benchmarks on a Radeon Pro W7800/gfx1100 with ROCm 7.2.3 show large prefill gains in many routed MoE cases, while decode and non RDNA3 architectures are mostly unchanged.If maintainers or other contributors have access to NVIDIA, CDNA, RDNA2, or RDNA4 hardware, the natural follow up would be to test the same routed width picker under the corresponding MMQ/launch policy and enable it per architecture where it is beneficial.
Benchmark Summary
Hardware/software:
-ngl 99GGML_CUDA_FA_ALL_QUANTS=ON-fa 1 -ctk q8_0 -ctv f16 -sm none -t 4 --poll 0 -r 5The improvement depends on the physical ubatch/chunk width that reaches routed MoE MMQ, not total context length:
So long prompts can still benefit when they are processed in smaller ubatch chunks.
Benchmark sweep
The 128 expert models show the expected crossover behavior at ubatch 2048:
pp2048and larger are neutral because the typical width has reachedmmq_x_max = 128. The 256-expert Qwen3.6 shape remains below crossover and still improves throughpp8192.Requirements