ndamiano/sglang-rtxpro6000

Personal Optimized SGLang runtime for Qwen3.8-27B/DFlash2 and Qwen3.8 Flash-Next on one RTX PRO 6000 Blackwell (SM120).

Python

0

15,267 commits

updated Sep 3, 2026

See the code

See what people are saying

SourceMessageScoreDate

Open sourcing Game Summoner, my prompt to game site (r/LocalLLaMA)

tldr: Open sourced my prompt to game suite: https://github.com/ndamiano/ai-agent-test, it's MIT licensed, and this runs well on my 5090 with 64gb ram, but any model that can handle tool calls can manage. Edit: I can't believe I forgot to share a game... This is one shot with qwen 3.8 flash next!…

8

Oct 8, 2026

README

One SGLang runtime, two Qwen3.8 configurations, one RTX PRO 6000

One optimized SGLang runtime for a single RTX PRO 6000, with qualified launch configurations for both Qwen3.8-27B/DFlash2 and Qwen3.8 Flash-Next.

This repository contains the complete SGLang-derived source used on one NVIDIA RTX PRO 6000 Blackwell Workstation Edition (96 GB, SM120, TP=1). It is not two builds: both model configurations run from the same patched source.

  • Qwen3.8-27B pairs an FP8 target with incoai/Qwen3.8-27B-DFlash2.
  • Qwen3.8 Flash-Next pairs an NVFP4 target with its native NEXTN MTP layer.

Flash-Next is day-one engineering. It has extensive qualification on this exact machine—including 524K context, multimodal input, reasoning, tools, agentic workloads, CUDA-graph recovery, and persistent prefix restoration—but it may still contain rough edges or hardware/model-specific assumptions.

Validation suite

The canonical test suite used to qualify these runtimes—including reasoning, tool calling, long-context needles, vision, and concurrent decode—is maintained in jpezzulli/pennyroyal-validation. This repository contains the runtime source, configuration, and measured results; pennyroyal-validation contains the reusable tests and result catalog.

Why this runtime exists

The important work is architectural, not merely a collection of launch flags:

  • DFlash2 integration for Qwen3.8-27B, with the selector inside the draft CUDA graph, fused draft KV materialization, and fixed-width TRTLLM-MHA/XQA target verification on SM120.
  • Native NEXTN MTP for Flash-Next with QSA index sharing, recovery graphs, and gdn_mtp_cache_mode=none.
  • FlashInfer GDN decode and prefill for Flash-Next, plus a deliberately narrow SM120 FlashInfer WY output-only RecoverSSM path.
  • QSA sparse attention: Triton sparse-GQA prefill, the FlashInfer QSA wrapper resolving to XQA on SM120, and sgl-kernel top-k.
  • FlashInfer CUTLASS MoE for the Flash-Next target and native-MTP layer.
  • Correct three-axis multimodal mRoPE in the fused QK RMSNorm+RoPE kernel.
  • Target, draft, verify, prefill, and accepted-state recovery CUDA graphs.
  • FP8 KV and 524,288-token factor-2 YaRN for both launch configurations.
  • HiCache/NIXL persistence for complete hybrid state—not KV alone—including DFlash2 side state or Flash-Next GDN, Qwen4 PLE, and compressed QSA state.
  • Restart restoration, representation-specific FILE namespaces, and radix- prefix reuse followed by long continuation.
  • Measured reasoning, tool-calling, vision, long-context needle, controlled decode, and real agentic behavior.

Published identity

ItemValue
Canonical branchpennyroyal-main-sm120-final
Current executable sourcefb1216c6c459cb024e709eba892d9e7ded103688
Current release tagpennyroyal-v2.1.1
Initial unified dated tagsglang-rtxpro6000-20260827
Earlier 27B dated tagqwen38-dflash2-pro6000-20260824
Upstream integration basee7e78940168f3ba65c762a6f82fd8bc5b6ee04e3
Installed SGLang0.5.19.dev490+gfb1216c6c
Python / PyTorch3.12.13 / 2.13.0+cu130
CUDA / compilerCUDA 13.3 (NVCC 13.3.73) / GCC 15.3.1
FlashInfer / NIXL0.6.17 / 1.4.0
GPU / driverRTX PRO 6000 96 GB, SM120 / 610.57.04

The current documentation commit sits above the executable source. It does not change python/, rust/, or the kernel trees. Exact source lineage and current upstream status are in CHANGES.md and PROVENANCE.md.

Qualified configuration matrix

Rows intentionally separate representation, datatype, backend, and capacity. The BF16 runtime dtype is not presented as a claim that every quantized kernel executes or accumulates entirely in BF16.

PropertyQwen3.8-27B + DFlash2Qwen3.8 Flash-Next
Target checkpointorcarouter/Qwen3.8-27B-Uncensored-FP8 familyRadixArk/Qwen3.8-Flash-Next-NVFP4
Target weight formatblock FP8 E4M3, 128x128 blocksModelOpt NVFP4, group size 16 on selected Linear modules
Quantized-path activationsdynamic FP8 E4M3NVFP4 input activations on selected Linear modules
Runtime dtype for unquantized tensorsBF16; includes excluded layers and BF16 lm_headBF16; includes ignored layers, native MTP, PLE, QSA/GDN state-facing tensors, and vision
Target KV datatypeFP8 E4M3FP8 E4M3
Speculative KV datatypeDFlash2 draft: FP8 E4M3native-MTP: FP8 E4M3
Recurrent/GDN SSM stateFP32BF16
Convolution stateBF16BF16
MoE backendTriton FP8 MoE; auto resolves to Triton with A2A noneFlashInfer CUTLASS for target and native MTP
Target attentionFlashInfer prefill; TRTLLM-MHA/XQA decode and fixed-width verifyQSA Triton sparse prefill; FlashInfer QSA wrapper resolving to XQA for sparse decode; general attention FlashInfer
Linear/GDN attentionTriton decode, prefill, and state-writing verifyFlashInfer decode/prefill; WY output-only verify/recovery in none mode
Speculative backendDFlash2, 8 draft tokens, 2,048-token windownative NEXTN, 3 steps, top-k 1, 4 draft tokens
Served context524,288, factor-2 YaRN target and draft524,288, factor-2 YaRN
KV page size6464
Current GPU KV capacity1,118,784 target and draft tokens824,384 target and native-MTP tokens
Mamba capacity24 slots; maximum 5 retained states/path24 slots; extra_buffer, tracking interval 64
HiCache/NIXL96 GB configured host tier; target KV + Mamba/GDN + DFlash2 state32 GB configured host tier; packed target/native-MTP KV + GDN + PLE + QSA keys
Maximum active requests44

