When a Benchmark Crashes: The Elusive FP4 GEMM Comparison on Blackwell SM120
Introduction
In the course of a deep optimization session for the GLM-5-NVFP4 large language model running on 8× NVIDIA RTX PRO 6000 Blackwell GPUs, the assistant reached a pivotal moment of investigation. After systematically benchmarking FlashInfer's FP4 matrix multiplication kernels across dozens of matrix sizes and establishing that the CUTLASS-based implementation plateaued at roughly 1,300 TFLOPS—about 65% of the theoretical 2,000 TOPS peak for Blackwell's SM120 architecture—the assistant turned its attention to an alternative implementation. The sgl_kernel library, bundled with the SGLang inference framework, exposed a function called cutlass_scaled_fp4_mm that promised the same FP4 GEMM operation through a potentially different code path. Message [msg 874] captures the moment this comparison was attempted—and failed.
The message itself is deceptively brief: a single SSH command executing a Python benchmark script, followed by a truncated error traceback. But this brief failure sits at the intersection of several converging lines of investigation, embodying the challenges of deploying cutting-edge models on bleeding-edge hardware. To understand why this message matters, one must trace the reasoning that led to it, the assumptions that underlay it, and the knowledge it ultimately produced.
The Message: What Actually Happened
The assistant executed a command via SSH on the remote machine (10.1.230.174), activating the Python virtual environment at /root/ml-env/bin/activate and running a script at /tmp/bench_fp4.py. The script had been written in the immediately preceding message ([msg 873]) after two earlier attempts to run the benchmark inline via shell heredocs had failed due to Python f-string parsing issues caused by shell escaping.
The output begins with the table header printed by the script—Description | sgl_kernel | flashinfer | ratio—but then immediately crashes:
Traceback (most recent call last):
File "/tmp/bench_fp4.py", line 33, in <module>
sgl_kernel.cutlass_scaled_fp4_mm(a_fp4, b_fp4, a_scale, b_scale, alpha, torch.bfloat16)
File "/root/ml-env/lib/python3.12/site-packages/sgl_kernel/gemm.py", line 174, in cutlass_scaled_fp4_mm
torch.ops.sgl_kernel.cutlass_scaled_fp4_mm.default(
Fi...
The traceback is truncated (ending with "Fi..."), but the critical information is clear: the call to sgl_kernel.cutlass_scaled_fp4_mm on line 33 of the benchmark script raised an exception. The error propagated through the Python wrapper in sgl_kernel/gemm.py at line 174, where it invoked the underlying PyTorch custom operator torch.ops.sgl_kernel.cutlass_scaled_fp4_mm.default. The exact error message is lost to truncation, but the pattern is unmistakable—the CUTLASS kernel failed to execute on the Blackwell GPU.
Why This Message Was Written: The Reasoning and Motivation
To understand the motivation behind this benchmark, one must appreciate the trajectory of the investigation up to this point. The assistant had been systematically characterizing the performance of GLM-5-NVFP4, a Mixture-of-Experts model with 256 experts (8 activated per token), a hidden size of 6144, and an intermediate size of 2048. The model uses 4-bit floating-point (FP4) quantization for its weight matrices, which means all the heavy matrix multiplications (GEMMs) are performed in FP4 precision.
The assistant had already established several critical findings in the preceding messages ([msg 867], [msg 868], [msg 869]):
- The FP4 CUTLASS kernels in FlashInfer plateau at ~1,300 TFLOPS for very large matrices (batch sizes of 4K+), which is only about 65% of the estimated 2,000 TOPS theoretical peak for the Blackwell GPU's 188 SMs.
- During actual inference decode, per-expert batch sizes are tiny—around 16–64 tokens per expert—which achieves merely 0.8–55 TFLOPS (0.02–3% of peak). This is because the 256 experts scatter tokens too thinly.
- FP4 was only ~2× faster than BF16 for the same matrix dimensions (437 TFLOPS vs 225 TFLOPS at batch=512), not the 4× that the 4× smaller data format would theoretically enable. These findings painted a clear picture: the FP4 GEMM kernels were significantly underperforming on Blackwell's SM120 architecture. The assistant had also discovered that
sgl_kernel—a library shipped with SGLang—contained several FP4-related functions, includingcutlass_scaled_fp4_mmandcutlass_moe([msg 869]). This raised an obvious question: Does SGLang's own CUTLASS FP4 implementation perform better than FlashInfer's? The motivation for message [msg 874] was thus to conduct a head-to-head comparison of the two FP4 GEMM implementations across the exact matrix sizes that matter for GLM-5 inference: the attention projection dimensions (M×768×6144) and the MoE expert dimensions (M×2048×6144), for batch sizes ranging from 16 to 1024 tokens. Ifsgl_kernelproved faster, it could be swapped in as a drop-in replacement to improve inference throughput.
How Decisions Were Made
The decision to run this benchmark was the result of a systematic, hypothesis-driven investigation. The assistant had been working through a ranked optimization plan for GLM-5-NVFP4, and understanding the baseline FP4 GEMM performance was a prerequisite for any further optimization work.
The decision process unfolded across several messages:
- [msg 869]: After benchmarking FlashInfer's FP4 GEMMs across a wide range of sizes, the assistant discovered that
sgl_kernelhad FP4 functions. The decision to benchmark them was immediate and logical. - [msg 870]: The assistant checked the function signature of
cutlass_scaled_fp4_mmusinghelp(), confirming it accepted the same parameters (a, b, block_scale_a, block_scale_b, alpha, out_dtype) as FlashInfer's API. - [msg 871]: The first attempt to run the comparison inline failed with a
NameErrorbecause the shell was interpreting Python f-string curly braces. - [msg 872]: A second inline attempt with different quoting also failed with the same
NameError, confirming the shell escaping issue was fundamental. - [msg 873]: The assistant pivoted to writing the script to a file (
/tmp/bench_fp4.py) using a heredoc, which avoided the shell escaping problem entirely. This was the correct engineering decision—when inline execution fails due to quoting complexity, writing a file is the robust alternative. - [msg 874]: The script was executed and crashed. The key decision was the choice to compare
sgl_kernel.cutlass_scaled_fp4_mmagainstflashinfer.mm_fp4using the CUTLASS backend. The assistant could have tested other backends (cuBLASLt, cuDNN, TRTLLM) but had already established in [msg 866] that cuDNN failed on SM120 and TRTLLM explicitly rejected it. CUTLASS was the only working backend for FP4 on Blackwell, making it the natural comparison point.
Assumptions Made
This message rests on several assumptions, some explicit and some implicit:
- That
sgl_kernel.cutlass_scaled_fp4_mmwould work on SM120. This was the critical assumption that proved false. The assistant had already seen that cuDNN and TRTLLM backends failed on Blackwell, but CUTLASS-based kernels in FlashInfer worked (albeit with suboptimal performance). The assumption that SGLang's CUTLASS kernels would also work was reasonable but ultimately incorrect. - That the benchmark script was correctly written. After two shell-escaping failures, the assistant correctly identified the problem and switched to a file-based approach. The script itself was well-structured: it used proper warmup iterations,
torch.cuda.synchronize()barriers, and sufficient iterations (100) for statistical significance. The assumption that the script would execute without errors was reasonable given the careful construction. - That the matrix sizes chosen were representative. The sizes (M=16,64,256,512,1024; N=768 or 2048; K=6144) were directly derived from the GLM-5 model architecture and the TP8 tensor parallelism configuration. This was a well-informed choice.
- That a performance difference would be informative. Even if both implementations performed similarly, the comparison would have been valuable—it would confirm that the ~1,300 TFLOPS ceiling was fundamental to CUTLASS on SM120 rather than specific to FlashInfer's integration.
- That the environment was correctly set up. The assistant activated the Python virtual environment and assumed that
sgl_kernelwas importable and functional. The import succeeded (noModuleNotFoundError), but the kernel execution failed.
Mistakes and Incorrect Assumptions
The primary mistake revealed by this message is the assumption that sgl_kernel.cutlass_scaled_fp4_mm would work on Blackwell SM120. In hindsight, this assumption was optimistic. The assistant had already documented multiple backend failures on SM120:
- cuDNN: Failed with
CUDNN_STATUS_BAD_PARAM([msg 866]) - TRTLLM: Explicitly rejected SM120 (mentioned in [msg 866])
- cuBLASLt: Found to be no faster than FlashInfer's CUTLASS path (per the chunk summary) The CUTLASS kernels in FlashInfer worked, but they were clearly not optimized for SM120—they plateaued at 65% of theoretical peak and couldn't use larger tile configurations due to the 99KB shared memory limit on Blackwell. It was reasonable to hope that SGLang's CUTLASS kernels might be better tuned, but the failure suggests they may not support SM120 at all, or may have a different issue (e.g., a missing kernel variant for the specific matrix dimensions). A secondary observation is that the assistant did not capture the full error message. The output is truncated with "Fi...", which could have contained crucial diagnostic information—the exact error type (e.g.,
RuntimeError,CUDAError) and message. In a debugging workflow, this loss of information is costly. The truncation likely occurred because the SSH command's stderr was piped through the conversation system, and the output was cut at a certain length.
Input Knowledge Required
To fully understand this message, one needs knowledge spanning several domains:
- GLM-5-NVFP4 Model Architecture: The model uses FP4 quantization for weights, has a hidden size of 6144, an MoE intermediate size of 2048, 256 experts with 8 activated per token, and is deployed with tensor parallelism (TP8 initially, later TP4+PP2).
- Blackwell SM120 Architecture: The NVIDIA RTX PRO 6000 Blackwell GPUs have compute capability 12.0 (SM120), 188 SMs, a 600W TDP, and a 99KB shared memory limit per SM. The theoretical FP4 peak is estimated at ~2,000 TOPS, and the memory bandwidth is 1,597 GB/s.
- FP4 Quantization Format: The model uses 4-bit floating point (NVFP4), where each 4-bit value represents a floating-point number. The weights are stored in a packed uint8 format (two 4-bit values per byte) with block-wise scaling factors stored as float8_e4m3fn.
- CUTLASS and GEMM Kernels: CUTLASS is a CUDA template library for matrix multiply-accumulate operations. The FP4 GEMM operation involves dequantizing the 4-bit weights on-the-fly, performing the multiply-accumulate in a higher precision (e.g., BF16), and writing the result. Kernel efficiency depends on tile sizes, shared memory usage, and the compute-to-memory ratio (arithmetic intensity).
- FlashInfer and SGLang Libraries: FlashInfer is a library of GPU kernels for LLM inference, used by SGLang. The
sgl_kernelpackage is SGLang's own kernel library, which may have different implementations or optimizations. - The SGLang Serving Stack: The model is deployed using SGLang, and the assistant has been tuning server parameters like
--max-running-requestsand--num-continuous-decode-steps.
Output Knowledge Created
Despite being a "failure," this message produces valuable negative knowledge:
- sgl_kernel.cutlass_scaled_fp4_mm does not work on Blackwell SM120 (in this configuration). This is a definitive result that saves future investigation time. The assistant can now rule out this optimization path.
- The CUTLASS FP4 implementation in FlashInfer remains the only viable FP4 GEMM backend for GLM-5 on Blackwell. Since cuDNN, TRTLLM, and sgl_kernel all fail, the optimization effort must focus on improving the FlashInfer CUTLASS path or finding alternative approaches (e.g., expert parallelism, piecewise CUDA graphs, MSCCLPP allreduce—all of which the assistant explored later in the session).
- The benchmark methodology was validated. The script structure (warmup, synchronization, multiple iterations) was sound, and the failure was in the kernel execution, not the benchmarking framework.
- A data point for SGLang developers. If this issue is reported, it provides evidence that
cutlass_scaled_fp4_mmneeds SM120 support, which may require updating the CUTLASS kernels or adding a kernel fallback.
The Thinking Process Visible in Reasoning Parts
The assistant's thinking process across the messages leading to [msg 874] reveals a methodical, hypothesis-driven approach to performance debugging:
- Observation: FlashInfer's FP4 GEMMs plateau at ~1,300 TFLOPS ([msg 868]).
- Hypothesis: Maybe SGLang's own kernels are better optimized for SM120.
- Evidence gathering: Check if
sgl_kernelhas FP4 functions ([msg 869]). It does—cutlass_scaled_fp4_mmandcutlass_moeamong others. - API verification: Check the function signature ([msg 870]). It accepts the same parameters.
- Experiment design: Write a benchmark comparing both implementations across representative sizes ([msg 871], [msg 872], [msg 873]).
- Execution: Run the benchmark ([msg 874]).
- Result: Failure. The assistant does not panic or overreact to the failure. In the messages that follow ([msg 875] onward, not shown in the provided context), it presumably analyzes the error, confirms the incompatibility, and pivots to other optimization strategies. This is characteristic of good engineering practice: treat negative results as data, not as setbacks. The assistant's thinking also shows awareness of the broader optimization landscape. Even before running this benchmark, it had already launched research agents exploring expert parallelism, piecewise CUDA graphs, MSCCLPP allreduce, and other advanced techniques (per the chunk summary). The FP4 GEMM comparison was one thread in a larger investigation, not the sole focus.
Broader Significance
This message, though brief and seemingly trivial, encapsulates several universal truths about high-performance computing on cutting-edge hardware:
Bleeding-edge means breaking. When you're running a model that was released weeks ago on GPUs that were released months ago, with software stacks that are being updated daily, failures are the norm. Every working configuration is a small miracle of compatibility.
Negative results are valuable. Knowing that sgl_kernel.cutlass_scaled_fp4_mm fails on SM120 saves the next person (or the same assistant in a future session) from trying the same experiment. In a field where "try it and see" is a common methodology, documented failures are as important as documented successes.
The optimization stack is deep. When a model is compute-bound at the kernel level, you can optimize the kernels (CUTLASS tuning), the execution strategy (expert parallelism, CUDA graphs), the communication (allreduce fusion), or the system parameters (batch size, continuous decode steps). The assistant's willingness to explore all these levels simultaneously is a model of systematic optimization.
Shell escaping is still a problem in 2025. The fact that the assistant had to write a script file because inline Python heredocs kept failing due to shell quoting is a reminder that even with advanced AI systems, the Unix command line remains a minefield of edge cases.
Conclusion
Message [msg 874] is a snapshot of a moment in a larger optimization journey—a moment where a carefully designed experiment failed, producing a negative result that was nonetheless valuable. The assistant's systematic approach to benchmarking FP4 GEMM performance, its willingness to explore alternative implementations, and its methodical handling of failures all exemplify the engineering mindset required to deploy large language models on novel hardware. The truncated traceback, with its tantalizing "Fi...", leaves the exact nature of the failure slightly mysterious, but the message is clear: on Blackwell SM120, even CUTLASS-based FP4 kernels are not guaranteed to work, and the path to optimal performance requires deeper investigation at every level of the stack.