Repository navigation
[SM90] Use native block32 DeepGEMM for DeepSeek-V4.1 - #42604
Conversation
| and deep_gemm_wrapper.ENABLE_JIT_DEEPGEMM | ||
| and (backend.is_auto() or backend.is_deep_gemm()) | ||
| ): | ||
| return partial( |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
| 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, ( |
There was a problem hiding this comment.
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.
| _is_cuda | ||
| and get_platform().is_sm90 | ||
| and envs.SGLANG_OPT_HOPPER_BLOCK_FP8_BF16.get() | ||
| and not use_deepgemm_runner |
There was a problem hiding this comment.
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.
| weight_scale: torch.Tensor, | ||
| input_scale: Optional[torch.Tensor] = None, | ||
| bias: Optional[torch.Tensor] = None, | ||
| act_scale_ue8m0: bool = False, |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
agree, btw seems like exactly the same behavior actually already exists in the main branch for the current block128
|
@vladnosiv Can you add aime dataset's acc too? |
|
/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. |
|
|
/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. |
|
🚀 🚀 🚀 |
BBuf
left a comment
There was a problem hiding this comment.
LGTM. The current-head targeted tests pass on H100, B200 and RTX 5090, including the native SM90 block32 and UE8M0 activation-scale cases.
|
/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. |
|
🚀 🚀 🚀 🚀 |
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
Accuracy Tests
GSM8K, correct answers
Speed Tests and Profiling
Fixed workload 16k inp / 1k out, simulated acceptance length 5.5
Trace analysis
Checklist
Review and Merge Process
/tag-and-rerun-ci,/tag-run-ci-label,/rerun-failed-ciCI States
Latest PR Test (Base): ❌ Run #38011736527
Latest PR Test (Extra): ❌ Run #38011736377
Latest PR Test (AMD ROCm 10): ❌ Run #38011736554