[Qwen4-Exp] Load nvidia/Qwen3.8-Flash-Next-NVFP4 (ModelOpt MIXED_PRECISION) on qwen4-main-squashed - #38121
Merged
Qiaolin-Yu merged 4 commits intoSep 5, 2026
Conversation
Jiminator
marked this pull request as ready for review
September 5, 2026 11:23
Jiminator
requested review from
Alisehen,
AniZpZ,
BBuf,
Edwardf0t1,
FlamingoPg,
HaiShaw,
OrangeRedeng,
Ying1123,
alphabetc1,
b8zhong,
ch-wan,
hanming-lu,
hnyls2002,
huangtingwei9988,
hzh0425,
ispobock,
merrymercy,
mmangkad,
xiezhq-hermann and
yizhang2077
as code owners
September 5, 2026 11:23
…PLE and fp8 MTP nvidia/Qwen3.8-Flash-Next-NVFP4 is exported by ModelOpt as MIXED_PRECISION: routed experts NVFP4, the PLE n-gram table FP8 (shard_N.weight + weight_scale), MTP experts FP8_BLOCK_SCALES (weight_scale_inv), quantized_layers keyed model.language_model.* and no text_config.ple_embedding_dtype. Four things kept it from loading on this branch: - ModelOptMixedPrecisionConfig could not match model.language_model.* keys to the model.* prefixes Qwen4-Exp modules use, and iterated exclude_modules=None. - Qwen4ExpNGramEmbedding only picked fp8 storage for an fp8 checkpoint or an explicit ple_embedding_dtype, so the fp8 shards hit the offload auto-switch ValueError; it now resolves the table's quant_algo from the mixed config. - The sm100 Qwen MoE override skipped modelopt_mixed, leaving the runner on auto; ModelOptNvFp4FusedMoEMethod then resolved trtllm at run time but had enable_flashinfer_trtllm_moe=False and raised Unsupported moe_runner_backend. - _mtp_quant_config dropped the mixed config for the MTP head, and the mixed config had no FP8_BLOCK_SCALES mapping; both now route the MTP experts to the 128x128 block Fp8MoEMethod. Ported from #37752 (base qwen4-main-squashed-rebased) onto qwen4-main-squashed: - The sm100 Qwen MoE runner override lives inline in arg_groups/overrides.py on this branch (model_overrides/qwen3_moe.py does not exist here yet). - This branch's ModelOptMixedPrecisionConfig has no fp8_pb_wo_config, so a 128x128 block Fp8Config (fp8_block_config) is added for FP8_BLOCK_SCALES. - Comments trimmed. (cherry picked from commit 7bc5bec)
…stub test - qwen3_moe override: only default modelopt_mixed to flashinfer_trtllm when the mixed config's expert layers are NVFP4/FP8; W4A16_NVFP4 experts go to marlin (or reject an explicit non-marlin runner), mirroring the Nemotron override. - test_shared_experts_fusion_gates: the modelopt_mixed stub now carries quantized_layers; add the positive mtp.* case. Ported from #37752 onto qwen4-main-squashed: the override and its test target arg_groups/overrides.py instead of model_overrides/qwen3_moe.py. (cherry picked from commit 4369675)
The MTP head of nvidia/Qwen3.8-Flash-Next-NVFP4 quantizes its experts
FP8_BLOCK_SCALES, so it goes through Fp8MoEMethod while the target's NVFP4
experts go through ModelOptNvFp4FusedMoEMethod. The MoE runner backend is
global: on sm100 the Qwen override picks flashinfer_trtllm, which
Fp8MoEMethod supports, but sm120 (RTX PRO 6000) has no trtllm-gen and pins
--moe-runner-backend flashinfer_cutlass for the NVFP4 experts, a backend
for which Fp8MoEMethod.create_moe_runner created no runner at all:
AttributeError: 'Fp8MoEMethod' object has no attribute 'runner'
(Fp8MoEMethod.apply, during the draft CUDA-graph warmup)
Resolve flashinfer_cutlass / flashinfer_cutedsl to triton for fp8 experts
instead of falling through the unhandled branch. The unit test covers both
backends and the triton pass-through.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V5B2WK8ciABmJ8pMBtGcgN
Jiminator
force-pushed
the
qwen38-flash-next-nvidia-mixed-squashed
branch
from
September 5, 2026 11:32
99567a6 to
81f5ae2
Compare
Qiaolin-Yu
approved these changes
Sep 5, 2026
Merged
5 tasks
Jiminator
pushed a commit
that referenced
this pull request
Sep 6, 2026
…lash-Next-NVFP4 Relabel the RadixArk NVFP4 option as NVFP4 (RDXA) and add NVFP4 (NVDA) with two in-progress 2x DGX Spark TP=2 cells (they need the ModelOpt MIXED_PRECISION loader from #38121, not yet in the qwen38flashnext image): low latency with the MTP draft read from the RadixArk export (this export's fp8 block-scaled MTP experts cannot be TP-sharded), high throughput without MTP; explicit flashinfer_cutlass MoE runner. Add ISL 1024 / OSL 256 speed rows for all four DGX Spark cells. Verified on qwen4-main-squashed @ 9b2aee2: GSM8K 97.5% / 97.5%. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Jiminator
pushed a commit
that referenced
this pull request
Sep 6, 2026
nvidia/Qwen3.8-Flash-Next-NVFP4 on a single RTX PRO 6000 (SM120, 96 GB), TP=1, verified on the qwen4-main-squashed tip 9b2aee2 (#38121 merged; the qwen38flashnext image does not carry the loader yet, so both cells are in-progress like the Spark NVDA cells). Same shape and pools as the RDXA cells: PLE table pinned in host RAM, extra_buffer_lazy + skip-decode-lock, bf16 SSM state, 16 requests with MTP at 0.96 and 64 without at 0.93. Differences from the RDXA cells: no --quantization (resolves to modelopt_mixed), no --mamba-track-interval (not on qwen4-main-squashed), and low latency keeps the in-checkpoint fp8 MTP head. At TP=1 it needs no sharding and #38121 runs it on triton under the flashinfer_cutlass pin; the RadixArk BF16 draft measured the same on this card (accept 3.33 vs 3.31, TPOT 18.5 vs 19.1 ms at 16), so the single-checkpoint command stays. Measured (1024-in/256-out random; chat GSM8K, thinking off, n=200): with MTP 6.1 ms TPOT at 1 request, 19.1 ms / 628 tok/s at 16, accept 3.3, GSM8K 96.5% (97.5% on an earlier run); without MTP 11.5 ms at 1, 55.8 ms / 879 tok/s at 64, GSM8K 97.0%. Peak memory leaves 2.6 GB / 4.0 GB. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01V5B2WK8ciABmJ8pMBtGcgN
Jiminator
pushed a commit
that referenced
this pull request
Sep 6, 2026
Both cells were measured on the qwen4-main-squashed tip (9b2aee2, #38121 merged), which is the branch the page's Python install path builds; the note now says the qwen38flashnext image predates the loader instead of implying the recipe is unverified. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Jiminator
pushed a commit
that referenced
this pull request
Sep 6, 2026
…-next-local image lmsysorg/sglang:dev-qwen38-next-local is the qwen4-main-squashed build (9b2aee2: the #38121 ModelOpt MIXED_PRECISION loader and the file-backed PLE table backend). None of the DGX Spark or RTX PRO 6000 recipes run on the qwen38flashnext image, so the command generator now picks the new image for those two hardware rows; the datacenter rows keep qwen38flashnext. - Docker tab: the qwen38flashnext pull stays for H200 / B200 / B300 / GB300; a second pull for DGX Spark and RTX PRO 6000 is added next to it. - Every Spark and RTX cell's warning banner names the image to use. - Spark NCCL note: the new image ships NCCL 2.29.7 (pip) over a system 2.28.3, below the 2.30.7 the cross-node decode graphs need; say so and how to upgrade it in the container. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01V5B2WK8ciABmJ8pMBtGcgN
Jiminator
pushed a commit
that referenced
this pull request
Sep 6, 2026
Wording only, no flag or number changes. Drops the em-dash clusters and decorative bold in the two notes accordions and the Docker tab, and fixes two claims that had gone stale or were too strong: - "None of the DGX Spark or RTX PRO 6000 recipes run on the qwen38flashnext image" was not true of the RadixArk cells (the 2x Spark ones were verified on it, the RTX ones first passed on it). The Docker tab and the cell warnings now say what is true: that image predates the loaders the NVIDIA export (#38121) and the file-backed table (#37068) need, so the Spark and RTX rows are generated for dev-qwen38-next-local. - The PLE Offload chip reason for DGX Spark still said "Off is the verified setting until NVMe-backed PLE lands"; it landed, and the single-Spark cells use On (NVMe file). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01V5B2WK8ciABmJ8pMBtGcgN
4 tasks
Jiminator
pushed a commit
to Jiminator/sglang
that referenced
this pull request
Sep 8, 2026
Restore the original sgl-project#38121/sgl-project#37752 MTP and sm100 runner gates, which are still absent from main. Deployment testing found that dropping the mixed MTP config loads FP8 expert values without their intended quantization method and reduces draft acceptance. Co-authored-by: Yangmin Li <yangminl@nvidia.com>
5 tasks
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.
Motivation
#37752 makes
nvidia/Qwen3.8-Flash-Next-NVFP4load, but it is stacked on #37500 (qwen4-main-squashed-rebased). This PR is the same change rebased ontoqwen4-main-squashed(#36497). The two #37752 commits are cherry-picked with their original authorship; the port notes are in the commit messages and repeated below.#36845 and #36806 needed no rebase: both were merged straight into
qwen4-main-squashedand are its two tip commits (99c9362e66,78c5024e9d).The NVIDIA export (revision
fab0aecb) is a ModelOpt MIXED_PRECISION checkpoint.RadixArk/Qwen3.8-Flash-Next-NVFP4is not.quantized_layers["model.language_model.layers.N.mlp.experts"]quantized_layers["model.language_model.layers.1.ple.ple_embedding.ngram_embedding"], 128 fp8shard_N.weight+weight_scalequantized_layers["mtp.layers.0.mlp.experts"],weight_scale_invignorelistconfig.jsoncarriesquantization_config(quant_method: modelopt,quant_algo: MIXED_PRECISION) and notext_config.ple_embedding_dtype. Onqwen4-main-squashedthe server dies while loading weights:With
--no-ple-offload-embeddingit dies at CUDA-graph capture instead:Modifications
Commits 1 and 2 are #37752:
ModelOptMixedPrecisionConfig: resolvemodel.language_model.*keys against themodel.*prefixes Qwen4-Exp modules use; defaultexclude_modulesto[]; mapFP8_BLOCK_SCALESto the 128x128 blockFp8LinearMethod/Fp8MoEMethod; exposeresolve_quant_algo().Qwen4ExpNGramEmbedding: use fp8 table storage when the mixed config marks the ngram table FP8, so the pinned-host offload path sees fp8 storage up front.modelopt_mixedtoflashinfer_trtllmon sm100 when the expert layers are NVFP4/FP8; routeW4A16_NVFP4experts to marlin, or reject an explicit non-marlin runner._mtp_quant_config: keep the mixed config for the MTP head when it listsmtp.*layers.Port differences, forced by what
qwen4-main-squashedhas:python/sglang/srt/arg_groups/overrides.py(this branch has noarg_groups/model_overrides/qwen3_moe.py), so the change and its test target that file.ModelOptMixedPrecisionConfighas nofp8_pb_wo_confighere, so a 128x128 blockFp8Configis added asfp8_block_configand onlyFP8_BLOCK_SCALESmaps to it.patch.object(overrides_module, "is_sm100_supported", ...), the idiom this branch's test file already uses.Commits 3 and 4 came out of validating on 1x RTX PRO 6000 (sm120). They are separate so either can be dropped or moved:
Fp8MoEMethod.create_moe_runnerresolvesflashinfer_cutlass/flashinfer_cutedslto triton. The MoE runner backend is global. sm120 has no trtllm-gen, so NVFP4 experts need--moe-runner-backend flashinfer_cutlass, and for that backendFp8MoEMethodcreated no runner at all; the FP8_BLOCK_SCALES MTP head then died in the draft CUDA-graph warmup withAttributeError: 'Fp8MoEMethod' object has no attribute 'runner'. On sm100 the override picksflashinfer_trtllm, whichFp8MoEMethodsupports, so [Qwen4-Exp] Load nvidia/Qwen3.8-Flash-Next-NVFP4 (ModelOpt MIXED_PRECISION: NVFP4 experts, fp8 PLE, fp8 MTP) #37752 never hit this. Unit test:test/registered/unit/layers/quantization/test_fp8_moe_runner_fallback.py.gc.collect()before profiling the KV budget).qwen4-main-squashedpredates it. Without it, loader temporaries still referenced at profiling time understate free memory by about 6 GiB on a 96 GB card, and the pinned mamba pool plus KV no longer fit (Loaded weights leave no GPU memory for the KV cache under --mem-fraction-static=0.93). This is not specific to the checkpoint. Drop it here if the base branch picks it up from main.Accuracy Tests
1x RTX PRO 6000 Blackwell (96 GB, sm120), TP1,
lmsysorg/sglang:qwen38flashnextwith this branch overlaid (sglang-kernel 0.4.6.post1matches this branch's pin; the image ships flashinfer 0.6.18, the branch pins 0.6.17). GSM8K is the chat endpoint, 200 questions, thinking off, greedy,max_tokens=1024, at 64 concurrent requests (no MTP) or 16 (MTP).Common flags:
--fp4-gemm-backend flashinfer_cutlass --moe-runner-backend flashinfer_cutlass --ple-offload-embedding --page-size 64 --chunked-prefill-size 4096 --context-length 262144 --mamba-radix-cache-strategy extra_buffer_lazy --mamba-ssm-dtype bfloat16 --reasoning-parser qwen3, envSGLANG_OPT_MAMBA_SKIP_DECODE_LOCK=1, no--quantization(resolved from the checkpoint). No MTP adds--max-running-requests 64 --max-mamba-cache-size 192 --mem-fraction-static 0.93. MTP adds--speculative-algorithm NEXTN --speculative-num-steps 3 --speculative-eagle-topk 1 --speculative-num-draft-tokens 4 --max-running-requests 16 --max-mamba-cache-size 48 --mem-fraction-static 0.96.Both boots log
quant=modelopt_mixed, quant_algo=MIXED_PRECISION, keep 81.35 GB of weights on the GPU with the fp8 ngram table pinned in host RAM (scheduler RSS about 71 GB), and resolve the linear-attention kernels to triton. The MTP boot logsFp8MoEMethod has no FLASHINFER_CUTLASS path; using triton for its fp8 experts.Pools: no MTP has 192 mamba slots (10.58 GB) and a 97,600-token KV pool, with 5.25 GB free after graph capture and 4.0 GB left at peak; MTP has 48 slots, 3.59 GB of intermediate SSM state and a 169,664-token KV pool, with 4.12 GB free after capture and 2.9 GB left at peak. Neither server log has an error.Unit tests in the same container, plus
pre-commit run --files <changed files>, all pass:Speed Tests and Profiling
bench_serving --backend sglang-oai --dataset-name random --random-input-len 1024 --random-output-len 256 --random-range-ratio 1 --request-rate inf --flush-cache, same servers as above:RadixArk/Qwen3.8-Flash-Next-NVFP4on theqwen4-main-squashed-rebasedimage with the same flags (#37995) measured GSM8K 97.0-97.5 and TPOT 5.8-5.9 ms at concurrency 1 with MTP, and GSM8K 97.0-98.0 and 856-861 tok/s at 64 without. The NVIDIA export lands in the same place.Checklist
🤖 Generated with Claude Code
https://claude.ai/code/session_01V5B2WK8ciABmJ8pMBtGcgN
CI States
Latest PR Test (Base): ❌ Run #33963603943
Latest PR Test (Extra): ❌ Run #33963603948
Latest PR Test (AMD ROCm 7.2): ❌ Run #33963604062