You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
NVFP4 MoE on SM120 (RTX PRO 6000 Blackwell): Full Debug Report
Title
CUTLASS & FlashInfer NVFP4 MoE Grouped GEMM Fails on SM120 Desktop Blackwell GPUs — Debug Journey, Patches, and Benchmark Results
All native FP4 MoE backends produce garbage output or crash on SM120 (compute_120) due to broken CUTLASS grouped GEMM templates. Through systematic patching of FlashInfer 0.6.5's SM120 capability checks and CuTe DSL architecture restrictions, we achieved the first known correct native FP4 MoE output on desktop Blackwell — albeit at reduced speed (14.6 tok/s vs Marlin's 46-49 tok/s) due to FlashInfer autotuner falling back to slow kernel tactics after TMA WS grouped GEMM initialization failures.
4.2.1 (vendored in vLLM), 4.4.1 (tested separately)
Model
Parameter
Value
Model
nvidia/Qwen3.5-397B-A17B-NVFP4
Total Params
397B (17B active per token)
Experts
512 routed + 1 shared, 10 routed per token
Quantization
NVFP4 (FP4 weights with FP8 block scales)
Parallelism
TP=2 + PP=2 (optimal for PCIe)
KV Cache
FP8 e4m3
Max Seq Len
32,768
The Problem
NVFP4 MoE models produce garbage output (random whitespace, commas, fragments) on SM120 desktop Blackwell GPUs when using any backend that relies on CUTLASS grouped block-scaled FP4 GEMM kernels. Dense (non-MoE) FP4 GEMM works correctly — the issue is specifically in the grouped GEMM path used by MoE expert computations.
Symptom
Prompt: "What is the capital of Kentucky?"
Output: " , , (!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
The model loads, serves requests, and generates tokens — but the MoE expert GEMM produces numerically wrong results, leading to incoherent output.
What We Tried (Chronological)
Phase 1: CUDA Kernel-Level Fixes (vLLM Source Rebuilds)
1. GDC (Grid Dependency Control) Barriers
Hypothesis: Missing PDL synchronization barriers in CUTLASS grouped GEMM
Action: Added -DCUTLASS_ENABLE_GDC_FOR_SM100=1 to CMakeLists.txt
Finding: The flag was silently ignored! compute_120 (without a) doesn't define __CUDA_ARCH_FEAT_SM120_ALL, so the #ifndef CUTLASS_GDC_ENABLED guard evaluated to false
Fix: Added -DCUTLASS_GDC_ENABLED directly as a compiler flag
Result: GDC barriers now compiled as real PTX instructions (griddepcontrol.wait/launch), but still garbage output
2. FP32 Amax Computation
Hypothesis: Half-precision amax in cvt_warp_fp16_to_fp4 causing quantization errors on SM120
Action: Patched nvfp4_utils.cuh to compute per-block amax entirely in FP32 (fabsf/fmaxf instead of __habs2/__hmax2)
Result: Still garbage. Scale computation was already FP32; the half-precision amax wasn't the root cause.
3. Pingpong Kernel Schedule
Hypothesis: Cooperative schedule buggy on SM120, Pingpong might work
Action: Changed SM120 GEMM from KernelScheduleAuto to KernelPtrArrayTmaWarpSpecializedPingpong
Result: SEGFAULT. Pingpong schedule crashes on SM120.
Action: Cloned CUTLASS 4.4.1, set VLLM_CUTLASS_SRC_DIR, rebuilt _C.abi3.so
Critical Bug: First clone attempt silently got 4.2.1 due to CMake's FetchContent_Declare overwriting our clone with hardcoded GIT_TAG v4.2.1. Fixed by using VLLM_CUTLASS_SRC_DIR env var.
Result: Still garbage. CUTLASS 4.4.1 has the same broken SM120 grouped block-scaled GEMM templates.
Phase 2: Alternative MoE Backends (FlashInfer)
vLLM supports 5 MoE backends for NVFP4:
VLLM_CUTLASS (default) — broken on SM120
FLASHINFER_TRTLLM — blocked by SM100-only capability checks
FLASHINFER_CUTLASS — blocked by SM120 capability checks + missing sm_120a in CuTe DSL
FLASHINFER_CUTEDSL — blocked by SM100-only capability checks
# Changed: major >= 9 adds "a" suffix (generates compute_120a which is needed for CUTLASS MMA)# SM120 needs "a" suffix for MMA instructions, but not "f" (CUDA 13.0+ only)
FlashInfer's autotuner logs reveal the root cause:
flashinfer.jit: [Autotuner]: Skipping tactic <MoERunner> 14, due to failure:
[TensorRT-LLM][ERROR] Failed to initialize cutlass TMA WS grouped gemm.
Error: Error Internal (cutlass_kernel_file_gemm_grouped_sm120_M128_BS_group2.generated.cu:60)
All TMA warp-specialized grouped GEMM tactics fail to initialize on SM120 with compute_120a. The autotuner falls back to slower, non-TMA tactics. This is a CUTLASS template-level issue where SM120's TMA grouped GEMM doesn't work with the a suffix — it likely requires the f suffix (compute_120f) which is only available with CUDA 13.0+.
Key Technical Findings
1. compute_120 vs compute_120a vs compute_120f
Flag
CUDA Version
MMA Instructions
CUTLASS Grouped GEMM
Result
compute_120
12.8+
Not enabled
"Arch conditional MMA" error
Fails
compute_120a
12.8+
Enabled
TMA WS tactics fail, slow fallback
14.6 tok/s
compute_120f
13.0+ only
Full feature set
Potentially fast tactics
Testing
2. SM120 Desktop is NOT SM100 Compatible
Despite sharing the "Blackwell" brand, SM120 (desktop) and SM100 (datacenter) have different:
Compute capability families (12 vs 10)
Supported architecture features (a vs f suffix)
Pre-compiled cubin compatibility (SM100 cubins crash on SM120)
3. The Broken Chain
vLLM CUTLASS grouped GEMM → garbage output (kernel correctness bug)
↓ upgrade CUTLASS 4.4.1
Still garbage (same templates, 0 SM120 changes)
↓ try FlashInfer CUTLASS
Blocked: SM120 not in capability checks
↓ patch 10+ files
Works with correct output, but slow (autotuner fallback)
↓ try FlashInfer TRT-LLM
Crash: hardcoded SM==10 in C++ + SM100-only cubins
↓ next: compute_120f with CUDA 13.0
Pending...
BREAKTHROUGH: compute_120f with CUDA 13.0
A DGX Spark (SM121) user achieved 35 tok/s with FlashInfer CUTLASS using 12.1f (CUDA 13.0). The f suffix enables the "full" SM120 feature set with working TMA WS grouped GEMM tactics.
Results: compute_120f Nearly Triples Speed
Metric
compute_120a (CUDA 12.8)
compute_120f (CUDA 13.0)
Marlin W4A16
Single user
14.6 tok/s
39.0 tok/s
46-49 tok/s
4-user concurrent
6.9 tok/s/user
18.2 tok/s/user
~37 tok/s/user
compute_120f enabled the fast TMA WS grouped GEMM tactics that failed with compute_120a. This confirms the f suffix is the correct architecture designation for SM120 desktop Blackwell GPUs.
NVFP4 MoE on SM120 (RTX PRO 6000 Blackwell): Full Debug Report
Title
CUTLASS & FlashInfer NVFP4 MoE Grouped GEMM Fails on SM120 Desktop Blackwell GPUs — Debug Journey, Patches, and Benchmark Results
All native FP4 MoE backends produce garbage output or crash on SM120 (
compute_120) due to broken CUTLASS grouped GEMM templates. Through systematic patching of FlashInfer 0.6.5's SM120 capability checks and CuTe DSL architecture restrictions, we achieved the first known correct native FP4 MoE output on desktop Blackwell — albeit at reduced speed (14.6 tok/s vs Marlin's 46-49 tok/s) due to FlashInfer autotuner falling back to slow kernel tactics after TMA WS grouped GEMM initialization failures.Environment
sm_120, NOTsm_120a)Model
nvidia/Qwen3.5-397B-A17B-NVFP4The Problem
NVFP4 MoE models produce garbage output (random whitespace, commas, fragments) on SM120 desktop Blackwell GPUs when using any backend that relies on CUTLASS grouped block-scaled FP4 GEMM kernels. Dense (non-MoE) FP4 GEMM works correctly — the issue is specifically in the grouped GEMM path used by MoE expert computations.
Symptom
The model loads, serves requests, and generates tokens — but the MoE expert GEMM produces numerically wrong results, leading to incoherent output.
What We Tried (Chronological)
Phase 1: CUDA Kernel-Level Fixes (vLLM Source Rebuilds)
1. GDC (Grid Dependency Control) Barriers
-DCUTLASS_ENABLE_GDC_FOR_SM100=1to CMakeLists.txtcompute_120(withouta) doesn't define__CUDA_ARCH_FEAT_SM120_ALL, so the#ifndef CUTLASS_GDC_ENABLEDguard evaluated to false-DCUTLASS_GDC_ENABLEDdirectly as a compiler flaggriddepcontrol.wait/launch), but still garbage output2. FP32 Amax Computation
cvt_warp_fp16_to_fp4causing quantization errors on SM120nvfp4_utils.cuhto compute per-block amax entirely in FP32 (fabsf/fmaxfinstead of__habs2/__hmax2)3. Pingpong Kernel Schedule
KernelScheduleAutotoKernelPtrArrayTmaWarpSpecializedPingpong4.
compute_120aArchitecture Flagcompute_120agencode for FP4 kernel compilationa-specific instructions are not available on desktop Blackwell (confirmed by CUTLASS Issue Support NVFP4 KV for prefill and batch attention kernels #2820).5. CUTLASS 4.4.1 Upgrade
VLLM_CUTLASS_SRC_DIR, rebuilt_C.abi3.soFetchContent_Declareoverwriting our clone with hardcodedGIT_TAG v4.2.1. Fixed by usingVLLM_CUTLASS_SRC_DIRenv var.Phase 2: Alternative MoE Backends (FlashInfer)
vLLM supports 5 MoE backends for NVFP4:
VLLM_CUTLASS(default) — broken on SM120FLASHINFER_TRTLLM— blocked by SM100-only capability checksFLASHINFER_CUTLASS— blocked by SM120 capability checks + missingsm_120ain CuTe DSLFLASHINFER_CUTEDSL— blocked by SM100-only capability checksMARLIN— working W4A16 workaround (46-49 tok/s)6. FlashInfer CUTLASS Backend (The Breakthrough)
Required patches (10+ files):
vLLM Capability Checks (3 files)
FlashInfer JIT Architecture Filters (flashinfer/jit/fused_moe.py)
FlashInfer Compilation Context (flashinfer/compilation_context.py)
CuTe DSL
admissible_archs(5 files, 18+ locations)Added
"sm_120a"after every"sm_100a"in admissible_archs lists.cuda.py Device Mapping
TRT-LLM C++ Launcher (flashinfer/data/csrc/trtllm_fused_moe_kernel_launcher.cu)
Additional Requirements
nvccmust be in PATH (FlashInfer JIT needs it)VLLM_NVFP4_GEMM_BACKEND=cutlassenv var for dense layers (use vLLM native CUTLASS)Result: CORRECT OUTPUT! First known native FP4 MoE on SM120 desktop Blackwell.
Benchmark Results
Launch Command (FlashInfer CUTLASS — Working Native FP4)
Speed Comparison
--moe-backend marlin)Why FlashInfer CUTLASS is 3x Slower Than Marlin
FlashInfer's autotuner logs reveal the root cause:
All TMA warp-specialized grouped GEMM tactics fail to initialize on SM120 with
compute_120a. The autotuner falls back to slower, non-TMA tactics. This is a CUTLASS template-level issue where SM120's TMA grouped GEMM doesn't work with theasuffix — it likely requires thefsuffix (compute_120f) which is only available with CUDA 13.0+.Key Technical Findings
1.
compute_120vscompute_120avscompute_120fcompute_120compute_120acompute_120f2. SM120 Desktop is NOT SM100 Compatible
Despite sharing the "Blackwell" brand, SM120 (desktop) and SM100 (datacenter) have different:
avsfsuffix)3. The Broken Chain
BREAKTHROUGH:
compute_120fwith CUDA 13.0A DGX Spark (SM121) user achieved 35 tok/s with FlashInfer CUTLASS using
12.1f(CUDA 13.0). Thefsuffix enables the "full" SM120 feature set with working TMA WS grouped GEMM tactics.Results:
compute_120fNearly Triples Speedcompute_120a(CUDA 12.8)compute_120f(CUDA 13.0)compute_120fenabled the fast TMA WS grouped GEMM tactics that failed withcompute_120a. This confirms thefsuffix is the correct architecture designation for SM120 desktop Blackwell GPUs.Launch Command (CUDA 13.0 + compute_120f)
Why 39 vs 49 tok/s?
The remaining ~20% gap vs Marlin is likely due to:
Production Recommendation (Current)
Use Marlin for production until
compute_120fresults are confirmed:Required env vars:
Related Issues
Files Patched (Complete List)
FlashInfer 0.6.5
flashinfer/compilation_context.pyflashinfer/jit/fused_moe.py(3 locations)supported_major_versions12flashinfer/data/csrc/trtllm_fused_moe_kernel_launcher.cu(2 locations)ICHECK_EQ->ICHECK_GEflashinfer/data/cutlass/python/CuTeDSL/cutlass/cute/nvgpu/cpasync/copy.py(4 locations)sm_120ato admissible_archsflashinfer/data/cutlass/python/CuTeDSL/cutlass/cute/nvgpu/tcgen05/mma.py(2 locations)sm_120ato admissible_archsflashinfer/data/cutlass/python/CuTeDSL/cutlass/cute/nvgpu/tcgen05/copy.py(3 locations)sm_120ato admissible_archsflashinfer/data/cutlass/python/CuTeDSL/cutlass/cute/arch/mbar.py(8 locations)sm_120ato admissible_archsflashinfer/data/cutlass/python/CuTeDSL/cutlass/cute/arch/elect.py(1 location)sm_120ato admissible_archsflashinfer/data/cutlass/python/CuTeDSL/base_dsl/runtime/cuda.py(12, 0)device mappingvLLM 0.17.0
vllm/model_executor/layers/fused_moe/experts/trtllm_nvfp4_moe.pyis_device_capability_family(120)vllm/model_executor/layers/fused_moe/flashinfer_trtllm_moe.pyis_device_capability_family(120)vllm/model_executor/layers/fused_moe/flashinfer_cutedsl_moe.pyis_device_capability_family(120)vLLM Source (CUDA kernel rebuilds — tested but not needed for FlashInfer path)
vllm-src/CMakeLists.txt-DCUTLASS_GDC_ENABLED,-DCUTLASS_ENABLE_GDC_FOR_SM100=1vllm-src/csrc/quantization/fp4/nvfp4_utils.cuhReport date: March 8, 2026
Hardware: 4x RTX PRO 6000 Blackwell (SM120, 96GB each)
Tested by: Kentucky Local Counsel Inference Lead, Brandon Music