The Art of Knowing When to Pivot: A Deep Dive into MoE Kernel Analysis
In the course of deploying a large language model across distributed infrastructure, few moments are as critical as the one where an engineer realizes they have been optimizing the wrong thing. Message 6494 in this opencode session captures exactly such a moment — a carefully reasoned analysis that synthesizes the results of multiple failed experiments, identifies the true bottleneck, and redirects effort toward a more promising approach. This message is a masterclass in diagnostic reasoning under uncertainty, and it reveals the kind of systems-level thinking that separates effective optimization from busywork.
The Context: A MoE Kernel Tuning Odyssey
To understand message 6494, we must first appreciate the journey that led to it. The assistant had been working on deploying the Qwen3.5-122B-A10B-FP8 model — a 122-billion-parameter Mixture-of-Experts (MoE) model with 256 experts — across two NVIDIA DGX Spark nodes. After successfully getting the model serving and achieving reasonable throughput, the assistant turned to optimization.
The MoE layer is a natural target for performance tuning in any MoE-based model. SGLang uses Triton-based fused MoE kernels that can be autotuned for specific GPU architectures. The assistant had identified that the RTX PRO 6000 Blackwell GPUs (SM120 architecture) lacked optimized kernel configurations, so the server was falling back to default configurations or emitting warnings about sub-optimal configs.
The initial approach was straightforward: run the existing autotuning script (tuning_fused_moe_triton.py) to find optimal kernel parameters. But this hit a bug — the script's common_utils.py had a subtle issue where it redirected the model config to text_config for encoder-decoder models, but text_config.architectures was None for the Qwen3.5 architecture, causing a crash. The assistant patched this (msg 6478), then attempted to run the tuning. The tuning timed out after 10 minutes for a single batch size — the script was testing 1,920 configurations with 100 iterations each, an exhaustive search that was prohibitively slow.
Pivoting to a more practical approach, the assistant copied the existing B200 (NVIDIA Blackwell data center GPU) kernel configuration as a starting point, reasoning that both B200 and RTX PRO 6000 are Blackwell architecture (SM100 vs SM120) and should have similar optimal parameters. The config was deployed and benchmarked (msg 6491), yielding throughput numbers of approximately 122 tok/s at concurrency 1 and 1,566 tok/s at concurrency 64.
The result: no measurable improvement over the default configuration.
The Analysis: Why the B200 Config Didn't Help
Message 6494 opens with the assistant's diagnosis of this non-result:
For BF16 with small M (≤ E=256), the default isBLOCK_SIZE_M=16, BLOCK_SIZE_N=32, BLOCK_SIZE_K=64, GROUP_SIZE_M=1which is quite close to the B200 optimized config. The B200 config for small batches usesN=64, K=64vs defaultN=32, K=64. This is likely why there was no measurable difference — the defaults are already reasonable.
This is a crucial observation. The assistant had just read the default configuration code (msg 6493) and could now compare the two configurations side-by-side. The B200 config used BLOCK_SIZE_N=64 while the default used BLOCK_SIZE_N=32 — both with BLOCK_SIZE_K=64. The difference in N dimension (the intermediate size of each expert) was the only meaningful delta, and it turned out not to matter for this workload.
But the assistant doesn't stop at the surface-level explanation. The message continues with a deeper structural insight:
The MoE kernel is probably not the bottleneck for this model. With E=256 experts but only N=256 per-expert intermediate size (very small matrices per expert), the GEMM is memory-bound not compute-bound. The kernel config doesn't matter much when the matrices are tiny.
This is the key analytical leap. The assistant has internalized the model's architecture and mapped it to the hardware's performance characteristics. Let's unpack what this means.
The Qwen3.5-122B-A10B model has 256 experts, each with an intermediate size (N) of 256 and a hidden size (K) of 3,072. In the fused MoE kernel, each expert performs a matrix multiplication of dimensions M×K (where M is the number of tokens routed to that expert) by K×N. With N=256, each expert's weight matrix is only 256×3,072 — approximately 1.5 million parameters per expert. For comparison, a typical attention projection in a large model might be 8,192×8,192 (67 million parameters).
When matrices are this small, the GPU's compute units are not the limiting factor. The bottleneck shifts to memory bandwidth — how fast the GPU can load the weight matrices from HBM into SRAM for computation. Triton kernel configurations (block sizes, number of warps, number of pipeline stages) primarily affect compute efficiency, not memory bandwidth. When the computation is memory-bound, the kernel configuration has little impact on overall performance because the GPU cores are spending most of their time waiting for data, not computing.
This insight is grounded in the "roofline model" of performance analysis, which classifies operations as either compute-bound or memory-bound. The assistant correctly identifies that the MoE GEMMs for this model fall squarely in the memory-bound regime, making kernel autotuning a low-leverage activity.
The Proposed Next Steps: A Two-Pronged Approach
Having diagnosed why the B200 config didn't help, the assistant proposes a refined approach:
Let me now focus on something that could actually help — running the tuning with a focus on realistic batch sizes and let me also try a smarter approach. Instead of full autotuning, let me write a focused benchmark script that tests a handful of promising configs around the B200 optimums for the specific batch sizes we care about (1-64 for agentic coding).
This is a reasonable intermediate step. The assistant acknowledges that the full autotuning was too expensive (1,920 configs × 18 batch sizes × 100 iterations = potentially hours of computation) but doesn't want to abandon the approach entirely without trying a more targeted search. The idea is to test a small number of configurations around the known-good B200 parameters, focusing only on the batch sizes that matter for the target use case (agentic coding with concurrency 1-64).
However, even as the assistant articulates this plan, the reasoning continues to evolve:
Actually, let me step back and think about what would actually make a difference. The MoE kernel for this model has E=256, N=256 (512 with gate+up), K=3072. Each expert GEMM is 256x3072 (tiny). The real bottleneck is likely the expert selection and token routing, not the GEMM kernel itself.
This is the moment of true insight. The assistant realizes that even a perfectly tuned GEMM kernel cannot address the fundamental architectural bottleneck. For MoE models, the overhead of routing tokens to experts — computing routing probabilities, selecting top-k experts, and gathering/scattering token representations — can dominate the forward pass, especially when the expert matrices are small. The GEMM itself is fast because the matrices are tiny; the real cost is in the routing logic.
This realization leads to the final pivot:
Let me instead focus on the speculative decoding tuning which has a more direct impact on per-request latency.
Speculative decoding is a technique where a small "draft" model generates candidate tokens that are then verified by the large model in parallel. This can dramatically reduce per-request latency because multiple tokens can be generated in a single forward pass of the large model. For the Qwen3.5-122B model, which supports MTP (Multi-Token Prediction) speculation, tuning the speculation parameters (number of speculative steps, top-k values) could yield significant improvements in perceived latency — the very metric that matters most for interactive agentic coding use cases.
The Todo List: A Record of Completed Experiments
The message concludes with a todowrite block showing the assistant's task tracking:
[
{
"content": "Try --enable-fused-moe-sum-all-reduce flag — no measurable improvement",
"status": "completed",
"priority": "high"
},
{
"content": "Try --enable-flashinfer-allreduce-fusion — NOT activating on SM120, removed",
"status": "completed",
"priority": "high"
},
{
"content": "Remove allreduce fusion flag and restore original config",
"status": "completed",
"priority": "high"
},
{
"content": "Run MoE Triton kernel autotuning for RT...",
"status": "in_progress",
"priority": "high"
}
]
This todo list reveals the broader optimization campaign that frames message 6494. The assistant had already tried two other optimization flags — fused MoE all-reduce and flashinfer all-reduce fusion — both of which failed to produce improvements. The MoE kernel autotuning was the next attempt, and this message represents the moment where that attempt is being critically evaluated and ultimately deprioritized.
The first two completed items are particularly telling. --enable-fused-moe-sum-all-reduce is a technique that fuses the all-reduce communication with the MoE computation, reducing synchronization overhead. --enable-flashinfer-allreduce-fusion attempts a similar fusion using the flashinfer library. Both showed "no measurable improvement," which is consistent with the assistant's diagnosis — if the MoE GEMMs are memory-bound and the routing overhead dominates, fusing the all-reduce with the computation won't help because the computation isn't the bottleneck.
Assumptions and Their Validity
Message 6494 rests on several assumptions, most of which are well-justified:
- The B200 and RTX PRO 6000 are similar enough that B200 configs are a good starting point. This is reasonable — both are Blackwell architecture GPUs. The B200 uses the GB100 die (SM100) while the RTX PRO 6000 uses the GB202 die (SM120), but the microarchitecture is the same. The main differences are memory bandwidth, compute unit count, and memory capacity, not the fundamental execution model.
- The default config is close to optimal for small M. The assistant verified this by reading the default configuration code and comparing it to the B200 config. The only difference was
BLOCK_SIZE_N(32 vs 64), and the assistant correctly reasoned that this wouldn't matter much for memory-bound operations. - The GEMM is memory-bound, not compute-bound. This is the most important assumption and the one that drives the entire pivot. It is well-supported by the arithmetic intensity analysis: with N=256 and K=3,072, each expert GEMM processes 256×3,072 = 786,432 elements in the weight matrix and 256×M elements in the input. The compute-to-communication ratio is low, making it memory-bound.
- Expert selection and token routing are the real bottleneck. This is a reasonable hypothesis but is not directly verified in this message. The assistant doesn't run profiling to confirm this — it's a logical inference from the model architecture. This is a minor weakness in the reasoning, but it's a pragmatic one: running detailed kernel profiling would take time, and the assistant has enough information to make a high-confidence decision.
- Speculative decoding tuning will have more impact. This is the final assumption driving the pivot. It's reasonable because speculative decoding directly addresses per-request latency, which is the metric the user cares about for interactive use cases. However, it's worth noting that speculative decoding and MoE kernel optimization target different metrics — speculation improves latency while kernel tuning improves throughput. The assistant is implicitly prioritizing latency over throughput, which is the right call for agentic coding.
Knowledge Required and Created
To fully understand message 6494, one needs:
- Familiarity with Mixture-of-Experts model architecture (experts, routing, gating)
- Understanding of Triton kernel parameters (BLOCK_SIZE_M/N/K, GROUP_SIZE_M, num_warps, num_stages)
- Knowledge of the roofline model and memory-bound vs compute-bound classification
- Awareness of speculative decoding as a latency optimization technique
- Context about the Qwen3.5-122B model's specific dimensions (E=256, N=256, K=3072)
- Understanding of the B200 vs RTX PRO 6000 GPU architecture differences The message creates several pieces of output knowledge:
- The B200 MoE kernel config does not improve throughput on RTX PRO 6000 for this model
- The default config for BF16 with small M is already near-optimal
- The MoE GEMM for this model is memory-bound, making kernel tuning low-leverage
- Expert selection and routing are the likely real bottleneck
- Speculative decoding tuning is a more promising direction for latency improvement
The Thinking Process
The reasoning in message 6494 follows a clear arc: observation → analysis → deeper insight → pivot. The assistant first observes that the B200 config produced no improvement, then analyzes why by comparing the default and B200 configurations. This leads to the insight that the defaults are already reasonable for small M.
But the assistant doesn't stop there. It connects this observation to the model's architectural dimensions and identifies the root cause: the matrices are tiny, making the GEMM memory-bound. This is a structural insight that explains not just the B200 config result but also the failure of the earlier all-reduce fusion experiments.
The "stepping back" moment is particularly valuable. The assistant explicitly re-evaluates its approach mid-thought, moving from "let me try a smarter tuning approach" to "actually, let me think about what would really make a difference." This self-correction is a hallmark of effective problem-solving.
The final pivot to speculative decoding is not just a random redirection — it's a strategic choice based on the user's use case (agentic coding, which is latency-sensitive) and the model's capabilities (MTP speculation support). The assistant is optimizing for the right metric given the deployment context.
Conclusion
Message 6494 is a remarkable example of diagnostic reasoning in systems engineering. It demonstrates how a series of failed experiments can be synthesized into a deeper understanding of the system's behavior, leading to a more informed optimization strategy. The assistant correctly identifies that MoE kernel autotuning is a low-leverage activity for this particular model and deployment, and redirects effort toward speculative decoding tuning — a choice that is both technically sound and aligned with the user's priorities.
The message also serves as a cautionary tale about the seductiveness of autotuning. It's easy to reach for a brute-force search when faced with performance concerns, but as this message shows, understanding the fundamental architecture and bottleneck characteristics can save hours of computation and lead to more impactful optimizations. The assistant's willingness to "step back and think" rather than blindly continuing down the autotuning path is what makes this message a model of thoughtful engineering practice.