Skip to content

[SM90] Use native block32 DeepGEMM for DeepSeek-V4.1 - #42604

Merged
BBuf merged 7 commits into
sgl-project:mainfrom
vladnosiv:native-block32-sm90
Oct 10, 2026
Merged

BBuf merged 7 commits into
sgl-project:mainfrom
vladnosiv:native-block32-sm90

Conversation

@vladnosiv

@vladnosiv vladnosiv commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

Motivation

DeepSeek-V4.1-Flash stores its dense FP8 weights in [32,32] blocks, compared with [128,128] in DeepSeek-V4-Flash.
These GEMMs cover attention, the shared expert, indexer, Engram, and DSPARK linears.
On Hopper, the SGLang dispatcher routes K-block != 128 to Triton, while the DeepGEMM wrapper only accepts [128,128]. Larger prefill GEMMs can use the existing BF16 weight-cache fast path.
sgl-project/DeepGEMM#95 added native SM90 block32 support. This PR integrates that path into SGLang using sgl-deep-gemm==0.2.2

Modifications

Routes supported SM90 block32 linears through the existing DeepGEMM wrapper with:
fp8_gemm_nt((Aq, As), (Wq, Ws), D, recipe=(1, 32, 32))
The integration preserves checkpoint FP8 weights and UE8M0 activation rounding, passes the block dimensions through the GEMM wrapper, and prepares block32 scale buffers during kernel warmup.
Both prefill and decode use native DeepGEMM. The unused BF16 weight expansion is skipped when DeepGEMM is selected. Explicit Triton selection and unsupported shapes retain their fallback.

Server configuration for the tests listed below

SGLANG_ENABLE_DSV41_ENGRAM_HOST_TABLE=1 \
sglang serve \
  --model-path deepseek-ai/DeepSeek-V4.1-Flash \
  --trust-remote-code \
  --random-seed 42 \
  --tp 4 \
  --mem-fraction-static 0.8 \
  --attention-backend dsv4 \
  --moe-runner-backend flashinfer_mxfp4 \
  --ep-size 4 \
  --enable-decoder-swa-bounded-replay \
  --cuda-graph-max-bs-decode 64 \
  --reasoning-parser auto \
  --tool-call-parser auto \
  --speculative-algorithm DSPARK \
  --speculative-dspark-block-size 5 \
  --host 0.0.0.0 \
  --port 30000

Accuracy Tests

GSM8K, correct answers

Before After
1279/1319 1285/1319

Speed Tests and Profiling

Fixed workload 16k inp / 1k out, simulated acceptance length 5.5

Metric Before After Delta
Total time 4.618 s 3.408 s -26.2%
TTFT 1.017 s 1.002 s -1.4%
Decode throughput 285.87 tokens/s 426.87 tokens/s +49.3%

Trace analysis

Before After
W8A8 Share 41.47% 12.86%

Checklist

Review and Merge Process

  1. Ping Merge Oncalls to start the process. See the PR Merge Process.
  2. Get approvals from CODEOWNERS and other reviewers.
  3. Trigger CI tests with comments or contact authorized users to do so.
    • Common commands include /tag-and-rerun-ci, /tag-run-ci-label, /rerun-failed-ci
  4. After green CI and required approvals, ask Merge Oncalls or people with Write permission to merge the PR.

CI States

Latest PR Test (Base): ❌ Run #38011736527
Latest PR Test (Extra): ❌ Run #38011736377
Latest PR Test (AMD ROCm 10): ❌ Run #38011736554

