Skip to content

[Gemma4] Optimize Gemm4 with fused Q/K/V RMSNorm + per-expert FP8 ckpt loader - #24696

Merged
kpham-sgl merged 2 commits into
sgl-project:mainfrom
yuan-luo:fp8_gemma4_moe
May 10, 2026
Merged

kpham-sgl merged 2 commits into
sgl-project:mainfrom
yuan-luo:fp8_gemma4_moe

Conversation

@yuan-luo

@yuan-luo yuan-luo commented May 8, 2026 •

Copy link
Copy Markdown
Collaborator

Motivation

The original motivation is to speedup Gemm4 model. Two unrelated issues on the Gemma4 FP8-MoE path:

  1. Attention RMSNorm is launch-bound. Each Gemma4 attention layer issues three separate sgl-kernel rmsnorm launches (q/k/v). At small token counts the per-launch host overhead dominates — three back-to-back launches cost ~60μs regardless of M, even though the actual compute is trivial.

  2. compressed-tensors per-expert FP8 checkpoints fail silently. Models like RedHatAI/gemma-4-26B-A4B-it-FP8-Dynamic store one weight per expert (experts.<id>.{gate,up,down}_proj.{weight,weight_scale}). The existing loader only recognizes the stacked experts.gate_up_proj / experts.down_proj layout, so every routed expert is silently skipped → zero-init expert weights → server launches fine but generation collapses to all-<pad> and GSM8K = 0.0.

Design

1. Fused Q/K/V RMSNorm (gemma_qkv_rmsnorm)

  • One Triton kernel computes x · rsqrt(mean(x²) + eps) · w for all q/k/v heads in a single launch, in-place into the qkv buffer.
  • Grid (M,), BLOCK = next_pow2(head_dim), with tl.static_range over heads.
  • Operates on qkv.split(...) strided views via stride_*_m — no .contiguous() copy.
  • V path skips the weight multiply (V uses with_scale=False → weight is identically 1).
  • Conservative fallback in Gemma4Attention.forward: only takes the fused path when CUDA + q_norm.scale_shift == 0 == k_norm.scale_shift + not v_norm.with_scale. Non-standard configs and KV-shared layers retain the original three-norm
    path.

2. Per-expert FP8 loader

  • New regex branch in Gemma4ForConditionalGeneration.load_weights for ^.*\.moe\.experts\.<id>\.(gate|up|down)_proj\.(weight|weight_scale)$.
  • Maps each per-expert key to the fused FusedMoE param + shard id + expert id, then dispatches via param.weight_loader (standard FusedMoE signature).
  • If the regex matches but the fused param is absent (e.g. ckpt-format drift), emit logger.warning instead of silently skipping — this prevents reproducing the very failure mode the patch fixes.

3. Test

  • test/registered/models/test_gemma4_fp8_per_expert_loading.py (CI: stage-c-test-4-gpu-h100, est 120s) launches the FP8 model with TP=4 and asserts: server health, non-<pad> chat output, and GSM8K-20 ≥ 0.80 (BF16 baseline ~0.95). All three checks fail pre-fix.

Accuracy

MMLU 500 examples
BF16 (500 examples, TP=4):0.878

RedHatAI/gemma-4-26B-A4B-it-FP8-Dynamic

Category Score
Overall 0.885
STEM 0.952
Social sciences 0.918
Other 0.872
Humanities 0.823

Benchmark

H100 ×4, TP=4, RedHatAI/gemma-4-26B-A4B-it-FP8-Dynamic, batch=1, in=2048, out=64.

Microbench (single H100, bf16, Q=8h, KV=2h, head_dim=128):

M unfused (μs) fused (μs) speedup
1 44.4 19.8 2.25x
8 59.4 20.3 2.93x
64 59.4 20.4 2.91x
256 59.7 20.1 2.96x
1024 60.1 20.2 2.97x
4096 58.4 18.6 3.14x
8192 59.3 32.3 1.83x
16384 108.0 75.0 1.44x

Bit-exact vs unfused at M=1/8/128 (max abs diff = 0).

End-to-end (4-GPU, RedHatAI FP8):

Metric Unfused (baseline) Fused (this PR) Δ
Prefill 2048 tok 47.0 ms 46.0 ms -2.1%
Decode median 5.47 ms/tok 5.45 ms/tok -0.4%
Total 0.393 s 0.390 s -0.8%

Decode benefit is muted because the SGLang decode path runs inside CUDA Graph, which amortizes the launch overhead the fused kernel saves. Prefill (no graph) realizes the full 2% win. Net change is neutral-to-positive across regimes; never negative within the tested M range.

The per-expert FP8 loader is a correctness fix: pre-fix GSM8K-20 = 0.00, post-fix ≈ 0.95 — gated at ≥ 0.80 in the new test.

Test plan

  • Microbench: fused vs unfused bit-exact, 1.4–3.1x faster across M ∈ [1, 16384]
  • E2E prefill/decode latency comparison (above)
  • New CI test test_gemma4_fp8_per_expert_loading.py exercises the loader fix end-to-end on 4 GPUs
  • Existing Gemma4 tests still pass (need full CI run)

@yuan-luo

yuan-luo commented May 8, 2026

Copy link
Copy Markdown
Collaborator Author

/tag-and-rerun-ci

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a fused Triton kernel for QKV RMSNorm in Gemma4 models, improving efficiency by replacing three separate normalization passes with a single kernel. It also updates the weight loading logic in the multimodal Gemma4 implementation to support per-expert FP8 checkpoint formats, ensuring correct mapping of expert projections to fused parameters. I have no feedback to provide.

@github-actions github-actions Bot added the run-ci CI: run the baseline test suite on this PR label May 8, 2026
@kpham-sgl
kpham-sgl requested a review from pyc96 May 8, 2026 22:28

@pyc96 pyc96 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Could you also verify quality scores? e.g. MMLU

Comment thread python/sglang/srt/models/gemma4_mm.py Outdated
# routed-expert weight, leading to all-`<pad>` generation.
# Warn loudly so a future ckpt-format drift surfaces here
# instead of silently producing garbage outputs again.
logger.warning(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. Removed the inline logger.warning; misses now fall through to the existing centralized unloaded_params check, same as the other loader paths.

@yuan-luo

yuan-luo commented May 9, 2026

Copy link
Copy Markdown
Collaborator Author

LGTM

Could you also verify quality scores? e.g. MMLU

@pyc96 Updated mmlu scores.

@kpham-sgl
kpham-sgl merged commit d3fd91e into sgl-project:main May 10, 2026
120 of 135 checks passed
ltcs11 added a commit to ltcs11/sglang that referenced this pull request May 11, 2026
* main: (87 commits)
  [Fix] Disable FlashInfer allreduce fusion under deterministic inference (sgl-project#24629)
  fix: STANDALONE spec-decode hidden-size mismatch crash (sgl-project#24217)
  Followup fix for Custom AR V2 in non NVL scenarios (sgl-project#24742)
  Fix reduce_scatterv producer contract for SUM_LEN (sgl-project#24785)
  [NPU]Documentation update for communications quantization feature (sgl-project#24668)
  [Session R3] Add routed_experts_start_len for absolute routing slice control (sgl-project#24851)
  [Model] Add MiniCPM-V 4.6 support (sgl-project#24855)
  Support Intern-S2-Preview (sgl-project#24875)
  [PD] Unify dsv4 dispatch with swa (sgl-project#24888)
  Optimize MHC pipeline: DeepGemm, fused norm, fused hc_head (sgl-project#24775)
  Fix PD bootstrap failure handling (sgl-project#24772)
  [Spec] Cleanup idle stub and shape-check patterns (sgl-project#24881)
  [Bug] Add dsv4 state_type branch to mooncake disaggregation (sgl-project#24878)
  [Spec V1] Split draft-extend phase from `EagleDraftInput` into new `EagleDraftExtendInput` (sgl-project#24859)
  [Gemma4] Optimize Gemm4 with fused Q/K/V RMSNorm + per-expert FP8 ckpt loader (sgl-project#24696)
  [spec decoding] support kimi-k2.5-eagle3-mla (sgl-project#24826)
  [SPEC V2] fix: skip stale state updates in spec-v2 overlap (sgl-project#23456)
  [RL] Call torch.cuda.empty_cache() for `in-place` pause mode to avoid OOM (sgl-project#24854)
  [diffusion] CI: add cache-dit CI tests (sgl-project#19213)
  [Utils] Make request dump robust to unpicklable server_args and large meta_info (sgl-project#24767)
  ...

# Conflicts:
#	python/sglang/srt/utils/common.py
Chronostasys pushed a commit to MindLab-Research/sglang that referenced this pull request Aug 24, 2026
…t loader (sgl-project#24696)

Co-authored-by: luoyuan.luo <luoyuan.luo@antgroup.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

run-ci CI: run the baseline test suite on this PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants