Skip to content

Fuse the DSA (V3.2, GLM-5.x) indexer Q/K paths into single kernels - #27705

Merged
Fridge003 merged 41 commits into
mainfrom
brayden/remove-hadamard
Jun 27, 2026
Merged

Fridge003 merged 41 commits into
mainfrom
brayden/remove-hadamard

Conversation

@b8zhong

@b8zhong b8zhong commented Jun 9, 2026

Copy link
Copy Markdown
Collaborator

Note: to completely revert the affects of this PR, we can set SGLANG_DISABLE_DSA_INDEXER_FUSION=1

Changes

  1. Fuse the key projection and the head-gate projection into a single matmul
    instead of two.

  2. Fuse the query path — rope, optional Hadamard, fp8 quantization, and
    head-gate scaling — into one kernel instead of four separate ops.

  3. Fuse the key path — normalization, rope, optional Hadamard, fp8 quantization,
    and the index cache write — into one kernel instead of four. The previous
    split path is kept as a fallback for the cases that can't use the fused store
    (non-CUDA / NPU, HIP).

  4. Drop the Hadamard rotation for V3.2. It cancels out of the indexer scores, so
    removing it doesn't change results — it only affected quantization accuracy,
    and V3.2 now quantizes the un-rotated activations directly. It stays available
    for the paths that still want it.

  5. Run the key and query paths concurrently. Previously the cache store sat on
    the critical path after the key work; folding the store into the key kernel
    lets the entire key side overlap the query side.

Note: for the fusion, it seems vLLM has adopt a similar approach: vllm-project/vllm#38928

Checkpoint / weight loading

The fused key+head-gate matmul is bf16, so the loader has to land the key
projection as bf16. How it gets there depends on the checkpoint format (the bf16
result is identical either way):

Checkpoint indexer key projection loader behavior
deepseek-ai/DeepSeek-V3.2 (FP8) block-fp8 + scale dequantize to bf16 at load
zai-org/GLM-5-FP8 block-fp8 + scale dequantize to bf16 at load
nvidia/DeepSeek-V3.2-NVFP4 already bf16 straight copy
nvidia/GLM-5.1-NVFP4 already bf16 straight copy

The NVFP4 checkpoint authors intentionally left the (small) indexer out of
low-bit quantization and pre-dequantized its key projection to bf16, verified it
matches the FP8 checkpoint dequantized exactly. The head-gate projection is bf16
in all of them.

FP4:

Before:
Screenshot 2026-06-09 at 10 56 53 AM

After:
Screenshot 2026-06-09 at 10 58 15 AM
Screenshot 2026-06-09 at 1 17 45 PM

FP8:

Before:
Screenshot 2026-06-12 at 6 53 53 AM

After:
Screenshot 2026-06-12 at 6 54 06 AM

Accuracy Tests

GPQA:

nohup env CUDA_VISIBLE_DEVICES=4,5,6,7 python3 -m sglang.launch_server \
  --model-path nvidia/GLM-5.1-NVFP4 \
  --tp 4 \
  --ep 4 \
  --trust-remote-code \
  --reasoning-parser glm45 \
  --tool-call-parser glm47 \
  --port 30001 \
  --max-running-requests 256 > glm_server.log 2>&1 &
sglang serve \
  --model-path zai-org/GLM-5.2-FP8 \
  --tp 8 \
  --ep 8 \
  --trust-remote-code \
  --reasoning-parser glm45 \
  --tool-call-parser glm47 \
  --max-running-requests 256
nohup python3 -m sglang.test.run_eval --port 30020 --eval-name gpqa --num-examples 198 --max-tokens 128000 --repeat 8 --top-p 0.95 --temperature 1.0 --thinking-mode glm-45 > eval.log 2>&1 &

FP4:

Before:

Repeat: 8, mean: 0.854
Scores: ['0.838', '0.848', '0.869', '0.838', '0.854', '0.854', '0.864', '0.869']

After:

Repeat: 8, mean: 0.859
Scores: ['0.843', '0.828', '0.874', '0.864', '0.864', '0.848', '0.884', '0.864']

FP8:

Before:

Repeat: 8, mean: 0.856
Scores: ['0.869', '0.838', '0.889', '0.828', '0.838', '0.864', '0.864', '0.859']

After:

Repeat: 8, mean: 0.856
Scores: ['0.859', '0.859', '0.843', '0.843', '0.848', '0.859', '0.848', '0.889']

Speed Tests and Profiling

BS = 1: 97.72 -> 107.77 TPS with 0 context (about 10%), with above command on B300.

For B300 + GLM FP8 checkpoint and BS = 128, around 3212.05 -> 3418.63 TPS in decode


CI States

Latest PR Test (Base): ✅ Run #28271629599
Latest PR Test (Extra): ✅ Run #28302367849

