[CUDA] Add NVFP4 native FP4xFP4 prefill for QMoE on SM120 - #29824
Merged
Merged
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
Adds a native Blackwell (SM120+) NVFP4 QMoE FP4×FP4 block-scaled grouped-GEMM prefill path (with per-call routing between native/GEMV/dequant fallback), and updates CUDA build arch filtering to ensure SM120 has a loadable image (avoiding CUDA error 209). Updates tests and docs to reflect the new routing/accuracy characteristics and adds build/CI guidance.
Changes:
- Enable NVFP4 native FP4×FP4 CUTLASS prefill on SM120+ with routing knobs (
ORT_ENABLE_NVFP4_CUTLASS_GEMM,ORT_FP4_PREFILL_MIN_TOKENS,ORT_FP4_NATIVE_MAX_TOKENS_PER_EXPERT) and dense A16 fallback runner. - Add FP4×FP4 grouped-GEMM template instantiations/TUs and wire NVFP4 block scales through
QuantParams::FP4. - Update Python parity tests and CUDA/MoE QMoE documentation; adjust CUDA arch filtering to build native
sm_120aSASS on Linux while keeping MSVC constraints.
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| onnxruntime/test/python/transformers/test_qmoe_nvfp4_cuda.py | Adjust parity tolerances for native-prefill routing; add negative-model guards and GEMV-vs-fallback parity test. |
| onnxruntime/contrib_ops/cuda/moe/moe_quantization.h | Add NVFP4-native state toggles and dense fallback runner members. |
| onnxruntime/contrib_ops/cuda/moe/moe_quantization.cc | Implement NVFP4 SM120+ native FP4×FP4 runner + routing; plumb env vars; wire NVFP4 scales into QuantParams::FP4; update prepack logic. |
| onnxruntime/contrib_ops/cuda/llm/moe_gemm/moe_kernels.cu | Wire NVFP4 quant_params.fp4 stride setup and explicitly instantiate FP4×FP4 runner variants. |
| onnxruntime/contrib_ops/cuda/llm/moe_gemm/moe_gemm_kernels_fp4_fp4.cu | New TU for FP4×FP4 grouped-GEMM template instantiations (NVFP4 native path). |
| docs/OperatorKernels.md | Update QMoE type constraints to include NVFP4 scale tensor type (float8e4m3fn). |
| docs/ContribOperators.md | Document quant_type='nvfp4' and its required scale/global-scale inputs and types. |
| docs/contrib_ops/cuda/moe_qmoe.md | Document NVFP4 native prefill routing/accuracy and SM120 build/arch gotchas. |
| cmake/onnxruntime_providers_cuda.cmake | Adjust LLM object library arch filtering to include 120-real on Linux/non-MSVC and when FP4 QMoE requires real SM120 SASS. |
| cmake/onnxruntime_cuda_source_filters.cmake | Add new FP4×FP4 TU to FP4-QMoE filtering rules. |
| .agents/skills/ort-ci/SKILL.md | Clarify CI re-run guidance and doc-artifact download workflow. |
kunal-vaishnavi
approved these changes
Jul 24, 2026
This was referenced Aug 12, 2026
This was referenced Aug 20, 2026
Closed
This was referenced Aug 27, 2026
This was referenced Sep 3, 2026
This was referenced Sep 10, 2026
Open
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.
Description
Adds a native block-scaled FP4×FP4 (W4A4) grouped-GEMM prefill path for the
nvfp4QMoEquantization mode on Blackwell (SM120+). Previously
nvfp4always dequantized E2M1 weights toFP16/BF16 and ran the dense A16 MoE runner; now prefill shapes route through the native CUTLASS
block-scaled tensor-op, while decode/small-M shapes stay on the fused GEMV / dequant fallback. Also
fixes the CUDA
no kernel image(error 209) failure on SM120 by making the LLM object library buildnative
sm_120aSASS on Linux.Summary of Changes
Native NVFP4 FP4×FP4 prefill (QMoE)
onnxruntime/contrib_ops/cuda/moe/moe_quantization.ccQuantParams::FP4; route prefill (num_rows >= ORT_FP4_PREFILL_MIN_TOKENS) to native and decode to GEMV/fallback; profile thekFP4tactic for native prefill. Replaces manualgetenvparsing withParseEnvironmentVariableWithDefault.onnxruntime/contrib_ops/cuda/moe/moe_quantization.henable_nvfp4_cutlass_gemm_,fp4_prefill_min_tokens_,fp4_native_max_tokens_per_expert_, dense fallback runner).onnxruntime/contrib_ops/cuda/llm/moe_gemm/moe_gemm_kernels_fp4_fp4.cuonnxruntime/contrib_ops/cuda/llm/moe_gemm/moe_kernels.cuBuild / SM120 native SASS
cmake/onnxruntime_providers_cuda.cmakeEXCLUDE_SM120_REALon the LLM object library: Linux now builds nativesm_120aSASS (fixes CUDA error 209 on real-only arch lists); MSVC keeps the virtualcompute_120PTX to dodge the CCCLtcgen05host-compile failure;USE_FP4_QMOEkeeps120-realeverywhere.cmake/onnxruntime_cuda_source_filters.cmakeRouting controls (environment variables)
ORT_ENABLE_NVFP4_CUTLASS_GEMM(default 1) — master switch for the native NVFP4 path.ORT_FP4_PREFILL_MIN_TOKENS(default 64) — prefill/decode routing threshold.ORT_FP4_NATIVE_MAX_TOKENS_PER_EXPERT(default 0 = no bound) — upper bound above which prefill uses the dense A16 fallback.Tests & docs
onnxruntime/test/python/transformers/test_qmoe_nvfp4_cuda.pydocs/contrib_ops/cuda/moe_qmoe.mdTesting
CUDA_VISIBLE_DEVICES=0 python -m pytest onnxruntime/test/python/transformers/test_qmoe_nvfp4_cuda.py→ 18/18 pass on RTX 5060 Ti (SM120). Native-routed shapes (tokens 64/128) showmax_diff ≈ 0.197; decode/GEMV shapes are near-exact.ORT_FP4_PREFILL_MIN_TOKENS=100000dropsmax_diffto ≈1e-3, confirming the ~0.2 error is legitimate W4A4 activation quantization, not a kernel bug.test_moe_cuda.py,test_qmoe_cuda.py,test_qmoe_fp4_cuda.py).Motivation and Context
Finish remaining works of #29697.
nvfp4QMoE previously had no native execution path, so all shapes paid the dequant-to-A16 cost.This PR enables the Blackwell block-scaled FP4×FP4 tensor-op for prefill while keeping the
latency-sensitive decode path on the fused GEMV, and resolves the SM120
no kernel image(CUDA 209)failure that occurred when the LLM object library shipped no loadable SM120 image.
Checklist
ORT_ENABLE_NVFP4_CUTLASS_GEMM=0)