[XPU][MoE] Tune Triton fused MoE for Intel XPU - #53065
Draft
pmanczak wants to merge 1 commit into
Draft
Conversation
Make benchmarks/kernels/benchmark_moe.py runnable on XPU, add an XPU search space plus tile pruning, and ship tuned fused MoE configs for Intel Arc Pro B70. The XPU path had no tuned configs, so it always fell back to get_default_config() and logged the sub-optimal-config warning. Tuning recovers 1.16-3.16x of fused MoE kernel time (geometric mean 1.86x on E=64/N=1024 and 1.91x on E=64/N=512, OLMoE-1B-7B, bf16). The heuristic escalates BLOCK_SIZE_M with batch size, which is wrong for a 64-expert layer at topk=8 where the rows an expert receives stay small, and that makes its cost curve non-monotonic; the tuned curve is not. Three supporting changes. The benchmark hardcoded CUDA for graph capture, default device and cache clearing, now routed through torch.accelerator and current_platform. Ray keys its parallelism on the "GPU" resource, which XPU does not register, so ray.remote is applied dynamically instead of at class definition and --no-ray runs shapes serially in one process. sort_config() learns to keep grf_mode, without which the tuner would select a GRF mode and then drop it when writing the JSON. The search space is adapted from intel-xpu-backend-for-triton, which autotunes these kernels per launch rather than from a config file. BLOCK_SIZE_N=32 and num_warps=32 are left out: across four shapes, including a Mixtral-sized one, they never won and never came within 17% of the best. Signed-off-by: pmanczak <pawel.manczak@intel.com>
pmanczak
force-pushed
the
pmanczak/moe-autotune-xpu
branch
5 times, most recently
from
August 20, 2026 12:00
181ba82 to
a883afd
Compare
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.
Purpose
The Triton fused MoE kernel runs on Intel XPU but has no tuned configs there, so
it always falls back to
get_default_config()and logs "Using default MoEconfig. Performance might be sub-optimal!". This PR makes
benchmarks/kernels/benchmark_moe.pyusable on XPU and ships tuned configs forIntel Arc Pro B70.
Changes
torch.accelerator/current_platforminstead of hardcodedtorch.cuda.--no-ray. Ray keys its parallelism on the"GPU"resource, which XPUdoes not register, so
ray.remoteis now applied dynamically rather than atclass definition and the same worker class serves both paths.
num_warpsup to 32,num_stagesfrom 3, smallerBLOCK_SIZE_K,grf_mode) andprune_xpu_search_space(), which drops tileswider than the routed row count since those are pure padding and the slowest
to compile. Adapted from
intel-xpu-backend-for-triton.grf_modeinsort_config(). No plumbing is needed for it, as**configalready forwards extra keys into the launch, the same way ROCm passes
waves_per_eu.E=64, N=1024andE=64, N=512.Results
Kernel time from
benchmark_moe.py, Intel Arc Pro B70, bf16,allenai/OLMoE-1B-7B-0924. Baseline is the built-in heuristic config, tuned isthe shipped JSON.
E=64, N=1024(tp=1):E=64, N=512(tp=2):Geometric mean 1.86x and 1.91x respectively.
Two things drive the larger wins. The heuristic escalates
BLOCK_SIZE_Mwithbatch size, which is wrong for a 64-expert layer at
topk=8where the rows anexpert receives stay small; that makes its cost curve non-monotonic (batch 128
costs more than batch 256, for half the tokens) while the tuned curve is
monotonic. And half the winners sit outside the default space:
num_warps=16wins at 9 of 18 batch sizes, where the default space only explores 4 and 8.
Every shipped config was checked against an fp32 reference; relative L2 error is
4.1e-3, which is the bf16 output quantization step rather than kernel error.
End to end,
allenai/OLMoE-1B-7B-0924on one B70 with--moe-backend triton,the shipped configs supplied through
VLLM_TUNED_CONFIG_FOLDERand the baselinebeing the same run without them:
generate, 32 prompts x 64 tokenslm_eval arc_challenge, 4687 requestsAccuracy is unchanged:
arc_challengescores acc 0.4727 and acc_norm 0.4829 onboth. Greedy continuations are not bit-identical, since a different reduction
order moves logits by less than a bf16 step and flips near-ties, but the
identical loglikelihood scores show behaviour is unaffected.
The space leaves out
BLOCK_SIZE_N=32andnum_warps=32. Neither won at any ofthe 31 tuned batch sizes across
E=64, N=1024,E=64, N=512andE=40, N=512(Granite 3.1 3b-a800m), and on a Mixtral-shaped kernel (
E=8, N=14336, K=4096, topk=2) they stay far off the best even though that is the corner where widetiles get the most rows per expert:
BLOCK_SIZE_N=32num_warps=32BLOCK_SIZE_M=256(kept)BLOCK_SIZE_M=256is kept because its margin keeps shrinking with batch size onthat shape, and
prune_xpu_search_space()already drops it whenever the routedrow count is small. The space is 360 candidates rather than 720, which roughly
halves tuning time.
Test plan
benchmark_moe.py --model allenai/OLMoE-1B-7B-0924 --tp-size 1 --no-ray --tunecompletes on XPU and writes a config JSON
--moe-backend tritonpicks the shipped configup (the "default MoE config" warning is gone) and generates 1.65x faster at
identical
arc_challengeaccuracyray.remote(num_gpus=1), and pruning is only reached undercurrent_platform.is_xpu()