Brayden Zhong and others added 4 commits June 9, 2026 00:45
Co-authored-by: Kaixi <kaiximatteoc@nvidia.com>
Co-authored-by: Kaixi <kaiximatteoc@nvidia.com>
Co-authored-by: Kaixi <kaiximatteoc@nvidia.com>
Co-authored-by: Kaixi <kaiximatteoc@nvidia.com>
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Warning

You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again!

@b8zhong b8zhong changed the title Fuse the DSA (V3.2) indexer Q/K paths into single kernels Fuse the DSA (V3.2, GLM-5.x) indexer Q/K paths into single kernels Jun 9, 2026
Brayden Zhong and others added 4 commits June 9, 2026 19:36
Co-authored-by: Kaixi <kaiximatteoc@nvidia.com>
Co-authored-by: Kaixi <kaiximatteoc@nvidia.com>
Co-authored-by: Kaixi <kaiximatteoc@nvidia.com>
Co-authored-by: Kaixi <kaiximatteoc@nvidia.com>
Brayden Zhong and others added 3 commits June 9, 2026 23:19
Co-authored-by: Kaixi <kaiximatteoc@nvidia.com>
Co-authored-by: Kaixi <kaiximatteoc@nvidia.com>
Co-authored-by: Kaixi <kaiximatteoc@nvidia.com>
Co-authored-by: Kaixi <kaiximatteoc@nvidia.com>
@b8zhong
b8zhong enabled auto-merge (squash) June 27, 2026 00:09
@Fridge003
Fridge003 disabled auto-merge June 27, 2026 20:34
@Fridge003
Fridge003 merged commit 073de15 into main Jun 27, 2026
271 of 330 checks passed
@Fridge003
Fridge003 deleted the brayden/remove-hadamard branch June 27, 2026 21:29
@Fridge003 Fridge003 added the release-highlight Candidate PR for release note highlight label Jun 27, 2026
Fridge003 pushed a commit that referenced this pull request Jun 27, 2026
…27705)

Co-authored-by: Brayden Zhong <brayden@radixark.ai>
Co-authored-by: Kaixi <kaiximatteoc@nvidia.com>
whybeyoung pushed a commit to whybeyoung/sglang that referenced this pull request Jul 1, 2026
…oject#29613)

Reverts 073de15 (sgl-project#27705 "Fuse the DSA (V3.2, GLM-5.x) indexer Q/K
paths into single kernels") and its follow-up b6fceaa (sgl-project#29613).

The wk/weights_proj fusion (wk_weights_proj) and the fused-indexer weight
loader broke GLM-5.2 block-fp8 checkpoint loading with a weight-shape
mismatch during model load on both prefill and decode instances.
smartssw pushed a commit to smartssw/sglang that referenced this pull request Jul 6, 2026
…gl-project#27705)

Co-authored-by: Brayden Zhong <brayden@radixark.ai>
Co-authored-by: Kaixi <kaiximatteoc@nvidia.com>
vincentzed added a commit to vincentzed/sglang that referenced this pull request Jul 8, 2026
… for DeepSeek-V3.2

The DSA lightning-indexer fused Q/K kernels (PR sgl-project#27705) hardcoded the
interleave/GPT-J RoPE pairing (2i, 2i+1), so is_neox_style=True models
(DeepSeek-V3.2) were parked on the slow split path by sgl-project#30111 after the
wrong rotation corrupted indexer top-k selection (~2.4pt GSM8K drop,
0.955 -> 0.931, sgl-project#30088).

Add a compile-time kIsNeox branch to both kernels that pairs dim i with
i + rope_dim/2 via a lane shuffle (partner pack lives at lane ^ 8) and
loads the cos/sin halves layout with per-element frequency indexing;
the cache layout itself is identical between the two conventions. Plumb
is_neox through the JIT wrappers and drop the `and not is_neox_style`
fusion gate clause.

The interleave path is untouched (GLM-5.x byte-identical); Hadamard
behavior (kHadamard) and the DeepSeek-V4 native indexer are unchanged.

Tests: parametrize the fused-kernel unit tests over is_neox and add a
fused-vs-eager NeoX top-k checksum guard (an interleave-only rotation
collapses overlap to ~topk/3).
Chronostasys pushed a commit to MindLab-Research/sglang that referenced this pull request Aug 24, 2026
…gl-project#27705)

Co-authored-by: Brayden Zhong <brayden@radixark.ai>
Co-authored-by: Kaixi <kaiximatteoc@nvidia.com>
jakki-amd pushed a commit to jakki-amd/sglang that referenced this pull request Sep 9, 2026
…gl-project#27705)

Co-authored-by: Brayden Zhong <brayden@radixark.ai>
Co-authored-by: Kaixi <kaiximatteoc@nvidia.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants