The Turning Point: Diagnosing Concurrency as the Hidden Bottleneck in GLM-5-NVFP4 Inference

Introduction

In the course of deploying the GLM-5-NVFP4 large language model on eight NVIDIA RTX PRO 6000 Blackwell GPUs, the assistant reached a critical diagnostic moment. Message 670 represents a turning point in the optimization journey — a moment where scattered observations crystallized into a clear hypothesis, and the assistant committed to a new direction that would ultimately quadruple throughput. This article examines that message in depth: its reasoning, its assumptions, its context, and the chain of decisions it set in motion.

The Message in Full

The subject message reads:

Key insight from the K2-Thinking run: it used disable_cuda_graph=True, moe_runner_backend='auto', fp4_gemm_runner_backend='auto', attention_backend='triton', page_size=1, and no --enable-flashinfer-allreduce-fusion. It also had max_running_requests=2048 (uncapped). It reached 5,816 tok/s peak.

>

The critical difference with our current GLM-5 setup: 1. We're using --max-running-requests 64 (severely limiting concurrency!) 2. We're using --attention-backend flashinfer (K2 used triton) 3. We have cuda graphs enabled (K2 had them disabled)

>

The --max-running-requests 64 is the most likely bottleneck at high concurrency. Let me also check what the FlashInfer autotune does, then enable it and raise max-running-requests.

This is followed by a structured todo list showing three completed items (checking server status, running higher concurrency benchmarks, and enabling FlashInfer CUTLASS MoE autotune by patching model_runner.py) and one in-progress item (restarting the server with autotune and higher max-running-requests).

Context and Motivation: Why This Message Was Written

To understand why this message exists, one must appreciate the situation immediately preceding it. The assistant had been engaged in a multi-session effort to deploy the GLM-5-NVFP4 model — a massive mixture-of-experts (MoE) architecture with 256 experts, 78 hidden layers, and NVFP4 quantization — on eight RTX PRO 6000 Blackwell GPUs. The deployment had already overcome numerous obstacles: NaN crashes during decode (resolved by selecting working attention backends), PCIe P2P latency bottlenecks in a Proxmox VM environment (circumvented by moving to an LXC container), and CUDA initialization failures (fixed by disabling HMM in the nvidia_uvm module).

Despite these successes, the assistant was stuck at a frustrating plateau. The server was achieving roughly 880 total tokens per second at 256 concurrency — respectable, but far below what the hardware should deliver. The user had explicitly noted the problem in [msg 657]: "still quite low power and lowish pcie bw, probably want to tune kernels." GPU power draw was hovering around 83W per GPU, a tiny fraction of the 600W TDP. The GPUs were barely breaking a sweat.

The assistant had been investigating MoE kernel tuning, examining the FlashInfer CUTLASS backend, and reading through the local research repository at /home/theuser/glm-kimi-sm120-rtx6000bw/ — a collection of artifacts from a prior successful deployment of the Kimi K2-Thinking model on the same hardware. In [msg 668] and [msg 669], the assistant had been parsing the K2-Thinking final benchmark log, searching for the configuration that had achieved 5,816 tok/s peak throughput.

Message 670 is the moment where the assistant synthesized those findings into actionable insight.

The Reasoning Process: A Detective's Chain of Inference

The assistant's reasoning in this message follows a classic diagnostic pattern: compare a working system (K2-Thinking) against a struggling system (current GLM-5 setup), identify the differences, rank them by likely impact, and formulate a test.

The first step is extracting the K2-Thinking configuration from the benchmark log. The assistant identifies five key parameters: disable_cuda_graph=True, moe_runner_backend='auto', fp4_gemm_runner_backend='auto', attention_backend='triton', page_size=1, and the absence of --enable-flashinfer-allreduce-fusion. But the most striking discovery is max_running_requests=2048 — effectively uncapped.

The assistant then performs a side-by-side comparison with the current GLM-5 setup, listing three differences:

  1. --max-running-requests 64 vs 2048: This is the most dramatic discrepancy. A factor of 32x in the maximum number of concurrent requests the server will accept. The assistant immediately flags this as "severely limiting concurrency!"
  2. --attention-backend flashinfer vs triton: The K2-Thinking run used the triton attention backend, while the GLM-5 setup was using flashinfer. This is a meaningful difference — different attention kernels have different performance characteristics on SM120 (the consumer Blackwell architecture).
  3. CUDA graphs enabled vs disabled: The GLM-5 setup had CUDA graphs enabled (the default), while K2-Thinking explicitly disabled them with --disable-cuda-graph. The assistant then makes a judgment call: "The --max-running-requests 64 is the most likely bottleneck at high concurrency." This is a hypothesis, not a proven fact. But it's a well-reasoned one. The reasoning is straightforward: if the server can only handle 64 concurrent requests, then at any load above 64, requests will queue up and throughput will be artificially capped. The GPU will spend more time idle waiting for work than actually computing.

Assumptions Embedded in the Message

Several assumptions underpin the assistant's reasoning in this message, and it's worth examining them critically.

Assumption 1: The K2-Thinking configuration is a valid reference point. The assistant assumes that the K2-Thinking deployment on the same hardware (8x RTX PRO 6000 Blackwell) with a similar model (NVFP4-quantized MoE) represents a ceiling that the GLM-5 deployment should approach. This is a reasonable assumption — the hardware is identical, the quantization format is the same, and the model architectures are similar (both are large MoE transformers). However, there are differences: GLM-5 has 256 experts vs K2-Thinking's different expert count, different hidden sizes, and different layer counts. The assistant implicitly assumes these differences are secondary to the configuration parameters.

Assumption 2: Concurrency is the primary bottleneck. The assistant singles out --max-running-requests 64 as "the most likely bottleneck." This is a strong claim. It could be wrong — the bottleneck could instead be in the MoE kernel implementation, the attention backend, or the PCIe interconnect. The assistant hedges by noting there are three differences, but the todo list and subsequent actions show a clear prioritization of the concurrency fix.

Assumption 3: The autotune can be safely enabled. The assistant plans to "check what the FlashInfer autotune does, then enable it." But the source code has a TODO comment (visible in [msg 672]) warning that "flashinfer_cutlass will cause some flashinfer compilation errors. To be fixed." The assistant acknowledges this risk implicitly by planning to "try it, revert if it fails," but the message doesn't explicitly discuss the failure mode.

Assumption 4: Raising max-running-requests won't cause other problems. The assistant assumes that simply raising the concurrency limit will translate to higher throughput, without causing memory pressure, scheduling issues, or other resource contention problems. This is a plausible assumption given that the K2-Thinking run used 2048 without apparent issues, but it's not guaranteed.

Input Knowledge Required

To fully understand this message, a reader needs knowledge spanning several domains:

Model architecture knowledge: Understanding that GLM-5 is a mixture-of-experts (MoE) transformer with 256 experts, top-8 routing, and NVFP4 quantization. The MoE architecture means that each token is processed by only a subset of the model's parameters, making it memory-bandwidth-bound rather than compute-bound — which makes concurrency especially important for saturating the GPUs.

Hardware knowledge: Understanding the RTX PRO 6000 Blackwell GPU's SM120 architecture, its 600W TDP, and the PCIe topology constraints. The LXC container setup was specifically chosen to bypass virtualization overhead and enable GPU P2P access.

SGLang server architecture: Knowing that --max-running-requests controls the maximum number of simultaneous in-flight requests the server will handle, and that this directly limits the batch size that the GPU can work on. Also understanding the difference between attention backends (flashinfer vs triton) and the role of CUDA graphs in reducing kernel launch overhead.

The prior K2-Thinking deployment: The assistant had access to a local research repository containing logs, configs, and benchmark results from a previous successful deployment of the Kimi K2-Thinking model. This repository was the key reference that enabled the insight.

FlashInfer autotune: Understanding that FlashInfer has an autotuning mechanism that benchmarks different kernel configurations at startup and selects the fastest one for the specific hardware. The autotune was being skipped for the flashinfer_cutlass backend due to a known compilation issue.

Output Knowledge Created

This message creates several valuable pieces of knowledge:

A prioritized diagnosis: The message explicitly ranks the three configuration differences by likely impact, with --max-running-requests at the top. This prioritization guides all subsequent actions.

A testable hypothesis: The claim that raising max-running-requests from 64 to 2048 will significantly improve throughput is a hypothesis that can be tested empirically — and indeed, the assistant proceeds to test it in subsequent messages.

A structured action plan: The todo list transforms the insight into concrete steps: check server status, run higher concurrency benchmarks, enable FlashInfer CUTLASS MoE autotune by patching model_runner.py, and restart the server with the new parameters.

A documented comparison: By writing out the side-by-side comparison of K2-Thinking vs GLM-5 configurations, the message creates a permanent record of the diagnostic reasoning. This is valuable not just for the current session but for anyone who later needs to understand why certain configuration choices were made.

The Thinking Process Visible in the Message

The assistant's thinking process is remarkably transparent in this message. We can observe several cognitive patterns:

Pattern recognition: The assistant recognizes that the K2-Thinking configuration is a known-good reference point and uses it as a template for diagnosis. This is a form of analogical reasoning — "this similar system worked with these settings, so our system should work with similar settings."

Abductive reasoning: The assistant reasons backward from the symptom (low throughput) to the most likely cause (limited concurrency). This is abduction — inference to the best explanation. The assistant considers multiple possible causes (the three listed differences) and selects the one that seems most explanatory.

Prioritization under uncertainty: The assistant doesn't know for certain which difference is the bottleneck, but it makes a judgment call and acts on it. The todo list shows a pragmatic approach: try the most impactful change first, then iterate.

Self-correction: The assistant had previously been investigating MoE kernel tuning (see [msg 662]), but the K2-Thinking log analysis shifted the focus to concurrency. This shows a willingness to abandon a line of investigation when new evidence points in a different direction.

The Aftermath: What Happened Next

The immediate next message ([msg 671]) shows the assistant executing the plan: it finds the autotune gating code in model_runner.py and patches it to include flashinfer_cutlass in the autotune list. The subsequent messages show the server restart with --max-running-requests 1024, --disable-cuda-graph, and --disable-radix-cache, resulting in throughput jumping from ~880 tok/s to ~1,950 at 256 concurrency, ~2,800 at 512, and ~3,740 at 1024 concurrency — nearly a 4x improvement.

However, the story doesn't end there. Despite the dramatic throughput gains, GPU power draw remained around 250W out of 600W TDP, indicating that the hardware was still underutilized. This led to further investigation into FlashInfer allreduce fusion, which turned out to be unsupported on SM120, and a subsequent attempt to patch the flashinfer kernel that actually degraded performance. The assistant's diagnosis was correct — concurrency was indeed the primary bottleneck — but it was not the only one.

Conclusion

Message 670 exemplifies the kind of diagnostic reasoning that separates effective optimization from random tweaking. By systematically comparing a working configuration against a struggling one, ranking the differences by likely impact, and formulating a testable hypothesis, the assistant transformed a frustrating plateau into a clear path forward. The message also illustrates the importance of having good reference points — the K2-Thinking research repository, built from a prior deployment, was the key that unlocked the insight.

The assumptions embedded in the message — that concurrency was the primary bottleneck, that the autotune could be safely enabled, that the K2-Thinking configuration was a valid reference — were largely correct, though not perfectly so. The concurrency fix worked spectacularly, but the autotune and allreduce fusion attempts would later reveal deeper hardware limitations. This is the nature of systems optimization: each answer raises new questions, and the journey from 880 tok/s to 3,740 tok/s is never the end of the story.