[MoE] Add Xe2 FP8 W8A16 grouped GEMM support - #341
Conversation
06f12f8 to
f461539
Compare
4caf772 to
442cd7b
Compare
Restore the fused small-route prepare path for Xe2 FP8 W8A16 MoE, guard its static launch assumptions, and reuse cached workspace views. Keep int64 route IDs on the direct path and add focused prepare, workspace, and FP8 cleanup coverage.
There was a problem hiding this comment.
Pull request overview
This PR adds Xe2/BMG support for MoE checkpoints with FP8 (E4M3) expert weights by introducing a BF16-activation / FP8-weight grouped GEMM (W8A16) backend, wiring it through the Torch extension + Python fused_experts API, and providing both AOT and SYCL JIT launch paths. It also adds a small-routed fast-path input preparation kernel and extensive correctness/contract tests and benchmarks around the new FP8 flow.
Changes:
- Add Xe2 FP8(E4M3) weight-only grouped GEMM kernel (scalar + 128×128 block scales, optional bias) with AOT + JIT dispatch.
- Integrate FP8 weight-only execution into
python/sgl_kernel/moe.py::fused_experts, including activation variants and small-routed input preparation. - Add new tests and benchmarks covering API validation, kernel correctness, workspace caching, and performance.
Reviewed changes
Copilot reviewed 19 out of 19 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/test_moe_prepare_input.py | Adds unit tests for small-route prepare selector and new prepare_moe_input_small op correctness/error handling. |
| tests/test_moe_gemm.py | Adds FP8 E4M3 W8A16 reference quant/dequant helpers and end-to-end FP8 MoE + grouped GEMM tests (scalar + block scales, activations, bias). |
| tests/test_moe_fused_experts_workspace.py | Updates workspace cache tests to cover the new view-cache behavior. |
| src/torch_extension_sycl.cc | Registers new ops: moe_grouped_mm_nt_xe20_fp8_w8a16 and prepare_moe_input_small. |
| src/sycl/MoEPrepareInputs.cpp | Implements prepare_moe_input_small SYCL kernel and its validation/device capability checks. |
| src/sycl/kernels/moe/xe20/fp8/moe_mainloop.hpp | Introduces FP8-weight/BF16-activation mainloop (scalar + block-scale handling) for Xe2. |
| src/sycl/kernels/moe/xe20/fp8/moe_kernel.hpp | Implements grouped GEMM kernel wrapper for FP8 weights, including scheduler modes and scale layout handling. |
| src/sycl/GroupGemmFp8W8A16Xe20LauncherInstance.cpp.in | Adds templated per-tile launcher instance for JIT compilation and entry symbol. |
| src/sycl/GroupGemmFp8W8A16Xe20.cpp | Adds dispatcher + validation for FP8 W8A16 grouped GEMM, including tile selection and static scheduler rules. |
| src/jit/moe_jit.h | Declares JIT launch API for FP8 W8A16 grouped GEMM. |
| src/jit/moe_jit.cpp | Adds FP8 W8A16 tile selection + JIT compilation cache plumbing for runtime kernels. |
| src/GroupGemmFp8W8A16Xe20.cmake | Adds AOT instantiation generation for the FP8 W8A16 grouped GEMM tile/scale/bias matrix. |
| src/CMakeLists.txt | Wires new FP8 grouped GEMM sources into the build (and MOE exclusion filter). |
| src/BuildOnLinux.cmake | Ensures FP8 instance bundles are included/linked correctly for AOT and JIT configurations. |
| python/sgl_kernel/moe.py | Adds FP8 weight-only MoE path, FP8 scale validation, small-route prepare selection, and workspace view caching. |
| include/sgl_kernel_ops.h | Exposes C++ API for moe_grouped_mm_nt_xe20_fp8_w8a16 and prepare_moe_input_small. |
| benchmark/bench_moe_fp8_w8a16_grouped_gemm.py | Adds op-level benchmark comparing SGL scalar/block FP8 paths (and optional vLLM reference). |
| benchmark/bench_fused_moe_fp8.py | Adds small opt-in end-to-end FP8 MoE benchmark with preloading of FP8 AOT instances. |
| .isort.cfg | Adds sgl_kernel classification to isort config. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
There was a problem hiding this comment.
can you reuse W4A16 files since they are the same?
There was a problem hiding this comment.
Thank you for your comments. I will try to reuse the w4a16 implementation.
| run_w8a16_scalar(A, Bp, w_scale_gmem, w_scale_row_stride, D, blk_coord, mma, thr_id, Bias, gemm_n, m_actual); | ||
| } else { | ||
| constexpr int BLK_M = get<0>(decltype(mma.tile_mnk()){}); | ||
| if (m_actual % BLK_M == 0) { |
There was a problem hiding this comment.
Shall we request the FWK side to do the padding? You can compare the performance w/ and w/o padding
@jmunetong for awareness
There was a problem hiding this comment.
Thanks for your comments. Use real m size instead. No significant performance changes were observed w/ and w/o padding (~2% grouped gemm time).
| reorder(tBrB_packed, tSrB); | ||
| CUTLASS_PRAGMA_UNROLL | ||
| for (int i = 0; i < tSrB.size(); ++i) { | ||
| tSrB(i) = apply_bf16_weight_scale(tSrB(i), w_scale); |
There was a problem hiding this comment.
Can you try to reuse W4A16 code with several constexpr dispatch?
Summary
Add FP8 E4M3 MoE support for Xe2/BMG with BF16 activations and outputs.
The existing
use_fp8_w8a8=TrueAPI remains compatible, but dispatches to W8A16 because Xe2 has no native FP8 x FP8 MMA and the evaluated W8A8 path was slower.Changes
Add Xe2 FP8 W8A16 grouped GEMM with:
Use a static grid-stride scheduler for grouped GEMMs with small routed
work or short-K scalar scales:
total_m <= num_experts, orK <= 128.This avoids dynamic tile-stealing atomics and improves short-GEMM latency
by about 2.2%-3.6%.
Add a specialized small-batch input-preparation path for FP8 MoE.
For workloads with a small number of routed rows, one workgroup performs the expert histogram, prefix computation, stable route ranking, and activation scatter, avoiding the generic multi-kernel preparation path.
Performance
Measured on Intel Arc Pro B60 with PyTorch 2.12.0+xpu using XPU events.
Small-batch input preparation
(M, TopK, E, H)(1, 8, 256, 2048)(2, 8, 128, 2048)(4, 8, 128, 2048)(5, 8, 128, 2048)(8, 8, 128, 128)End-to-end MoE
Scalar FP8 weight scales
(H, I, E, TopK)(7168, 512, 256, 8)(7168, 512, 256, 8)(7168, 512, 256, 8)(2048, 256, 512, 10)(2048, 256, 512, 10)(2048, 256, 512, 10)128x128 block FP8 weight scales
(H, I, E, TopK)(7168, 512, 256, 8)(7168, 512, 256, 8)(7168, 512, 256, 8)(2048, 256, 512, 10)(2048, 256, 512, 10)(2048, 256, 512, 10)