[#11932][fix] Filter CUTLASS MoE GEMM tile configs by device shared memory on SM121#12704
Conversation
📝 WalkthroughWalkthroughTwo runtime shared memory validation checks were added: one filters CUTLASS GEMM candidate configurations when max shared memory is below 120KB, and another validates kernel shared memory requirements against device limits before kernel launch. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes 🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@cpp/tensorrt_llm/kernels/cutlass_kernels/cutlass_heuristic.cpp`:
- Around line 561-568: The SM<120 KiB pruning only removes CtaShape128x128x128B
but leaves 64B K-tile configs that the FP4 dispatcher
(dispatchNVFP4xNVFP4GemmCTAShapeSm120) doesn't handle, causing an invalid-config
throw; update the pruning logic around candidate_configs and
CutlassGemmConfig::tile_config_sm120 to either remove the additional 64B shapes
(CtaShape128x128x64B, CtaShape128x256x64B, CtaShape256x128x64B) or, better,
whitelist only the shapes the dispatcher supports (CtaShape128x128x128B,
CtaShape128x128x256B, CtaShape256x128x128B) so candidate_configs contains only
dispatchable CutlassTileConfigSM120 values and the autotuner no longer hits the
default invalid-config path.
- Around line 554-559: The static kMaxSmem initializer currently queries device
0; change it to call cudaGetDevice() to obtain the current device and pass that
device ID into cudaDeviceGetAttribute(), adding explicit error checks for both
cudaGetDevice and cudaDeviceGetAttribute and falling back or logging on error.
Replace the literal 120 * 1024 with a named constant (e.g., kSmemThresholdBytes)
and use that constant where the literal appears. Declare the iterator variable
named it as const (e.g., const auto it) where it is defined. Also update the
file copyright year to 2026.
In
`@cpp/tensorrt_llm/kernels/cutlass_kernels/moe_gemm/launchers/moe_gemm_tma_ws_launcher.inl`:
- Around line 673-682: Replace the current function-static kMaxSmem that calls
cudaDeviceGetAttribute(..., 0) with a runtime query that calls cudaGetDevice()
to obtain the current device id and then calls cudaDeviceGetAttribute(&val,
cudaDevAttrMaxSharedMemoryPerBlockOptin, device) so the shared-memory check for
GemmGrouped/GemmKernel_ uses the active GPU; remove the lambda-cached static and
compute smem limit per invocation and keep the TLLM_CHECK_WITH_INFO(smem_size <=
kMaxSmem, ...) guard unchanged except that kMaxSmem is now the per-call value.
Also add the same per-device SMEM preflight guard (compute current device via
cudaGetDevice and compare sizeof(typename GemmKernel_::SharedStorage) against
that device's limit) into moe_gemm_tma_ws_mixed_input_launcher.inl before
calling gemm.can_implement().
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: ee34cc95-0326-4ec6-978d-b97646526a47
📒 Files selected for processing (2)
cpp/tensorrt_llm/kernels/cutlass_kernels/cutlass_heuristic.cppcpp/tensorrt_llm/kernels/cutlass_kernels/moe_gemm/launchers/moe_gemm_tma_ws_launcher.inl
93b9c60 to
556d505
Compare
…ared memory on SM121 SM121 (DGX Spark GB10) has 99 KiB shared memory per block vs 228 KiB on SM120 (B200). CUTLASS StageCountAutoCarveout computes pipeline stages assuming 228 KiB, causing TMA warp-specialized MoE grouped GEMM tactics to fail with opaque "Error Internal" on gemm.initialize(). This patch adds two fixes: 1. Runtime SMEM guard in moe_gemm_tma_ws_launcher.inl: checks kernel SharedStorage size against cudaDevAttrMaxSharedMemoryPerBlockOptin before launch, converting opaque CUTLASS errors into clear diagnostics that the autotuner can skip. 2. Heuristic filter in get_candidate_configs_sm120(): on devices with < 120 KiB SMEM, removes tile configs whose SharedStorage exceeds the device limit. Keeps only CtaShape128x128x64B which fits within 99 KiB including FINALIZE epilogue overhead (~80 KiB total). Signed-off-by: Mihai Chiorean <mihai.v.chiorean@gmail.com>
556d505 to
b1f4372
Compare
|
Hi @pamelap-nvidia, could you please review this PR? |
The original comment said 'SM121 (GB10) has 99 KiB vs SM120 (B200) 228 KiB', but B200 is SM100, not SM120. SM120 is consumer Blackwell (RTX PRO 6000) which has the SAME 99 KiB SMEM as SM121 GB10 — confirmed independently in issue NVIDIA#11932 by @waynehacking8. The runtime code is unchanged and correct (it queries cudaDevAttrMaxSharedMemoryPerBlockOptin), only the prose is fixed to label arches accurately. Signed-off-by: Mihai Chiorean <mihai.v.chiorean@gmail.com>
|
@pamelap-nvidia — gentle bump on this one. PR is mergeable, all checks green, and the fix has been independently confirmed on SM120 RTX PRO 6000 by @waynehacking8 in #11932. If you're not the right reviewer for the CUTLASS heuristic / MoE launcher path, please feel free to redirect — happy to address feedback from whoever's the best fit. |
|
/bot run --extra-stage "GB10-PyTorch-Post-Merge-1,RTXPro6000D-PyTorch-Post-Merge-1,RTXPro6000D-4_GPUs-PyTorch-Post-Merge-1,RTXPro6000D-4_GPUs-PyTorch-Post-Merge-2" |
|
PR_Github #55295 [ run ] triggered by Bot. Commit: |
|
PR_Github #55295 [ run ] completed with state
|
|
@pamelap-nvidia I'm not sure what failed in CI and why. I updated the branch. hopefully it will pass this time. mind starting a CI run again? when this merges, it actually opens the gate for MTP for qwen3.6 35b nvfp4 with mtp on trt-llm. |
revert accidental change Signed-off-by: Mihai Chiorean <mihai.v.chiorean@gmail.com>
@karljang really appreciate your patience. I'm having a hard time figuring out the next failure. it would be really nice to know what tests blossom is running and how so I can run them myself and make sure I am confident before pinging you guys. Just an idea. Other than that... I need more logs to see what's failing this time. Again, really appreciate your help I would like to merge this first before #15851 |
|
/bot run --extra-stage "GB10-PyTorch-Post-Merge-1,RTXPro6000D-PyTorch-Post-Merge-1,RTXPro6000D-4_GPUs-PyTorch-Post-Merge-1,RTXPro6000D-4_GPUs-PyTorch-Post-Merge-2" |
|
/bot kill |
|
/bot run --extra-stage "GB10-PyTorch-Post-Merge-1,RTXPro6000D-PyTorch-Post-Merge-1,RTXPro6000D-4_GPUs-PyTorch-Post-Merge-1,RTXPro6000D-4_GPUs-PyTorch-Post-Merge-2" --disable-fail-fast |
|
PR_Github #60787 [ kill ] triggered by Bot. Commit: |
|
PR_Github #60787 [ kill ] completed with state |
|
PR_Github #60788 [ run ] triggered by Bot. Commit: |
|
PR_Github #60788 [ run ] completed with state
|
|
/bot run --extra-stage "GB10-PyTorch-Post-Merge-1,RTXPro6000D-PyTorch-Post-Merge-1,RTXPro6000D-4_GPUs-PyTorch-Post-Merge-1,RTXPro6000D-4_GPUs-PyTorch-Post-Merge-2" --disable-fail-fast |
|
PR_Github #60891 [ run ] triggered by Bot. Commit: |
|
PR_Github #60891 [ run ] completed with state |
|
@rosong11 @schetlur-nv mind taking a look? CI passes now and there are 2 approvals already |
|
@mihai-chiorean , |
…nnahz/dep-1083-port-flashinfer-stable-va-lifecycle-for-native-all-reduce * 'main' of https://github.com/NVIDIA/TensorRT-LLM: (83 commits) [None][feat] Bind SourceIdentity to checkpoint artifacts (NVIDIA#16159) [None][infra] Waive 4 failed cases for main in pre-merge 49550 (NVIDIA#16798) [None][fix] Make FlashInfer sampling op wrappers opaque to Dynamo (NVIDIA#16732) [None][feat] top-k: route decode to CuTe DSL GVR top-k in e2e (NVIDIA#16420) [None][feat] Default GLM-5 to the Python KV-cache transceiver (NVIDIA#16524) [None][chore] Add NVTX ranges to per-iteration ADP sync points in PyExecutor (NVIDIA#16422) [https://nvbugs/6426850][test] Unwaive Qwen3.5 397B NVFP4 ADP4 TRTLLM test (NVIDIA#16348) [https://nvbugs/6445456][fix] Restore inplace ops for functionalization v2 (NVIDIA#16410) [None][infra] Waive 1 failed cases for main in pre-merge 49229 (NVIDIA#16786) [None][fix] Load DeepSeek V4 mixed-precision NVFP4 checkpoints (NVIDIA#16433) [None][feat] ADP conversation router: configurable least-queued placement for new conversations (NVIDIA#16294) [None][infra] Waive 1 failed cases for main in pre-merge 49424 (NVIDIA#16780) [None][infra] Waive 1 failed cases for main in pre-merge 49424 (NVIDIA#16781) [TRTLLMINF-188][infra] Require approval for PerfSanity wildcard runs (NVIDIA#16777) [TRTLLM-13969][feat] Support MiniMax M3 for Disaggregated Serving (NVIDIA#16017) [NVIDIA#11932][fix] Filter CUTLASS MoE GEMM tile configs by device shared memory on SM121 (NVIDIA#12704) [None][chore] Remove attention backend test waivers (NVIDIA#16723) [TRTLLM-14540][perf] Skip fp32 state round-trip in FlashInfer GDN pre… (NVIDIA#16703) [TRTLLM-13694][feat] Add IBDB recipe provenance and refresh configs (NVIDIA#16254) [None][infra] Preview/bump/main (NVIDIA#16758) ... Signed-off-by: Hannah Zhang <hannahz@nvidia.com>
…ared memory on SM121 (NVIDIA#12704) Signed-off-by: Mihai Chiorean <mihai.v.chiorean@gmail.com>
Summary
Consumer Blackwell (SM120 RTX PRO 6000, SM121 GB10 / DGX Spark) has a smaller opt-in shared-memory budget than SM100/B200. Some CUTLASS MoE grouped GEMM TMA warp-specialized tactics selected for the SM120 path can exceed that device limit and fail at
gemm.initialize()with an opaque internal error. This was independently observed on RTX PRO 6000 in #11932 and blocks good Qwen3.6 NVFP4 performance on GB10.This PR keeps the existing SM120 mixed-MoE/NVFP4 path, but makes tactic selection shared-memory-aware:
moe_gemm_tma_ws_launcher.inl, checking kernelSharedStorageagainstcudaDevAttrMaxSharedMemoryPerBlockOptinbefore launch. Oversized tactics now fail with a clear diagnostic that autotuning can skip.get_candidate_configs_sm120().The implementation uses runtime device attributes rather than hard-coding GB10-specific behavior.
Impact
Relationship to related work
Qwen3.5/3.6 MoE NVFP4 + MTP support) on SM120/SM121.1.3.0rc15on sm_121a / GB10: MTP path fails — CUTLASS sm_120 grouped-GEMM init → SMEM shortfall → Triton fallback emits.rsPTX rejected by PTXAS #14575 for consumer Blackwell MTP workloads.