The current 27B launcher uses the 24-slot/five-state setting qualified on 2026-08-26. The earlier 2026-08-24 performance release used 16 slots, a three-state path cap, and a 1,194,496-token KV pool. Both campaigns are retained in RESULTS.md rather than silently merging their allocations.

Resolved backends: Qwen3.8-27B/DFlash2

Component or phaseResolved implementationHow selected or enabledEvidence
Target prefill attentionFlashInferexplicit hybrid prefill backend64K and 490K controlled prefill
Target decode attentionTRTLLM-MHA with XQAexplicit decode backend; SM120 supported pathcontrolled and agentic decode
Fixed-width target verificationTRTLLM-MHA/XQA with packed causal masklocal 0f159cd545graph-metadata regression; 1x/4x decode
Linear/GDN decode, prefill, verifyTritonresolved linear backendstartup configuration and long-context suite
Target FP8 MoETritonauto + A2A none resolves Fp8MoEMethod to Tritonserver args plus source resolver
DFlash2 draft attentionFlashInferexplicit draft backenddraft-runner startup line
Draft local convolutionDFlash2 local-convolution pathmerged upstream PR #35371DFlash2 startup and decode
Candidate selectionfolded into draft CUDA graphupstream DFlash2 integrationgraph-capture startup line
DFlash fused KV materializationenabled, 5 layers / 8 KV heads / 128 head dimupstream DFlash2 integrationallocation/startup line
Multimodal attentiontriton_attnautomaticstartup log; vision smoke
Multimodal rotaryfused three-axis mRoPElocal 64ecd64924, PR #35744numerical kernel tests and vision
Sampling / grammarFlashInfer / XGrammarautomaticstartup log; reasoning and tools
HiCache transferNIXL POSIX, io_uring, O_DIRECTexplicit storage backendrestart and concurrent restoration
Persistent representationtarget KV + Mamba/GDN + DFlash2 sidecarlocal NIXL integrationnamespace and restore qualification

The selected 27B target keeps lm_head in BF16. The quantized-head selector from upstream PR #35496 is present in the base but is not the source of this checkpoint's measured speed. No separate local DeepGEMM SM120 patch is claimed; this FP8 configuration resolves MoE to Triton.

Resolved backends: Qwen3.8 Flash-Next

Component or phaseResolved implementationHow selected or enabledEvidence
Target GDN decodeFlashInferGDNKernelnarrow phase overridestartup dispatcher; 1x/4x decode
Target GDN prefillFlashInferGDNKernelnarrow phase override64K/490K prefill and needles
Native-MTP draft decodeFlashInferGDNKernelshared GDN dispatchdraft CUDA graphs and live decode
Native-MTP draft extendFlashInferGDNKernelshared GDN dispatchdraft extend graph capture
Active GDN target verificationFlashInfer WY output-onlylocal 280825c3e2, none mode onlydirect state parity and graph replay
Ordinary/tree state-writing verificationTritonGDNKernelarchitecture gate deliberately preservednon-none source dispatch and focused tests
Accepted-state recoveryFlashInfer WY output-onlynarrow SM120 RecoverSSM routerecovery graphs BS 1-4; long continuation
QSA sparse prefillTriton sparse GQAmodel path + FP8 tile fix 95da38fb3b64K/490K exact qualification
QSA sparse decodeFlashInfer QSA wrapper resolving to XQASM120 wrapper dispatch c1da0eef56, narrowed to exact SM120 by 8de07a058f; FlashInfer selects XQA on SM120direct backend probe and live decode
QSA top-ksgl-kernelautomaticstartup resolution
QSA MTP index sharingenabledmodel pathstartup line and shared-index tests
Target MoEFlashInfer CUTLASSautomatic ModelOpt-NVFP4 resolutionstartup resolution and live tests
Native-MTP MoEFlashInfer CUTLASSautomatic speculative resolutionstartup resolution and live tests
HyperConnection Mixpersistent Triton Mixautomatic SM120 fallbackHC numerical tests; FlashInfer gate retained
HyperConnection Combinefused SGLang CUDAQwen4 model pathkernel tests and full suite
Multimodal attentiontriton_attnautomaticfull 1,024-token vision validation
Sampling / grammarFlashInfer / XGrammarautomaticstartup log; reasoning and tool suite
HiCache transferNIXL POSIX, io_uring, O_DIRECTexplicit storage backend64K/490K restart restoration
Persistent representationpacked target/native-MTP KV + complete GDN/PLE siblings + compressed QSA keyslocal hybrid-pool integrationrestart restore, needles, continuation

SM120 enablement was scoped, not indiscriminate