and deep_gemm_wrapper.ENABLE_JIT_DEEPGEMM
and (backend.is_auto() or backend.is_deep_gemm())
):
return partial(

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.

DeepGEMM #95 reports 0.951× speedup for M=1–4, but this switches those shapes to DeepGEMM in auto mode too. Could you add single-request decode results without speculation, plus DSPARK results with real acceptance? That would help decide whether small M should stay on Triton.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Workload Before, tokens/s After, tokens/s Delta
16k input / 1024 output, bs=1, no speculation 126.62 125.66 −0.76%
16k input / 1024 output, bs=1, DSPARK simulated 5.5 acc len 291.71 420.31 +44.09%
Single GSM8K prompt, bs=1, DSPARK ~3.8 acc len 201.51 281.14 +39.52%

assert not deep_gemm_wrapper.DEEPGEMM_SCALE_UE8M0
assert input.dtype == torch.float8_e4m3fn
assert weight.shape[0] % 64 == 0 and weight.shape[1] % 128 == 0, (
assert shape_supported and block_supported, (

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.

On the pre-quantized-activation path, an unsupported block32 shape now raises an AssertionError instead of falling back to Triton. This may convert a previously working request into a crash.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

fixed

_is_cuda
and get_platform().is_sm90
and envs.SGLANG_OPT_HOPPER_BLOCK_FP8_BF16.get()
and not use_deepgemm_runner

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.

This disables the Hopper BF16 weight cache for every SM90 block32 layer, which makes the new weight_bf16 parameter dead code and strips the BF16 fast path from exactly the shapes DeepGEMM cannot serve.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

fixed

weight_scale: torch.Tensor,
input_scale: Optional[torch.Tensor] = None,
bias: Optional[torch.Tensor] = None,
act_scale_ue8m0: bool = False,

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.

This parameter is added to deepgemm_w8a8_block_fp8_linear_with_fallback's signature but only the new block32 partial ever supplies it; the [128,128] DeepGEMM dispatch routes still return the bare function, so its Triton fallback silently drops ue8m0 activation rounding.

@vladnosiv vladnosiv Oct 6, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

agree, btw seems like exactly the same behavior actually already exists in the main branch for the current block128

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

fixed

@vladnosiv
vladnosiv requested a review from fzyzcjy as a code owner October 6, 2026 14:44

@yuan-luo yuan-luo 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

@BBuf

BBuf commented Oct 8, 2026

Copy link
Copy Markdown
Collaborator

@vladnosiv Can you add aime dataset's acc too?

@BBuf

BBuf commented Oct 9, 2026

Copy link
Copy Markdown
Collaborator

/rerun-test test/registered/unit/layers/quantization/test_fp8_blockwise_linear_backends.py test/registered/kernels/ops/gemm/test_fp8_blockwise_gemm.py

Targeted validation for b093f33.

@github-actions

github-actions Bot commented Oct 9, 2026

Copy link
Copy Markdown
Contributor

⚠️ Rebase Required Before Re-run

A major update has landed on main. Your PR is diverged relative to required base commit 60878c3fba50.

Re-run was not dispatched. What to do:

  • Rebase your branch onto the latest main and push again
  • Follow issue #21065 for context
  • CI-fix PRs may request the bypass-maintenance label to skip this check

@BBuf

BBuf commented Oct 9, 2026

Copy link
Copy Markdown
Collaborator

/rerun-test test/registered/unit/layers/quantization/test_fp8_blockwise_linear_backends.py test/registered/kernels/ops/gemm/test_fp8_blockwise_gemm.py

Targeted validation for a0fac1e after updating the branch from main.

@github-actions

github-actions Bot commented Oct 9, 2026 •

Copy link
Copy Markdown
Contributor

🚀 4-gpu-b200 (1 test): ✅ View workflow run

cd test/ && python3 registered/unit/layers/quantization/test_fp8_blockwise_linear_backends.py

🚀 1-gpu-5090 (2 tests): ✅ View workflow run

cd test/ && python3 registered/unit/layers/quantization/test_fp8_blockwise_linear_backends.py
cd test/ && python3 registered/kernels/ops/gemm/test_fp8_blockwise_gemm.py

🚀 1-gpu-h100 (1 test): ✅ View workflow run

cd test/ && python3 registered/unit/layers/quantization/test_fp8_blockwise_linear_backends.py

@BBuf BBuf 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. The current-head targeted tests pass on H100, B200 and RTX 5090, including the native SM90 block32 and UE8M0 activation-scale cases.

@BBuf

BBuf commented Oct 10, 2026

Copy link
Copy Markdown
Collaborator

/rerun-test test/registered/unit/layers/deep_gemm_wrapper/test_warmup_memory.py test/registered/unit/layers/quantization/test_fp8_blockwise_linear_backends.py test/registered/kernels/ops/gemm/test_fp8_blockwise_gemm.py

Targeted validation for 1d8096a after merging main and reconciling block32 warmup memory accounting with the scale-workspace fix.

@github-actions

github-actions Bot commented Oct 10, 2026 •

Copy link
Copy Markdown
Contributor

🚀 ubuntu-latest (1 test): ✅ View workflow run

cd test/ && python3 registered/unit/layers/deep_gemm_wrapper/test_warmup_memory.py

🚀 4-gpu-b200 (1 test): ✅ View workflow run

cd test/ && python3 registered/unit/layers/quantization/test_fp8_blockwise_linear_backends.py

🚀 1-gpu-5090 (2 tests): ✅ View workflow run

cd test/ && python3 registered/unit/layers/quantization/test_fp8_blockwise_linear_backends.py
cd test/ && python3 registered/kernels/ops/gemm/test_fp8_blockwise_gemm.py

🚀 1-gpu-h100 (1 test): ✅ View workflow run

cd test/ && python3 registered/unit/layers/quantization/test_fp8_blockwise_linear_backends.py

@BBuf
BBuf merged commit 2ff3e6d into sgl-project:main Oct 10, 2026
113 of 129 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

deepseek dependencies Pull requests that update a dependency file jit-kernel

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants