Repository navigation
[Perf] deepseek_v4: bump sgl-deep-gemm to 0.2.6, FlashInfer-layout scales from DeepGEMM producers, current MQA logits API - #48424
Conversation
… on SM107 On CC 10.7, wo_b (N=5120, K=8192) runs faster through the FlashInfer cute-dsl MXFP8 GEMM than through DeepGEMM at >= 8192 rows, including the conversion of the producer's DeepGEMM-packed activation scales to the FlashInfer 128x4 swizzle. Smaller row counts and other shapes stay on DeepGEMM, as does batch-invariant / deterministic mode. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…er's 128x4 scales Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…16 weights The 0.2.3-style call (positional clean_logits + logits_dtype kwarg) is routed by sgl-deep-gemm to fp8_fp4_mqa_logits_legacy, so prefill ran legacy/impls/sm100_bf16_mqa_logits.cuh. With bf16 weights, call the current API, which outputs bf16 logits and reaches impls/sm100_mqa_logits.cuh. fp32 weights keep the legacy call. B300, H32, 131K ctx, 4x4096 new tokens, sgl-deep-gemm built from source, index logits kernel time per prefill chunk (min of 4): DG 7ae89b8, old call 2180.9 / 4334.5 us (ratio 2 / ratio 1) DG 7ae89b8, new call 2181.3 / 4333.9 us DG sgl-project#134, old call 2181.2 / 4333.3 us DG sgl-project#134, new call 2087.0 / 4147.2 us (-4.3% / -4.3%) Logits are bitwise identical across all four arms. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> (cherry picked from commit 0cea022ee2c7ff211bb1ecad5e9c10d3b0c4a19d)
…rite FlashInfer scales FlashInfer on producer-written 128x4 scales beats or ties DeepGEMM at every measured row count (1..16384) for both DSv4 shapes, so the per-shape row threshold is removed. Batch-invariant and deterministic modes keep the DeepGEMM GEMM. batch_invariant_or_deterministic moves to mxfp8_input.py with top-level imports, and the allocation sites pass flashinfer= by keyword. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
/rerun-test registered/unit/layers/quantization/test_fp8_blockwise_linear_backends.py registered/kernels/ops/attention/dsv4/test_mega_attention.py registered/kernels/ops/layernorm/test_mhc_kernels.py registered/unit/models/test_deepseek_v4_boundary.py registered/unit/models/test_deepseek_v4_pipeline.py registered/e2e/model_executor/test_decoder_tail_moe_bound.py registered/kernels/ops/attention/test_dsv41_prefill_sparse_indexer.py registered/kernels/ops/attention/test_dense_prefill_indexer.py registered/kernels/ops/attention/test_fp4_indexer.py registered/unit/layers/test_dsv41_indexer_tp_shard.py registered/e2e/models/test_deepseek_v41_flash_gb300_dp2ep2.py |
|
🚀 🚀 🚀 🚀 🚀 |
This comment has been minimized.
This comment has been minimized.
…ales from DeepGEMM producers, current MQA logits API (sgl-project#48424) Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Summary
Bumps
sgl-deep-gemmto 0.2.6 and adopts the two 0.2.6 changes that need a caller-side change. The other 0.2.6 changes are DeepGEMM-internal and on by default: Mega MoE block_m 64 for decode loads, the mega_mhc split-barrier fix under CUDA graph replay, the K=64 MXF8F6F4 dense MMA on CC 10.7, and the SIMT dispatch pull for FP4 activations.DeepGEMM producers write FlashInfer's 128x4 scale layout (sgl-project/DeepGEMM#136)
On CC 10.7, two DSv4 linears take their input as an MXFP8 pair written by a DeepGEMM kernel.
wo_bgets it from thewo_afp8_einsumepilogue, andwqkv_afrom Mega mHC. 0.2.6 lets both producers write the scales directly in FlashInfer's 128x4 layout: pass a 4-D int32 scale[ceil(rows/128), K/128, 32, 4], and its flat uint8 view is FlashInfer'sa_descale. The pair then runs on the FlashInfer MXFP8 GEMM with no conversion step.mxfp8_input.pydeepgemm_pair_takes_flashinferis the route check.batch_invariant_or_deterministicmoves here fromfp8.py(with top-level imports), andFp8LinearMethod.applyuses it forpin_tactic.deepgemm_mxfp8_linear_inputhands a filled 4-D pair on asMxfp8SwizzledInput.Fp8LinearMethod.applyalready sends that type to FlashInfer.zero_deepgemm_mxfp8_scale_rowszeroes padded rows in either layout.deepseek_v4.py/deepseek_v4_mhc.py: the producers allocate the 4-D scale (flashinfer=on the allocation) when the route applies.Current MQA logits API for bf16 index weights (sgl-project/DeepGEMM#134)
The 0.2.3-style call (positional
clean_logitspluslogits_dtype) is routed by sgl-deep-gemm tofp8_fp4_mqa_logits_legacy. With bf16 weights,flat_index_logits_tilesnow calls the current API, which reaches the kernel #134 sped up. fp32 weights keep the legacy call. The logits are bitwise identical.Decode
wo_aeinsum producer also runs for decode and verify batches up to 2048 rows. Sowo_btakes the FlashInfer route there too, and the kernel table below covers decode-sized row counts.wqkv_a's Mega mHC producer is prefill-only, and the paged MQA logits call is unchanged, so neither route affects decode.Performance
Kernel level, CC 10.7. Producer + FlashInfer GEMM on 4-D scales, divided by producer + DeepGEMM GEMM on packed scales, both on 0.2.6. Each cell is one run or two runs (
run1 / run2) on swapped GPUs. Lower is better.wqkv_aat 8K–16K rows (0.99–1.00). On CC 10.3, an earlier measurement of the same producer + GEMM pair puts FlashInfer at 0.89–0.99, and DeepGEMM ahead by at most 1% (wqkv_aat 8K–16K). So no shape keeps a DeepGEMM route.#134 (CC 10.3, index logits per prefill chunk, H32, 131K context, 4×4096 new tokens): −4.3% with the new call. The old call is unchanged. Logits are bitwise identical.
Server, CC 10.7, DeepSeek-V4.1-Flash, DEP4 (
--dsv4-attn-backend flashmla_mega,SGLANG_OPT_DSV41_MEGA_MHC_PREFILL=1, DSPARK). Each arm ran once on each of two nodes.Accuracy is unchanged. At 16K-token prompts, prefill time is within run-to-run noise: these GEMMs are a small share of the step.
Decode, same server setup. Steady-state generation throughput summed over the 4 DP ranks, in tok/s. 128K-token context, simulated acceptance length 3.51, decode CUDA graphs up to 128. One server per cell; each arm ran once on each of two nodes.
wo_broute adds +1.7% on top (+1.5% and +1.8% on the two nodes).wo_broute adds +0.8%, within noise: +3.0% on one node and −1.3% on the other.A profiled prefill step on this PR (rank 0) shows both routes taken:
wo_bandwqkv_arun on FlashInfer's block-scaled dense GEMM.wo_aeinsum that produceswo_b's input.sm100_mqa_logits, not the legacy kernel.Tests
test_fp8_blockwise_linear_backends.py::test_deepgemm_producer_flashinfer_layout:flashinfer.block_scale_interleaveat 200 and 256 rows;CC 10.3 with sgl-deep-gemm 0.2.6: the file gives 17 passed and 7 skipped.
Indexer tests (
test_fp4_indexer,test_dense_prefill_indexer,test_dsv41_prefill_sparse_indexer,test_dsv41_indexer_tp_shard) on CC 10.3 with 0.2.6: 117 passed, 2 skipped.🤖 Generated with Claude Code
CI States
Latest PR Test (Base): ❌ Run #41934628566
Latest PR Test (Extra): ❌ Run #41934628353
Latest PR Test (AMD ROCm 10): ❌ Run #41934628246
Tip
Base CI only covers the core cases, and its workload may not exercise your change. Use
/rerun-testto run the tests your change touches, or copy this prompt for an agent: