Skip to content

[#11932][fix] Filter CUTLASS MoE GEMM tile configs by device shared memory on SM121#12704

Merged
karljang merged 26 commits into
NVIDIA:mainfrom
mihai-chiorean:fix/cutlass-moe-smem-sm121
Jul 23, 2026
Merged

[#11932][fix] Filter CUTLASS MoE GEMM tile configs by device shared memory on SM121#12704
karljang merged 26 commits into
NVIDIA:mainfrom
mihai-chiorean:fix/cutlass-moe-smem-sm121

Conversation

@mihai-chiorean

@mihai-chiorean mihai-chiorean commented Apr 2, 2026

Copy link
Copy Markdown
Contributor

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:

  1. Adds a runtime shared-memory guard in moe_gemm_tma_ws_launcher.inl, checking kernel SharedStorage against cudaDevAttrMaxSharedMemoryPerBlockOptin before launch. Oversized tactics now fail with a clear diagnostic that autotuning can skip.
  2. Filters SM120 candidate configs against the runtime device shared-memory limit before returning them from get_candidate_configs_sm120().
  3. Preserves valid low-SMEM candidates for both NVFP4 and mixed FP8xFP4 grouped GEMM. In particular, mixed FP8xFP4 keeps its existing large tile where it fits and also receives a smaller fallback tile for 99 KiB devices.

The implementation uses runtime device attributes rather than hard-coding GB10-specific behavior.

Impact

  • Without this fix: oversized tactics can fail during CUTLASS grouped-GEMM initialization on SM120/SM121, causing noisy autotuning failures and poor fallback behavior.
  • With this fix: oversized tactics are skipped cleanly; valid tactics remain available, including the mixed FP8xFP4 low-SMEM fallback needed by Qwen3.6 NVFP4 workloads.

Relationship to related work

@coderabbitai

coderabbitai Bot commented Apr 2, 2026

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

Two 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

Cohort / File(s) Summary
CUTLASS Config Filtering
cpp/tensorrt_llm/kernels/cutlass_kernels/cutlass_heuristic.cpp
Added <algorithm> include and runtime device query for cudaDevAttrMaxSharedMemoryPerBlockOptin in get_candidate_configs_sm120. When max shared memory is below 120KB, candidate configs with CtaShape128x128x128B tile are filtered out, retaining only 64B K-tile variants.
MOE GEMM Launcher Validation
cpp/tensorrt_llm/kernels/cutlass_kernels/moe_gemm/launchers/moe_gemm_tma_ws_launcher.inl
Added pre-launch validation check verifying kernel's required shared memory (sizeof(GemmKernel::SharedStorage)) does not exceed device's maximum shared memory per block with opt-in capability. Triggered before gemm.can_implement()/gemm.initialize() calls.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: filtering CUTLASS MoE GEMM tile configs based on device shared memory constraints for SM121, which directly addresses the core issue described in the PR.
Description check ✅ Passed The PR description includes a clear summary, impact, related work, and test plan, covering most required template content.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

📥 Commits

Reviewing files that changed from the base of the PR and between 11c40bb and 93b9c60.

📒 Files selected for processing (2)
  • cpp/tensorrt_llm/kernels/cutlass_kernels/cutlass_heuristic.cpp
  • cpp/tensorrt_llm/kernels/cutlass_kernels/moe_gemm/launchers/moe_gemm_tma_ws_launcher.inl

Comment thread cpp/tensorrt_llm/kernels/cutlass_kernels/cutlass_heuristic.cpp Outdated
Comment thread cpp/tensorrt_llm/kernels/cutlass_kernels/cutlass_heuristic.cpp Outdated
@mihai-chiorean
mihai-chiorean force-pushed the fix/cutlass-moe-smem-sm121 branch from 93b9c60 to 556d505 Compare April 2, 2026 19:03
…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>
@mihai-chiorean
mihai-chiorean force-pushed the fix/cutlass-moe-smem-sm121 branch from 556d505 to b1f4372 Compare April 2, 2026 19:10
@svc-trtllm-gh-bot svc-trtllm-gh-bot added the Community want to contribute PRs initiated from Community label Apr 2, 2026
@mihai-chiorean
mihai-chiorean marked this pull request as ready for review April 3, 2026 04:05
@karljang
karljang requested a review from pamelap-nvidia June 2, 2026 18:05
@karljang

karljang commented Jun 2, 2026

Copy link
Copy Markdown
Collaborator

Hi @pamelap-nvidia, could you please review this PR?
My Claude suggests you as the appropriate person to review it, but please feel free to reassign someone else on the team if you prefer.

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>
@mihai-chiorean

Copy link
Copy Markdown
Contributor Author

@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.

@pamelap-nvidia

Copy link
Copy Markdown
Collaborator

/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"

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #55295 [ run ] triggered by Bot. Commit: c15c02c Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #55295 [ run ] completed with state FAILURE. Commit: c15c02c
/LLM/main/L0_MergeRequest_PR pipeline #44248 completed with status: 'FAILURE'

CI Report

⚠️ Action Required:

  • Please check the failed tests and fix your PR
  • If you cannot view the failures, ask the CI triggerer to share details
  • Once fixed, request an NVIDIA team member to trigger CI again

CI Agent Failure Analysis

Link to invocation

@mihai-chiorean

Copy link
Copy Markdown
Contributor Author

@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.

@mihai-chiorean
mihai-chiorean requested a review from a team as a code owner July 19, 2026 00:05
@mihai-chiorean
mihai-chiorean requested review from mzweilz and niukuo July 19, 2026 00:05
@karljang
karljang removed request for a team, mzweilz and niukuo July 20, 2026 17:15
@mihai-chiorean

Copy link
Copy Markdown
Contributor Author

PR_Github #60091 [ run ] completed with state SUCCESS. Commit: 06b6a13 /LLM/main/L0_MergeRequest_PR pipeline #48478 completed with status: 'FAILURE'

CI Report

⚠️ Action Required:

  • Please check the failed tests and fix your PR
  • If you cannot view the failures, ask the CI triggerer to share details
  • Once fixed, request an NVIDIA team member to trigger CI again

CI Agent Failure Analysis

Link to invocation

@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

@karljang

Copy link
Copy Markdown
Collaborator

/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"

@karljang

Copy link
Copy Markdown
Collaborator

/bot kill

@karljang

Copy link
Copy Markdown
Collaborator

/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

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #60787 [ kill ] triggered by Bot. Commit: 0026d2a Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #60787 [ kill ] completed with state SUCCESS. Commit: 0026d2a
Successfully killed previous jobs for commit 0026d2a

Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #60788 [ run ] triggered by Bot. Commit: 0026d2a Link to invocation

@sunnyqgg sunnyqgg left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #60788 [ run ] completed with state SUCCESS. Commit: 0026d2a
/LLM/main/L0_MergeRequest_PR pipeline #49067 completed with status: 'FAILURE'

CI Report

⚠️ Action Required:

  • Please check the failed tests and fix your PR
  • If you cannot view the failures, ask the CI triggerer to share details
  • Once fixed, request an NVIDIA team member to trigger CI again

CI Agent Failure Analysis

Link to invocation

@karljang

Copy link
Copy Markdown
Collaborator

/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

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #60891 [ run ] triggered by Bot. Commit: 0026d2a Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #60891 [ run ] completed with state SUCCESS. Commit: 0026d2a
/LLM/main/L0_MergeRequest_PR pipeline #49160 completed with status: 'SUCCESS'

CI Report

Link to invocation

@mihai-chiorean

Copy link
Copy Markdown
Contributor Author

@rosong11 @schetlur-nv mind taking a look? CI passes now and there are 2 approvals already

@rosong11 rosong11 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@karljang

Copy link
Copy Markdown
Collaborator

@mihai-chiorean ,
We've got all approvals, but there are open conversations above. Could you please resolve them if possible? Thank you!

@karljang
karljang enabled auto-merge (squash) July 23, 2026 04:55
@karljang
karljang merged commit b039094 into NVIDIA:main Jul 23, 2026
8 checks passed
hhzhang16 added a commit to hhzhang16/TensorRT-LLM that referenced this pull request Jul 23, 2026
…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>
yuanjingx87 pushed a commit to yuanjingx87/TensorRT-LLM that referenced this pull request Jul 26, 2026
…ared memory on SM121 (NVIDIA#12704)

Signed-off-by: Mihai Chiorean <mihai.v.chiorean@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Community want to contribute PRs initiated from Community

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants