Conversation
c920888 to
611d8aa
Compare
|
Retargeting: these fusions now stack into #34859 directly via yhyang201#5 (base = |
…3.5 family) Three always-on fusions, all bit-equivalent up to FP4/FP8 rounding ties: 1. Fuse the post-attention GemmaRMSNorm with the gate_up NVFP4 input quant via FlashInfer add_rmsnorm_fp4quant (Gemma (1+w) folded into the weight; swizzled block-scale exposed as the 2D view the cuDNN backend validates). 2. Fuse the GDN gated RMSNorm with the out_proj static-FP8 input quant: an fp8-store epilogue in the fla layernorm_gated Triton kernel (skips the bf16 intermediate round-trip) plus prequantized-(fp8, scale) acceptance in ModelOptFp8LinearMethod. 3. Extend the SiLU+mul+FP4-quant fusion (previous commit) to the attention-layer dense MLPs, covering all 64 layers. RTX PRO 6000 (SM120), Qwen3.8-27B NVFP4+FP8 mixed ckpt, 8192-in/1024-out, bs=1, chunked-prefill 8192, KV fp8_e4m3 (5 requests, seed 1234): TTFT mean 674.8 -> 640.1 ms (-5.1%) TTFT median 665.3 -> 631.3 ms (-5.1%) decode 68.7 -> 69.1 output tok/s, ITL 13.92 -> 13.86 ms (no change) GSM8K (sglang.test.run_eval) matches the unfused baseline; per-fusion kill switches: SGLANG_DISABLE_SILU_FP4_QUANT_FUSION, SGLANG_DISABLE_POST_LN_FP4_QUANT_FUSION, SGLANG_DISABLE_GATED_NORM_FP8_QUANT_FUSION. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
611d8aa to
1b0aebc
Compare
|
Verified this PR on a DGX Spark (GB10) — summary: correctness checks out, perf is neutral on this chip (no gain, no regression). Environment
Server flags and bench client command were copied verbatim from the PR description (8K input / 1K output, 5 prompts, Correctness ✅
Performance
|
| Lane | Round | GPU temp | Mean TTFT (ms) | Median TTFT (ms) | TPOT (ms) |
|---|---|---|---|---|---|
| head | 4 | 51°C | 4241.7 | 4206.5 | 80.0 |
| base | 4 | 59°C | 4153.9 | 4119.6 | 80.2 |
| head | 5 | 60°C | 4143.3 | 4114.8 | 80.6 |
| base | 5 | 60°C | 4144.8 | 4114.3 | 80.4 |
Same-temperature adjacent pair (head r5 vs base r5, both at 60°C) is a dead heat, and decode TPOT is identical within noise across all interleaved rounds. On GB10 the fusions land within ±1% run-to-run noise — the RTX PRO 6000's ~2.3% TTFT gain does not reproduce here. Plausibly expected: with GB10's low memory bandwidth, prefill is dominated by GEMM/attention rather than the norm/act/quant HBM round-trips this PR removes.
No tracebacks, CUDA errors, or OOMs in any of the 12 server runs (6 bench lanes × server + 2 correctness + warmups). No objections from the GB10 side — functionally correct, perf-neutral here.
Motivation
For Qwen3.5-family hybrid (GDN + attention) models served with a mixed ModelOpt NVFP4(W4A4)+FP8 checkpoint, prefill spends a measurable share of GPU time in standalone norm / activation / quantization glue kernels: every projection input is normalized, written to HBM in bf16, then re-read and quantized by a separate kernel. Kernel-level tracing against vLLM 0.27.1 on the same model showed the GEMM/attention/GDN families at parity while SGLang lost time in this glue (vLLM fuses norm+quant and act+quant via torch.compile).
This PR removes the extra round-trips with three targeted fusions (all bit-equivalent up to FP4/FP8 rounding ties, each with a kill switch):
act_and_mul+ the standalone per-block FP4 quantize with FlashInfer'ssilu_and_mul_scaled_nvfp4_experts_quantize(single-group form), handingdown_proja prequantized(fp4, swizzled_scale)tuple through the existing_accepts_prequantized_fp4path. Enabled for both GDN-layer and attention-layer MLPs.add_rmsnorm_fp4quantfuses the residual-add, the norm, and thegate_upinput quant into one kernel. Gemma's(1 + w)scaling is folded into a precomputed weight; the swizzled block-scale is exposed as the 2D(m_padded, K/16)view so the cuDNN mm_fp4 backend's shape validation also passes.flalayernorm_gatedTriton kernel (skips the bf16 intermediate write entirely) and teachesModelOptFp8LinearMethodto accept a prequantized(fp8, scale)tuple forout_proj(explicit opt-in attribute, mirroring the fp4 path).Kill switches:
SGLANG_DISABLE_SILU_FP4_QUANT_FUSION=1,SGLANG_DISABLE_POST_LN_FP4_QUANT_FUSION=1,SGLANG_DISABLE_GATED_NORM_FP8_QUANT_FUSION=1.The fusions auto-enable only when the touched projections use the matching ModelOpt linear method (NVFP4 W4A4 for 1-2, per-tensor static FP8 for 3), so other checkpoints and quant modes keep their current control flow.
Benchmark
Re-benchmarked on 2026-08-20 against the current PR base and head. Both lanes ran back-to-back on the same otherwise-idle physical GPU with the same container, model snapshot, server flags, prompt seed, and client command.
Environment and revisions
lmsysorg/sglang:qwen382.13.0+cu130/ CUDA 13.0RadixArk/Qwen3.8-27B-NVFP4554ebba9b5f1b79dc11246341960360e6ef05ef4a4ffb996db3e823708a53637f851e2677d4455a8a3facf77a9bf07464d87299d21dede0837df8e9da4ffb996db3e823708a53637f851e2677d4455a8Because the merge base equals the tested main revision, this comparison isolates the PR's net diff.
Commands
The commands below were run inside the existing
sglang_bbufcontainer. For the main lane,SGLANG_TREE=/work/pr34934-rebench-main; for the PR lane,SGLANG_TREE=/work/pr34934-rebench-head.Server:
SGLANG_TREE=/work/pr34934-rebench-head CUDA_VISIBLE_DEVICES=2 \ PYTHONPATH="${SGLANG_TREE}/python" \ python -m sglang.launch_server \ --model-path RadixArk/Qwen3.8-27B-NVFP4 \ --host 0.0.0.0 \ --port 31002 \ --tp-size 1 \ --chunked-prefill-size 8192 \ --max-prefill-tokens 8192 \ --kv-cache-dtype fp8_e4m3 \ --mamba-ssm-dtype bfloat16 \ --disable-radix-cacheBenchmark client:
For each revision, one complete five-request run was discarded as a pre-run, then the recorded command was run three times (five requests per round, 15 measured requests per revision). Every invocation also ran the client's one built-in warmup request. GPU 2 had 0 MiB allocated before the first server was started and after the final server was stopped.
Per-round results
Aggregate result
TTFT aggregates all 15 per-request observations. Output throughput is total generated tokens divided by total benchmark duration across the three recorded rounds.
For the paired TTFT observations, the mean gain was 15.06 ms and the approximate 95% confidence interval was 10.79-19.32 ms. The current result supports a stable ~2.3% prefill TTFT improvement; decode throughput and ITL are unchanged within run-to-run noise.
Startup logs confirmed that the optimized paths were active for the expected layers:
Both server logs were checked for traceback, CUDA error, OOM, and exception signatures; none were found.
Correctness validation
Correctness was not rerun as part of the 2026-08-20 performance pass. The earlier full GSM8K validation (1319 examples) reported:
The fused kernels were also previously checked for identical residual propagation relative to
fused_add_rmsnorm.Data provenance
The performance tables above come from the current PR head and its exact merge base, using three saved
bench_serving --output-detailsJSONL results per lane. They replace the older 5-request/FlashInfer-0.6.17 table, which was measured against an earlier base and was not reproducible as a current-main/current-PR comparison. The previous H200 FP8-dynamic table was removed because these W4A4-specific fusions are inactive for that checkpoint and therefore it did not measure this PR's performance effect.Checklist
🤖 Generated with Claude Code
CI States
Latest PR Test (Base): ❌ Run #32368351888
Latest PR Test (Extra): ❌ Run #32368351907
Latest PR Test (AMD ROCm 7.2): ❌ Run #32368351823