CUDA: let any expert count use the fast mm_ids_helper path - #27978
Conversation
The optimized path grouped warp lanes by token and required warp_size % n_expert_used == 0, with a single hardcoded exception padding 6 up to 8. Every other count fell back to the generic path, which walks the tokens one at a time with a warp reduction per token, for each of the n_expert blocks. The lane group only has to divide the warp, and the loop body already guards the padded lanes with iex < n_expert_used, so the padding generalizes to the next power of two. The 6 -> 8 case and every count already dispatched keep the exact same padding as before. n_expert_used = 10 now reaches the fast path. Measured on Qwen3.8-Flash-Next (512 experts, 10 used) at 55k context on an RTX PRO 6000, warm runs with the first one discarded: prompt processing 2334 -> 2600 t/s Token generation is unaffected, since a single token leaves nothing to walk. Other expert counts reach the fast path by adding their case to the dispatch.
This comment was marked as low quality.
This comment was marked as low quality.
The perf claim needs a model whose expert count was not dispatched, so Qwen3.8-Flash-Next with 512 experts and 10 used. On anything using 2, 4, 6, 8, 16 or 32 there is nothing to measure, those already took the fast path. I re-ran it on current master, reverting only f1793c1 for the control, two separate builds, alternated in both orders with the first pair discarded: without 2161.5 2138.3 2137.8 2130.8 2139 -> 2351 t/s, +9.9% prefill at 55k context. A bit below the 2334 -> 2600 in the description, which came from a branch carrying other changes. (#28023 not merged for now) |
Overview
CUDA: unlock the fast mm_ids_helper path for any expert count, enable it for 10 (Qwen3.8-Flash-Next)
Additional information
mm_ids_helper groups tokens by expert before the MoE matmuls. It has a fast path that spreads warp lanes across tokens, and a slow generic one that walks a single token per iteration with a warp reduction each time.
The fast path only accepted expert counts dividing 32, plus a hardcoded case for 6, so anything else quietly fell back to the slow path. Qwen3.8-Flash-Next uses 10, and nsys put this kernel at 13.3% of prefill time, ahead of flash attention.
The real constraint isn't the expert count itself but the number of lanes per token, and the loop already guarded the extra lanes. So the padding just rounds up to the next power of two. Every count already dispatched gets the same padding as before and is unchanged. I added 10; any other count is one line away.
RTX PRO 6000 at 55k context, first run discarded: prefill
2334 to 2600 t/s2139 -> 2351 t/s, +9.9% (current master 62acc89). Generation doesn't move, with a single token there's nothing to walk. Only tested on CUDA with 32 wide warps.Requirements