Several upstream checks treated SM100 as the only eligible architecture even when an underlying kernel already compiled for SM120. This runtime distinguishes three cases:

  1. Explicit phase override. Automatic GDN selection used an SM100 helper and therefore did not select FlashInfer on SM120. FlashInfer 0.6.17 already supported the BF16 decode and prefill operations used here. The launcher selects only those phases with --linear-attn-decode-backend flashinfer and --linear-attn-prefill-backend flashinfer. Long prefill, exact needles, decode, and vision/reasoning qualification cover the resulting runtime.

  2. Narrow source integration. RecoverSSM needed FlashInfer WY output-only state output and accepted-state recovery. FlashInfer already contained an sm_120a implementation, but SGLang did not route SM120 into it. Commit 280825c3e2 enables only the output/recovery route used by gdn_mtp_cache_mode=none and preserves Qwen4 PLE accepted-state commit ordering. Direct tests cover all accepted lengths for four draft tokens, batch sizes 1-4, mixed acceptance, positions 63/64/65, extra_buffer, prefix restoration, retraction, long continuation, and captured-graph replay.

  3. QSA wrapper enabled, backend distinguished. Commit c1da0eef56 lets SM120 enter FlashInfer's page-aligned QSA decode wrapper, while 8de07a058f adopts upstream #36806's exact (12, 0) gate so SM121/GB10 is not admitted. On SM120 the wrapper resolves to XQA, an existing supported implementation; it does not select TRTLLM-Gen. No upstream SM100 throughput claim is attributed to Penny's SM120 results.

  4. Incompatible gates deliberately retained. Forced TRTLLM-Gen fails with Unsupported architecture. Bypassing the guard and loading the exact BF16-Q/FP8-KV/H256/P64 cubin directly returns CUDA_ERROR_NO_BINARY_FOR_GPU (209): the binary targets SM100 and contains the sm10x_tcgen05 instruction family unavailable on SM120. Supporting it would require kernel/compiler adaptation upstream of SGLang; see TensorRT-LLM #11799 and FlashInfer #3628. Ordinary FlashInfer state-writing GDN verification also remains gated and uses Triton, while FlashInfer HyperConnection Mix remains SM100-only and falls back to the qualified persistent Triton Mix.

Other bounded corrections follow the same rule. 0f159cd545 supplies XQA's packed mask for fixed-width DFlash2 verification rather than enabling a new global attention backend. 64ecd64924 extends the fused rotary kernel to real three-axis mRoPE rather than dropping the fused path or ignoring H/W positions.

Memory recovery and automatic KV sizing

Flash-Next configurationIntermediate SSMMamba slotsGPU KV capacity
BF16 before RecoverSSM1.05 GiB24745,600 tokens
RecoverSSM none mode024824,384 tokens

The sequence matters:

  1. BF16 reduced recurrent-state bytes per slot.
  2. Automatic Mamba sizing then expanded from 21 to 49 slots and consumed much of that saving.
  3. The workload needed far fewer slots; 24 remained above observed demand and returned the rest of the budget to KV.
  4. RecoverSSM removed the separate 1.05 GiB intermediate speculative SSM pool.
  5. With no forced KV-token count, the measured KV pool increased by 78,784 tokens—from 745,600 to 824,384, or 10.6%.

The physical pool is removed in 280825c3e2, but the current kv_cache_configurator.py::_handle_max_mamba_cache estimator only omits that reserve for ReplaySSM, not RecoverSSM none. There is no separate allocator correction commit in this runtime. The qualified launcher increases --mem-fraction-static from .97 to .981, approximately the recovered GPU fraction, so automatic KV sizing can consume the physically freed memory. The 824,384-token result was measured, not hard-coded, but the estimator debt is real and documented.

Performance and qualification

These rows are observations from different model configurations and are not a single A/B benchmark.

Flash-Next final campaign — source 64ecd64924

The published campaign below used lactd with the workstation card's fan curve active and this relevant power/clock profile:

power_cap: 450.0
min_core_clock: 210
max_core_clock: 2750
gpu_clock_offsets:
  0: 1000
mem_clock_offsets:
  0: 2000
TestResult
64K cold prefill10,103.70 tok/s
~490K cold prefill7,872.15 tok/s; 3/3 exact needles
1x 1,024-token decode171.09 tok/s
4x 1,024-token synchronized batch427.54 tok/s aggregate
MTP mean accepted length / rate2.58 / 52.74%
Reasoning97.49/100 across 139,863 completion tokens
Tools30/30 exact calls and semantically correct after review
Visioncomplete 1,024-token validation passed
Sealed agentic control148.80 tok/s
Natural 3,072-token decode162.05 tok/s

Per-stream post-first-token rates do not sum to the synchronized aggregate because each stream uses its own interval. The aggregate includes TTFT and the batch tail. These results were measured with QSA sparse decode resolving to XQA. No matched SM120 end-to-end A/B supports a percentage claim against another QSA backend.

Independent TP=2 FP8 validation

H3PO independently validated this runtime on a dual-GPU TP=2/EP=2 FP8 deployment with native MTP after removing the optional overlap-plan-stream setting. The raw third-party table, corpus description, capacity result, and scope limits are preserved in RESULTS.md.

Qwen3.8-27B/DFlash2 dated performance campaign

TestResult
64K prefill6,163.07 tok/s
489,921-token prefill1,618.31 tok/s; 3/3 exact needles
1x 1,024-token decode108.75 tok/s after first token
4x 1,024-token decode390.23 tok/s aggregate
Reasoning, xhigh / medium98.26 / 95.807
Medium tool suite30/30 tool selections and arguments; 29/30 reviewed response discipline

The cited public TP1 official-FP8/MTP3 community capture is directional rather than a strict A/B because checkpoint, runtime, speculation, power, harness, output duration, and cache configuration differ.

The current 24-slot/five-state confirmation retained exact long-context needles, reached a 96.92 reasoning score across 50,986 completion tokens, and used at most 10 of 24 Mamba entries.

27B real agentic context behavior

