Cracking the SM120 Shared Memory Ceiling: A Deep Dive into CUTLASS Tile Configuration Debugging

In the high-stakes world of large language model inference optimization, few things are as frustrating as a kernel that fails to initialize with a cryptic "Error Internal" message. This is exactly the situation the assistant faced in message 914 of this opencode session, where the goal was to maximize throughput of the GLM-5-NVFP4 model on eight NVIDIA RTX PRO 6000 Blackwell GPUs. The assistant had already established that the model was compute-bound rather than communication-bound, and that the FP4 GEMM kernels were the critical performance bottleneck. Now it needed to understand why certain CUTLASS tile configurations—specifically M128×N256 and M256×N128—were crashing during initialization, while smaller tiles like 128×128×128 and 128×128×256 worked fine.

The Context: A Compute-Bound Model on Blackwell GPUs

The broader session (Segment 7) had already produced several key findings. The assistant had benchmarked TP4+PP2 versus TP8 configurations, confirming the model was compute-bound. GPU power draw during inference was only ~235W out of 600W TDP—just 39%. The CUTLASS FP4 kernels achieved at most ~1,300 TFLOPS (70% of dense peak) for large matrices, but during actual decode, per-expert batch sizes of ~16–64 tokens yielded a paltry 0.8–55 TFLOPS (0.02–3% of peak). The 99KB shared memory limit on SM120 was preventing larger CUTLASS tile configurations from initializing. The user had given a clear directive in message 905: "Fix tiles, then try 2/3"—meaning first fix the failing tile configurations, then try increasing effective batch size and exploring the cuBLASLt FP4 path.

Tracing the Failure

The assistant's investigation in messages 906–913 had traced the failure to the initializeMoeGroupedGemm function in the CUTLASS MoE GEMM launcher. The can_implement check passed, but initialize returned kErrorInternal. This pointed to a runtime shared memory allocation failure—the kernel was requesting more dynamic shared memory than the device could provide, even after cudaFuncSetAttribute had been called to opt into the maximum.

The critical numbers, extracted in message 912, were:

The Shared Memory Calculation

Message 914 is where the assistant synthesizes all this information into a crystal-clear diagnosis. The message begins with "Now it's crystal clear:" and presents a detailed analysis of shared memory requirements for each tile configuration.

The calculation considers:

Assumptions and Their Validity

The assistant makes several assumptions in this analysis:

  1. The epilogue storage estimate: The assistant assumes BF16 output staging (2 bytes per element) for the default epilogue and FP32 accumulator + BF16 output (4 bytes per element) for the finalize epilogue. These are reasonable estimates based on typical CUTLASS epilogue patterns, but the assistant wisely hedges by noting they might be wrong and proceeding to check the actual source.
  2. That StageCountAutoCarveout is working correctly: The assistant assumes the auto-carveout mechanism is functioning as designed and reducing to the minimum number of stages. If there were a bug in the carveout calculation itself, the diagnosis might be different.
  3. That the failure is purely SMEM-related: Given that can_implement passes but initialize fails, the SMEM hypothesis is the most likely explanation. However, there could be other reasons for kErrorInternal—for instance, register pressure exceeding the architectural limit, or unsupported tensor memory accelerator (TMA) descriptors for certain tile dimensions.

Input Knowledge Required

To fully understand this message, one needs:

Output Knowledge Created

This message produces several valuable outputs:

  1. A precise diagnosis of the tile failure: The larger tiles fail because the epilogue output tile (M×N) requires more shared memory than is available after accounting for even a single pipeline stage of the mainloop.
  2. A quantitative model of shared memory usage: The assistant provides a reusable formula for estimating SMEM requirements for any tile configuration, which can be applied to other tile sizes or architectures.
  3. A clear direction for the fix: The problem is not with the mainloop pipeline stages but with the epilogue. This suggests that solutions might involve using a different epilogue strategy (e.g., epilogue in registers or via TMA store), reducing the output tile size, or finding a way to partition the output across multiple kernel invocations.
  4. An actionable next step: The assistant immediately follows the analysis by looking at the actual CUTLASS source code to verify the epilogue estimates and understand what StageCountAutoCarveout actually does, demonstrating a systematic approach to verification.