Repository navigation
[Feat] deepseek_v41: Serve decode and verify steps on SGLang's FP8 unified KV - #79
Open
ChangLi811 wants to merge 1 commit into
Open
ChangLi811 wants to merge 1 commit into
ChangLi811 wants to merge 1 commit into
Conversation
ChangLi811
force-pushed
the
dsv41-fp8-unified-kv
branch
from
October 29, 2026 15:26
d3831ce to
8361f90
Compare
This was referenced Oct 29, 2026
ChangLi811
marked this pull request as ready for review
October 29, 2026 15:27
ChangLi811
force-pushed
the
dsv41-fp8-unified-kv
branch
from
October 29, 2026 16:21
8361f90 to
5d47732
Compare
ChangLi811
requested review from
HaiShaw,
alexnails and
kevin-mii
as code owners
October 29, 2026 16:21
…ified KV
With SGLANG_HACK_FLASHMLA_BACKEND=unified_kv_triton and
SGLANG_DSV4_UNIFIED_KV_FP8=1, SGLang keeps a layer's KV in two pools (a 512 B nope
row of e4m3 and doubled E8M0 codes, a 128 B bf16 rope row) addressed by one row
index: per-request SWA rings, then the compressed rows past a layer base. The
DSpark draft's ring is bf16, one pool.
K1 writes the step's rows at SGLang's ring rows in that layout (and the draft's
bf16 pair, rounded before RoPE as SGLang's draft writer does); K2 reads the window
keys from SGLang's ragged SWA stream and the compressed rows past the layer base,
as the paged record's words, so the attention core is the paged one. On the bf16
ring K2 quantizes each key's nope tiles as K1 quantizes a record. One field, kv in
("paged", "fp8", "bf16"), names the layout throughout; the paged path is
unchanged. The bf16 unified KV without the FP8 pools is still refused.
The kernel checks gain --unified and --bf16-ring: K1 against SGLang's own writers
of the two layouts, K2 on the unified pools holding the paged keys, bit for bit
against the paged K2.
The README names sgl-project/sglang#44031 (V4.1's FP8 unified KV) among its
requirements.
The pool's get_unified_compress_row_base comes with sgl-project/sglang#44031, not in
SGLang main yet: it is read by name (PENDING_POOL_READS), so an SGLang without it is
refused with that reason, as minimax_m3 does for its pending switches; it moves to
SGLANG_READS once #44031 merges.
ChangLi811
force-pushed
the
dsv41-fp8-unified-kv
branch
from
October 30, 2026 03:16
5d47732 to
4951040
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Needs sgl-project/sglang#44031 (V4.1's FP8 unified KV with the DSpark draft).
Motivation
The monokernels read only SGLang's paged KV, so
SGLANG_HACK_FLASHMLA_BACKEND=unified_kv_tritonwithSGLANG_DSV4_UNIFIED_KV_FP8=1is refused, while the unified KV is the cache V4.1 serving moves to (with #44031, including the DSpark draft).Modifications
kvin("paged", "fp8", "bf16"), names the layout in the builds and the runner; the paged path is unchanged. The bf16 unified KV without the FP8 pools is still refused.check_k1 --unified / --bf16-ringagainst SGLang's own writers of the two layouts;check_k2 --unified --bf16-ringon the unified pools holding the paged keys, bit for bit against the paged K2.Accuracy Tests
DeepSeek-V4.1-Flash + DSpark (block size 5), one MI355X node,
rocm/sgl-dev:v0.5.22-rocm10-mi35x-20261025, SGLang: a local merge of #43465 (15e93db9e), #44730, #44031 and #46036 (aa6e51982). GSM8K: sgl-eval, 1319 questions, max tokens 4096. FP8 unified KV + decoder replay; on and off on fresh servers.Needles, zero-row groups and c16 / c32 stress pass; KL within bounds. Kernel checks at TP2 and TP4 (widths 1–48):
check_k1/check_k2paged,--unified,--bf16-ringall pass after rebasing ontomain.GSM8K above runs 64 threads, so most verify steps are wider than 8 requests and take SGLang's path. With AgentX's c1 recipe (
max-running-requests 2, its 19 environment variables,SGLANG_HIP_DSV41_INDEX_K_PAGE8=1), every verify step runs on the monokernels; on #70 (now inmain) plus this PR, #78 and #80 (DeepSeek-V4.1-Flash-1017 weights, fresh servers):(GSM8K / DSpark accept length. TP4 "off" accept lengths are left out: with the recipe's
--disable-shared-experts-fusion, SGLang's own path accepts less at batch 1–3, which--enforce-shared-experts-fusion, as the README uses, restores.)PD
MoRI PD (enabled by #70) over two MI355X nodes: P = TP4 + prefill CP4 + DSpark without the monokernels, D = TP4 + DSpark;
SGLANG_HIP_DSV41_INDEX_K_PAGE8=1on both peers; P and D started afresh for every row; GSM8K through the PD router.At 8 threads every verify step of the D runs on the monokernels when they are on. Greedy prompts (short, 15k–100k) and 50 long needles pass on every row; no GPU faults on either peer.
Speed Tests and Profiling
TP4, ShareGPT through the chat API, 500 output tokens: output throughput (tok/s) / mean TPOT (ms).
Checklist
pre-commit run --all-filespasses (ruff, isort, codespell).test/cover the change.aa6e51982:pytest test/unitpasses 264 (262 onmain), including the new unified-KV tests and thedeepseek_v41contract, which also passes against SGLang main (c6c753395). The 7 failures and 3 collection errors (GLM-5.3, MiniMax and DeepSeek-V4-Pro tests) are the same onmainand unrelated to this PR.get_unified_compress_row_basecomes with [Feat] [AMD] DeepSeek-V4.1: FP8 unified KV for the ratio-1/2 layers, with DSpark, PD and the UMBP linker sglang#44031, not in SGLang main yet. It is read by name (PENDING_POOL_READS), asminimax_m3does for its pending switches: on SGLang main the FP8 unified KV is refused at startup with that reason, and the paged KV is unaffected; on SGLang with #44031 nothing changes. Once #44031 merges, a follow-up moves the name intoSGLANG_READSand drops the check..github/CODEOWNERSthat names its owner. (No new model.)