The dated 124-request sample covered 85,156 output tokens and inputs from 183 to 350,195 tokens. RESULTS.md preserves the context-band tables, overlap treatment, and distinction between completed-request and instantaneous telemetry measurements.

Flash-Next real agentic context behavior

A separate decontaminated 96-request window covered 100,666 output tokens. RESULTS.md preserves its context-band and aggregate tables. The first sample after a large prefill was excluded because its telemetry interval mixed prefill or idle time with decode.

Detailed definitions, complete 27B context bands, both 27B campaigns, and persistence evidence are in RESULTS.md.

HiCache/NIXL persistence

HiCache/NIXL does not cause GPU-resident decode speed. It provides disposable, reusable prefix state across GPU/host eviction and service restart:

GPU radix state
  -> page-first HiCache host RAM, kernel I/O, write-through
  -> NIXL POSIX FILE storage, io_uring + O_DIRECT

Flash-Next restart evidence:

  • 63,808 of 63,864 input tokens restored; 56 recomputed.
  • 489,856 of 489,879 restored; 23 recomputed.
  • all three needles exact after restart.

The earlier 27B work also demonstrated 518,528 restored tokens with a six-token tail in 14.64 seconds, 60,032-token namespace reuse after restart, A→B→A page- size namespace rollback, three concurrent ~60K restores, and a 775,168-token three-request concurrent restore with only 320 tail/page-rounding tokens computed.

Two portable NIXL fixes from this project remain open upstream: PR #36520 isolates overlapping path registrations, and PR #36524 bounds bounce-backed hybrid transfers. Flash-Next adds complete PLE/GDN/QSA sibling-state persistence and load/COW ordering. MEMORY-AND-PERSISTENCE.md documents the representation namespace and actual failure boundaries.

Build and launch

There is one native build procedure and exactly two canonical launch recipes:

uv python install 3.12.13
uv venv --python 3.12.13 .venv
source .venv/bin/activate

export CUDA_HOME=/usr/local/cuda
export CC=/usr/bin/gcc-15 CXX=/usr/bin/g++-15 CUDAHOSTCXX=/usr/bin/g++-15
export MAX_JOBS=24 CMAKE_BUILD_PARALLEL_LEVEL=24
export FLASHINFER_NINJA_JOBS=24 FLASHINFER_NVCC_THREADS=4
export TORCHINDUCTOR_COMPILE_THREADS=24

uv pip install --prerelease=allow --index-strategy unsafe-best-match \
  --extra-index-url https://docs.sglang.ai/whl/cu130/ \
  --no-build-isolation -e python

Set REPO_ROOT, CACHE_BASE, NIXL_STORAGE_BASE, and the checkpoint paths, then choose one recipe:

configs/pennyroyal/serve-qwen38-27b-dflash2.sh
configs/pennyroyal/serve-flash-next.sh

Do not run them simultaneously on one GPU. BUILD.md records exact dependencies and RUN.md provides startup assertions, ordinary OpenAI-compatible smoke requests, and cold/radix/NIXL cache distinctions.

Source changes and upstream work

The cumulative history starts with the 2026-08-24 27B release, then layers the unified runtime and Flash-Next work on the same source line. The current active stack contains 24 commits above its integration base. Major groups are:

  • Qwen3.8-27B/DFlash2: independent target/draft overrides, fixed-width XQA mask, NVCC host-compiler identity, request-span observability, and NIXL correctness.
  • Flash-Next: Qwen4 model support, QSA/HC/PLE/native-MTP integration, SM120 QSA decode, FP8 QSA prefill, RecoverSSM, complete hybrid persistence, and mRoPE.
  • v2.1 upstream sync: exact-SM120 QSA routing from #36806 and the Mamba radix ghost-node/speculative tracking correction from #35821, adapted to Penny's fused CUDA and KDA accepted-state paths.
  • v2.1.1 maintenance: accumulated additive sampling penalties are applied correctly during 27B DFlash2 verification; shared HiCache JIT transfers are bound to their torch copy streams and load-back waits for in-flight forward writes for both supported models.
  • Open project PRs: #36520, #36524, and #35584.
  • Closed project submissions retained in runtime history: #35583; transient ragged/DSpARK PR #35586 is documented but not in the active source.
  • Related upstream work: #30967, #35371, #35496, #35744, #35821, #36497, #36644, and #36806.

CHANGES.md lists every material current commit, the earlier dated release hashes, exact PR links/status/heads, affected execution paths, and test coverage.

Scope and limitations

  • One RTX PRO 6000, TP=1, exact checkpoint families, and the recorded CUDA, PyTorch, FlashInfer, compiler, NIXL, and SGLang source.
  • SM120 paths were qualified narrowly; unsupported-by-default is not treated as proof of incompatibility, but no architecture gate was globally deleted.
  • Benchmark observations are not guarantees for another system.
  • Flash-Next and 27B results remain separate; neither model's features or numbers are silently attributed to the other.
  • The full published Flash-Next reasoning/tool/vision campaign ran at 64ecd64924. The v2.1.1 source at fb1216c6c4 received focused CPU/GPU DFlash, HiCache, hybrid/NIXL, and unified-load-back tests plus ordinary 64K/490K/1K/C4 and post-restart NIXL restoration on both supported models. The full reasoning and tool suites were not rerun for this narrow update.
  • NIXL cleaner thresholds are whole-filesystem occupancy percentages, not an absolute directory byte quota.

See LIMITATIONS.md for measurement and reproducibility detail.

Documentation map

Engineering history

The experimental path—including DFlash2 work and the HiCache/Mooncake/NIXL detour—is described at msoexpert.com. Mooncake is not a fallback in this runtime; it was rejected and removed.

License

The SGLang-derived source remains under Apache-2.0. Model checkpoints and third-party runtimes retain their own licenses.

ndamiano/sglang-rtxpro6000

Personal Optimized SGLang runtime for Qwen3.8-27B/DFlash2 and Qwen3.8 Flash-Next on one RTX PRO 6000 Blackwell (SM120).

Python

0

15,267 commits

updated Sep 3, 2026

See the code

See what people are saying

SourceMessageScoreDate

Open sourcing Game Summoner, my prompt to game site (r/LocalLLaMA)

tldr: Open sourced my prompt to game suite: https://github.com/ndamiano/ai-agent-test, it's MIT licensed, and this runs well on my 5090 with 64gb ram, but any model that can handle tool calls can manage. Edit: I can't believe I forgot to share a game... This is one shot with qwen 3.8 flash next!…

8

Oct 8, 2026

README

One SGLang runtime, two Qwen3.8 configurations, one RTX PRO 6000

One optimized SGLang runtime for a single RTX PRO 6000, with qualified launch configurations for both Qwen3.8-27B/DFlash2 and Qwen3.8 Flash-Next.

This repository contains the complete SGLang-derived source used on one NVIDIA RTX PRO 6000 Blackwell Workstation Edition (96 GB, SM120, TP=1). It is not two builds: both model configurations run from the same patched source.

  • Qwen3.8-27B pairs an FP8 target with incoai/Qwen3.8-27B-DFlash2.
  • Qwen3.8 Flash-Next pairs an NVFP4 target with its native NEXTN MTP layer.

Flash-Next is day-one engineering. It has extensive qualification on this exact machine—including 524K context, multimodal input, reasoning, tools, agentic workloads, CUDA-graph recovery, and persistent prefix restoration—but it may still contain rough edges or hardware/model-specific assumptions.

Validation suite

The canonical test suite used to qualify these runtimes—including reasoning, tool calling, long-context needles, vision, and concurrent decode—is maintained in jpezzulli/pennyroyal-validation. This repository contains the runtime source, configuration, and measured results; pennyroyal-validation contains the reusable tests and result catalog.

Why this runtime exists

The important work is architectural, not merely a collection of launch flags:

  • DFlash2 integration for Qwen3.8-27B, with the selector inside the draft CUDA graph, fused draft KV materialization, and fixed-width TRTLLM-MHA/XQA target verification on SM120.
  • Native NEXTN MTP for Flash-Next with QSA index sharing, recovery graphs, and gdn_mtp_cache_mode=none.
  • FlashInfer GDN decode and prefill for Flash-Next, plus a deliberately narrow SM120 FlashInfer WY output-only RecoverSSM path.
  • QSA sparse attention: Triton sparse-GQA prefill, the FlashInfer QSA wrapper resolving to XQA on SM120, and sgl-kernel top-k.
  • FlashInfer CUTLASS MoE for the Flash-Next target and native-MTP layer.
  • Correct three-axis multimodal mRoPE in the fused QK RMSNorm+RoPE kernel.
  • Target, draft, verify, prefill, and accepted-state recovery CUDA graphs.
  • FP8 KV and 524,288-token factor-2 YaRN for both launch configurations.
  • HiCache/NIXL persistence for complete hybrid state—not KV alone—including DFlash2 side state or Flash-Next GDN, Qwen4 PLE, and compressed QSA state.
  • Restart restoration, representation-specific FILE namespaces, and radix- prefix reuse followed by long continuation.
  • Measured reasoning, tool-calling, vision, long-context needle, controlled decode, and real agentic behavior.

Published identity

ItemValue
Canonical branchpennyroyal-main-sm120-final
Current executable sourcefb1216c6c459cb024e709eba892d9e7ded103688
Current release tagpennyroyal-v2.1.1
Initial unified dated tagsglang-rtxpro6000-20260827
Earlier 27B dated tagqwen38-dflash2-pro6000-20260824
Upstream integration basee7e78940168f3ba65c762a6f82fd8bc5b6ee04e3
Installed SGLang0.5.19.dev490+gfb1216c6c
Python / PyTorch3.12.13 / 2.13.0+cu130
CUDA / compilerCUDA 13.3 (NVCC 13.3.73) / GCC 15.3.1
FlashInfer / NIXL0.6.17 / 1.4.0
GPU / driverRTX PRO 6000 96 GB, SM120 / 610.57.04

The current documentation commit sits above the executable source. It does not change python/, rust/, or the kernel trees. Exact source lineage and current upstream status are in CHANGES.md and PROVENANCE.md.

Qualified configuration matrix

Rows intentionally separate representation, datatype, backend, and capacity. The BF16 runtime dtype is not presented as a claim that every quantized kernel executes or accumulates entirely in BF16.

PropertyQwen3.8-27B + DFlash2Qwen3.8 Flash-Next
Target checkpointorcarouter/Qwen3.8-27B-Uncensored-FP8 familyRadixArk/Qwen3.8-Flash-Next-NVFP4
Target weight formatblock FP8 E4M3, 128x128 blocksModelOpt NVFP4, group size 16 on selected Linear modules
Quantized-path activationsdynamic FP8 E4M3NVFP4 input activations on selected Linear modules
Runtime dtype for unquantized tensorsBF16; includes excluded layers and BF16 lm_headBF16; includes ignored layers, native MTP, PLE, QSA/GDN state-facing tensors, and vision
Target KV datatypeFP8 E4M3FP8 E4M3
Speculative KV datatypeDFlash2 draft: FP8 E4M3native-MTP: FP8 E4M3
Recurrent/GDN SSM stateFP32BF16
Convolution stateBF16BF16
MoE backendTriton FP8 MoE; auto resolves to Triton with A2A noneFlashInfer CUTLASS for target and native MTP
Target attentionFlashInfer prefill; TRTLLM-MHA/XQA decode and fixed-width verifyQSA Triton sparse prefill; FlashInfer QSA wrapper resolving to XQA for sparse decode; general attention FlashInfer
Linear/GDN attentionTriton decode, prefill, and state-writing verifyFlashInfer decode/prefill; WY output-only verify/recovery in none mode
Speculative backendDFlash2, 8 draft tokens, 2,048-token windownative NEXTN, 3 steps, top-k 1, 4 draft tokens
Served context524,288, factor-2 YaRN target and draft524,288, factor-2 YaRN
KV page size6464
Current GPU KV capacity1,118,784 target and draft tokens824,384 target and native-MTP tokens
Mamba capacity24 slots; maximum 5 retained states/path24 slots; extra_buffer, tracking interval 64
HiCache/NIXL96 GB configured host tier; target KV + Mamba/GDN + DFlash2 state32 GB configured host tier; packed target/native-MTP KV + GDN + PLE + QSA keys
Maximum active requests44

The current 27B launcher uses the 24-slot/five-state setting qualified on 2026-08-26. The earlier 2026-08-24 performance release used 16 slots, a three-state path cap, and a 1,194,496-token KV pool. Both campaigns are retained in RESULTS.md rather than silently merging their allocations.

Resolved backends: Qwen3.8-27B/DFlash2

Component or phaseResolved implementationHow selected or enabledEvidence
Target prefill attentionFlashInferexplicit hybrid prefill backend64K and 490K controlled prefill
Target decode attentionTRTLLM-MHA with XQAexplicit decode backend; SM120 supported pathcontrolled and agentic decode
Fixed-width target verificationTRTLLM-MHA/XQA with packed causal masklocal 0f159cd545graph-metadata regression; 1x/4x decode
Linear/GDN decode, prefill, verifyTritonresolved linear backendstartup configuration and long-context suite
Target FP8 MoETritonauto + A2A none resolves Fp8MoEMethod to Tritonserver args plus source resolver
DFlash2 draft attentionFlashInferexplicit draft backenddraft-runner startup line
Draft local convolutionDFlash2 local-convolution pathmerged upstream PR #35371DFlash2 startup and decode
Candidate selectionfolded into draft CUDA graphupstream DFlash2 integrationgraph-capture startup line
DFlash fused KV materializationenabled, 5 layers / 8 KV heads / 128 head dimupstream DFlash2 integrationallocation/startup line
Multimodal attentiontriton_attnautomaticstartup log; vision smoke
Multimodal rotaryfused three-axis mRoPElocal 64ecd64924, PR #35744numerical kernel tests and vision
Sampling / grammarFlashInfer / XGrammarautomaticstartup log; reasoning and tools
HiCache transferNIXL POSIX, io_uring, O_DIRECTexplicit storage backendrestart and concurrent restoration
Persistent representationtarget KV + Mamba/GDN + DFlash2 sidecarlocal NIXL integrationnamespace and restore qualification

The selected 27B target keeps lm_head in BF16. The quantized-head selector from upstream PR #35496 is present in the base but is not the source of this checkpoint's measured speed. No separate local DeepGEMM SM120 patch is claimed; this FP8 configuration resolves MoE to Triton.

Resolved backends: Qwen3.8 Flash-Next

Component or phaseResolved implementationHow selected or enabledEvidence
Target GDN decodeFlashInferGDNKernelnarrow phase overridestartup dispatcher; 1x/4x decode
Target GDN prefillFlashInferGDNKernelnarrow phase override64K/490K prefill and needles
Native-MTP draft decodeFlashInferGDNKernelshared GDN dispatchdraft CUDA graphs and live decode
Native-MTP draft extendFlashInferGDNKernelshared GDN dispatchdraft extend graph capture
Active GDN target verificationFlashInfer WY output-onlylocal 280825c3e2, none mode onlydirect state parity and graph replay
Ordinary/tree state-writing verificationTritonGDNKernelarchitecture gate deliberately preservednon-none source dispatch and focused tests
Accepted-state recoveryFlashInfer WY output-onlynarrow SM120 RecoverSSM routerecovery graphs BS 1-4; long continuation
QSA sparse prefillTriton sparse GQAmodel path + FP8 tile fix 95da38fb3b64K/490K exact qualification
QSA sparse decodeFlashInfer QSA wrapper resolving to XQASM120 wrapper dispatch c1da0eef56, narrowed to exact SM120 by 8de07a058f; FlashInfer selects XQA on SM120direct backend probe and live decode
QSA top-ksgl-kernelautomaticstartup resolution
QSA MTP index sharingenabledmodel pathstartup line and shared-index tests
Target MoEFlashInfer CUTLASSautomatic ModelOpt-NVFP4 resolutionstartup resolution and live tests
Native-MTP MoEFlashInfer CUTLASSautomatic speculative resolutionstartup resolution and live tests
HyperConnection Mixpersistent Triton Mixautomatic SM120 fallbackHC numerical tests; FlashInfer gate retained
HyperConnection Combinefused SGLang CUDAQwen4 model pathkernel tests and full suite
Multimodal attentiontriton_attnautomaticfull 1,024-token vision validation
Sampling / grammarFlashInfer / XGrammarautomaticstartup log; reasoning and tool suite
HiCache transferNIXL POSIX, io_uring, O_DIRECTexplicit storage backend64K/490K restart restoration
Persistent representationpacked target/native-MTP KV + complete GDN/PLE siblings + compressed QSA keyslocal hybrid-pool integrationrestart restore, needles, continuation

SM120 enablement was scoped, not indiscriminate

Several upstream checks treated SM100 as the only eligible architecture even when an underlying kernel already compiled for SM120. This runtime distinguishes three cases:

  1. Explicit phase override. Automatic GDN selection used an SM100 helper and therefore did not select FlashInfer on SM120. FlashInfer 0.6.17 already supported the BF16 decode and prefill operations used here. The launcher selects only those phases with --linear-attn-decode-backend flashinfer and --linear-attn-prefill-backend flashinfer. Long prefill, exact needles, decode, and vision/reasoning qualification cover the resulting runtime.

  2. Narrow source integration. RecoverSSM needed FlashInfer WY output-only state output and accepted-state recovery. FlashInfer already contained an sm_120a implementation, but SGLang did not route SM120 into it. Commit 280825c3e2 enables only the output/recovery route used by gdn_mtp_cache_mode=none and preserves Qwen4 PLE accepted-state commit ordering. Direct tests cover all accepted lengths for four draft tokens, batch sizes 1-4, mixed acceptance, positions 63/64/65, extra_buffer, prefix restoration, retraction, long continuation, and captured-graph replay.

  3. QSA wrapper enabled, backend distinguished. Commit c1da0eef56 lets SM120 enter FlashInfer's page-aligned QSA decode wrapper, while 8de07a058f adopts upstream #36806's exact (12, 0) gate so SM121/GB10 is not admitted. On SM120 the wrapper resolves to XQA, an existing supported implementation; it does not select TRTLLM-Gen. No upstream SM100 throughput claim is attributed to Penny's SM120 results.

  4. Incompatible gates deliberately retained. Forced TRTLLM-Gen fails with Unsupported architecture. Bypassing the guard and loading the exact BF16-Q/FP8-KV/H256/P64 cubin directly returns CUDA_ERROR_NO_BINARY_FOR_GPU (209): the binary targets SM100 and contains the sm10x_tcgen05 instruction family unavailable on SM120. Supporting it would require kernel/compiler adaptation upstream of SGLang; see TensorRT-LLM #11799 and FlashInfer #3628. Ordinary FlashInfer state-writing GDN verification also remains gated and uses Triton, while FlashInfer HyperConnection Mix remains SM100-only and falls back to the qualified persistent Triton Mix.

Other bounded corrections follow the same rule. 0f159cd545 supplies XQA's packed mask for fixed-width DFlash2 verification rather than enabling a new global attention backend. 64ecd64924 extends the fused rotary kernel to real three-axis mRoPE rather than dropping the fused path or ignoring H/W positions.

Memory recovery and automatic KV sizing

Flash-Next configurationIntermediate SSMMamba slotsGPU KV capacity
BF16 before RecoverSSM1.05 GiB24745,600 tokens
RecoverSSM none mode024824,384 tokens

The sequence matters:

  1. BF16 reduced recurrent-state bytes per slot.
  2. Automatic Mamba sizing then expanded from 21 to 49 slots and consumed much of that saving.
  3. The workload needed far fewer slots; 24 remained above observed demand and returned the rest of the budget to KV.
  4. RecoverSSM removed the separate 1.05 GiB intermediate speculative SSM pool.
  5. With no forced KV-token count, the measured KV pool increased by 78,784 tokens—from 745,600 to 824,384, or 10.6%.

The physical pool is removed in 280825c3e2, but the current kv_cache_configurator.py::_handle_max_mamba_cache estimator only omits that reserve for ReplaySSM, not RecoverSSM none. There is no separate allocator correction commit in this runtime. The qualified launcher increases --mem-fraction-static from .97 to .981, approximately the recovered GPU fraction, so automatic KV sizing can consume the physically freed memory. The 824,384-token result was measured, not hard-coded, but the estimator debt is real and documented.

Performance and qualification

These rows are observations from different model configurations and are not a single A/B benchmark.

Flash-Next final campaign — source 64ecd64924

The published campaign below used lactd with the workstation card's fan curve active and this relevant power/clock profile:

power_cap: 450.0
min_core_clock: 210
max_core_clock: 2750
gpu_clock_offsets:
  0: 1000
mem_clock_offsets:
  0: 2000
TestResult
64K cold prefill10,103.70 tok/s
~490K cold prefill7,872.15 tok/s; 3/3 exact needles
1x 1,024-token decode171.09 tok/s
4x 1,024-token synchronized batch427.54 tok/s aggregate
MTP mean accepted length / rate2.58 / 52.74%
Reasoning97.49/100 across 139,863 completion tokens
Tools30/30 exact calls and semantically correct after review
Visioncomplete 1,024-token validation passed
Sealed agentic control148.80 tok/s
Natural 3,072-token decode162.05 tok/s

Per-stream post-first-token rates do not sum to the synchronized aggregate because each stream uses its own interval. The aggregate includes TTFT and the batch tail. These results were measured with QSA sparse decode resolving to XQA. No matched SM120 end-to-end A/B supports a percentage claim against another QSA backend.

Independent TP=2 FP8 validation

H3PO independently validated this runtime on a dual-GPU TP=2/EP=2 FP8 deployment with native MTP after removing the optional overlap-plan-stream setting. The raw third-party table, corpus description, capacity result, and scope limits are preserved in RESULTS.md.

Qwen3.8-27B/DFlash2 dated performance campaign

TestResult
64K prefill6,163.07 tok/s
489,921-token prefill1,618.31 tok/s; 3/3 exact needles
1x 1,024-token decode108.75 tok/s after first token
4x 1,024-token decode390.23 tok/s aggregate
Reasoning, xhigh / medium98.26 / 95.807
Medium tool suite30/30 tool selections and arguments; 29/30 reviewed response discipline

The cited public TP1 official-FP8/MTP3 community capture is directional rather than a strict A/B because checkpoint, runtime, speculation, power, harness, output duration, and cache configuration differ.

The current 24-slot/five-state confirmation retained exact long-context needles, reached a 96.92 reasoning score across 50,986 completion tokens, and used at most 10 of 24 Mamba entries.

27B real agentic context behavior

The dated 124-request sample covered 85,156 output tokens and inputs from 183 to 350,195 tokens. RESULTS.md preserves the context-band tables, overlap treatment, and distinction between completed-request and instantaneous telemetry measurements.

Flash-Next real agentic context behavior

A separate decontaminated 96-request window covered 100,666 output tokens. RESULTS.md preserves its context-band and aggregate tables. The first sample after a large prefill was excluded because its telemetry interval mixed prefill or idle time with decode.

Detailed definitions, complete 27B context bands, both 27B campaigns, and persistence evidence are in RESULTS.md.

HiCache/NIXL persistence

HiCache/NIXL does not cause GPU-resident decode speed. It provides disposable, reusable prefix state across GPU/host eviction and service restart:

GPU radix state
  -> page-first HiCache host RAM, kernel I/O, write-through
  -> NIXL POSIX FILE storage, io_uring + O_DIRECT

Flash-Next restart evidence:

  • 63,808 of 63,864 input tokens restored; 56 recomputed.
  • 489,856 of 489,879 restored; 23 recomputed.
  • all three needles exact after restart.

The earlier 27B work also demonstrated 518,528 restored tokens with a six-token tail in 14.64 seconds, 60,032-token namespace reuse after restart, A→B→A page- size namespace rollback, three concurrent ~60K restores, and a 775,168-token three-request concurrent restore with only 320 tail/page-rounding tokens computed.

Two portable NIXL fixes from this project remain open upstream: PR #36520 isolates overlapping path registrations, and PR #36524 bounds bounce-backed hybrid transfers. Flash-Next adds complete PLE/GDN/QSA sibling-state persistence and load/COW ordering. MEMORY-AND-PERSISTENCE.md documents the representation namespace and actual failure boundaries.

Build and launch

There is one native build procedure and exactly two canonical launch recipes:

uv python install 3.12.13
uv venv --python 3.12.13 .venv
source .venv/bin/activate

export CUDA_HOME=/usr/local/cuda
export CC=/usr/bin/gcc-15 CXX=/usr/bin/g++-15 CUDAHOSTCXX=/usr/bin/g++-15
export MAX_JOBS=24 CMAKE_BUILD_PARALLEL_LEVEL=24
export FLASHINFER_NINJA_JOBS=24 FLASHINFER_NVCC_THREADS=4
export TORCHINDUCTOR_COMPILE_THREADS=24

uv pip install --prerelease=allow --index-strategy unsafe-best-match \
  --extra-index-url https://docs.sglang.ai/whl/cu130/ \
  --no-build-isolation -e python

Set REPO_ROOT, CACHE_BASE, NIXL_STORAGE_BASE, and the checkpoint paths, then choose one recipe:

configs/pennyroyal/serve-qwen38-27b-dflash2.sh
configs/pennyroyal/serve-flash-next.sh

Do not run them simultaneously on one GPU. BUILD.md records exact dependencies and RUN.md provides startup assertions, ordinary OpenAI-compatible smoke requests, and cold/radix/NIXL cache distinctions.

Source changes and upstream work

The cumulative history starts with the 2026-08-24 27B release, then layers the unified runtime and Flash-Next work on the same source line. The current active stack contains 24 commits above its integration base. Major groups are:

  • Qwen3.8-27B/DFlash2: independent target/draft overrides, fixed-width XQA mask, NVCC host-compiler identity, request-span observability, and NIXL correctness.
  • Flash-Next: Qwen4 model support, QSA/HC/PLE/native-MTP integration, SM120 QSA decode, FP8 QSA prefill, RecoverSSM, complete hybrid persistence, and mRoPE.
  • v2.1 upstream sync: exact-SM120 QSA routing from #36806 and the Mamba radix ghost-node/speculative tracking correction from #35821, adapted to Penny's fused CUDA and KDA accepted-state paths.
  • v2.1.1 maintenance: accumulated additive sampling penalties are applied correctly during 27B DFlash2 verification; shared HiCache JIT transfers are bound to their torch copy streams and load-back waits for in-flight forward writes for both supported models.
  • Open project PRs: #36520, #36524, and #35584.
  • Closed project submissions retained in runtime history: #35583; transient ragged/DSpARK PR #35586 is documented but not in the active source.
  • Related upstream work: #30967, #35371, #35496, #35744, #35821, #36497, #36644, and #36806.

CHANGES.md lists every material current commit, the earlier dated release hashes, exact PR links/status/heads, affected execution paths, and test coverage.

Scope and limitations

  • One RTX PRO 6000, TP=1, exact checkpoint families, and the recorded CUDA, PyTorch, FlashInfer, compiler, NIXL, and SGLang source.
  • SM120 paths were qualified narrowly; unsupported-by-default is not treated as proof of incompatibility, but no architecture gate was globally deleted.
  • Benchmark observations are not guarantees for another system.
  • Flash-Next and 27B results remain separate; neither model's features or numbers are silently attributed to the other.
  • The full published Flash-Next reasoning/tool/vision campaign ran at 64ecd64924. The v2.1.1 source at fb1216c6c4 received focused CPU/GPU DFlash, HiCache, hybrid/NIXL, and unified-load-back tests plus ordinary 64K/490K/1K/C4 and post-restart NIXL restoration on both supported models. The full reasoning and tool suites were not rerun for this narrow update.
  • NIXL cleaner thresholds are whole-filesystem occupancy percentages, not an absolute directory byte quota.

See LIMITATIONS.md for measurement and reproducibility detail.

Documentation map

Engineering history

The experimental path—including DFlash2 work and the HiCache/Mooncake/NIXL detour—is described at msoexpert.com. Mooncake is not a fallback in this runtime; it was rejected and removed.

License

The SGLang-derived source remains under Apache-2.0. Model checkpoints and third-party runtimes retain their own licenses.