[Comm] Share the CuTe DSL AR fusion core and wire it for DeepSeek-V3 / GLM-5.x - #37196
Draft
kpham-sgl wants to merge 2 commits into
Draft
[Comm] Share the CuTe DSL AR fusion core and wire it for DeepSeek-V3 / GLM-5.x#37196kpham-sgl wants to merge 2 commits into
kpham-sgl wants to merge 2 commits into
Conversation
kpham-sgl
force-pushed
the
cutedsl-ar-fusion-glm-qwen
branch
from
August 31, 2026 05:56
47076e1 to
44f7ae7
Compare
The fusion mechanism that landed with the Qwen3.5 stack is almost entirely architecture-agnostic: the deferred-MoE handoff record, the process-local workspace handle, and the LayerCommunicator hooks that route an eligible layer into the fused collective. Exactly one thing in it is Qwen-specific -- `gemma_weight`, because Qwen3.5 normalizes with GemmaRMSNorm while the DeepSeek-V3 family uses a plain RMSNorm. Move the generic parts to layers/moe/cutedsl_ar_fusion.py and reduce the per-architecture surface to one class attribute, NORM_WEIGHT_ATTR, read through a _norm_gamma() hook at the four sites that touched gemma_weight directly. qwen35_flashinfer_fusion.py stays as the Qwen flavour plus back-compat aliases, so qwen2_moe, qwen3_5 and the registered Qwen test import exactly what they did before. Two things that looked Qwen-specific but are not: weight_bias=0.0 is right for both flavours (the kernel computes x * (gamma + weight_bias), and neither wants a bias), and consuming the final layer's handoff with the model's own final norm is generic behaviour.
kpham-sgl
force-pushed
the
cutedsl-ar-fusion-glm-qwen
branch
6 times, most recently
from
August 31, 2026 20:49
7c5887d to
9f1aff1
Compare
Only Qwen3.5 could reach the CuTe DSL fused collective. Give the DeepSeek-V3
family the same path on the shared core, so the MoE finalize, the
shared-expert add and the post-experts all-reduce fold into the next layer's
input RMSNorm. GLM-5.x rides it unchanged: GlmMoeDsaForCausalLM subclasses
DeepseekV2ForCausalLM and reuses its decoder layer and MoE block.
DeepseekV2MoE already defers its finalize whenever the runner supports it,
then materializes it locally with moe_finalize_fuse_shared. The only new
decision is materialize-here versus hand-off, so the MoE keeps its signature
and reads a new per-layer flag published by the decoder next to
fuse_mlp_allreduce / mlp_reduce_scatter, which the same block already sets.
That flag is graph-visible: the read sits inside compiled MoE code.
- deepseek_flashinfer_fusion.py is the family's flavour of the shared core:
a plain RMSNorm, so the fused kernel reads layernorm.weight.
- Unlike Qwen3.5's shared expert this family's carries no sigmoid gate, so
it goes over unmodified.
- The decoder asks the communicator whether the layer is eligible and
returns the handoff untouched: postprocess_layer and the
_sglang_needs_allreduce_fusion flag both want a tensor.
- The model installs one workspace handle across its layers (the workspace
is compiled per hidden/top_k/eps, which every MoE layer shares) and
DeepseekV2ForCausalLM forwards the pre-capture hook to it, since
BaseRunner looks the hook up on the top-level module.
Off unless SGLANG_FLASHINFER_MNNVL_CUTEDSL_AR_FUSION=1, matching the Qwen
path. Per-layer eligibility is unchanged from the shared core: no DP
attention, no a2a backend, no CP, unscattered input, tp_size > 1.
kpham-sgl
force-pushed
the
cutedsl-ar-fusion-glm-qwen
branch
from
August 31, 2026 20:54
9f1aff1 to
c3b51b6
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation
The FlashInfer MNNVL CuTe DSL AR fusion landed with the Qwen3.5 stack: it folds the MoE finalize, the shared-expert add and the post-experts all-reduce into the next layer's input RMSNorm. Only Qwen3.5 can reach it. This gives the DeepSeek-V3 family the same path — which covers GLM-5.x unchanged, since
GlmMoeDsaForCausalLMsubclassesDeepseekV2ForCausalLMand reuses its decoder layer and MoE block.Draft: none of this has run on hardware. See Testing status.
Modifications
1. Extract the shared core (
layers/moe/cutedsl_ar_fusion.py).qwen35_flashinfer_fusion.pywas 347 lines of which almost everything is architecture-agnostic — the handoff record, the workspace handle, and theLayerCommunicatorhooks and eligibility predicates. Exactly one thing in it is Qwen-specific:gemma_weight, because Qwen3.5 normalizes withGemmaRMSNormand DeepSeek-V3/GLM use a plainRMSNorm. It appeared at four sites (ahasattrguard and a read inprepare_attn, a read inprepare_mlp, ahasattrinshould_use_all_reduce_rms_norm).The generic parts move out, and the per-architecture surface becomes one class attribute:
All four call sites now go through a
_norm_gamma(layernorm)hook.qwen35_flashinfer_fusion.pykeepsQwen35MoeFinalizeHandoff/Qwen35FlashInferFusionServiceas aliases, soqwen2_moe.py,qwen3_5.pyand the registeredtest_qwen35_flashinfer_fusion.pyimport exactly what they did before — no behaviour change on the Qwen path.Two things that looked Qwen-specific and are not, now documented as such:
weight_bias=0.0was justified as "GemmaRMSNorm.gemma_weight is already checkpoint weight + 1". The value is right for both: the kernel computesx * (gamma + weight_bias)and neither flavour wants a bias.2. Wire DeepSeek-V3 / GLM-5.x.
DeepseekV2MoE.forwardthreadsdefer_finalizeinto the dual-stream path, which returns the unfinalized handoff instead of callingfinalize_flashinfer_trtllm_deferred_output. Unlike Qwen3.5's shared expert, this family's carries no sigmoid gate, so it goes over unmodified — no_gate_shared_output_out_of_placeequivalent is needed._shared_expert_tp1adds the shared output after the all-reduce precisely because it is replicated, so folding it into the fused add would count it once per rank.postprocess_layerand the_sglang_needs_allreduce_fusionflag both want a real tensor.DeepseekV2ForCausalLMforwards the pre-capture hook, sinceBaseRunnerlooks it up on the top-level module.Off unless
SGLANG_FLASHINFER_MNNVL_CUTEDSL_AR_FUSION=1, matching the Qwen path. Per-layer eligibility is inherited unchanged: no DP attention, no a2a backend, no CP, unscattered input,tp_size > 1.Testing status
Nothing has run on hardware — the kernels need a Blackwell MNNVL fabric and this was developed without a GPU. What has been checked:
pre-commit(isort/ruff/black/codespell) clean.test/registered/unit/layers/moe/test_cutedsl_ar_fusion.py) covering the extraction: each family resolves its own RMSNorm weight,_norm_gammareturnsNoneon the wrong flavour so the predicates decline rather than raise, both communicators subclass the shared core, and the Qwen aliases still resolve.test_qwen35_flashinfer_fusion.pyimports are unchanged by design.Before this leaves draft: GSM8K + decode throughput on GLM-5.x on B300/GB300 with the env var on, against the same run with it off; and a Qwen3.5 run to confirm the extraction is a no-op for it.
Known gaps
DSACPLayerCommunicatorbranch is untouched, sodsa_enable_prefill_cp/mla_enable_prefill_cplayers keep the ordinary path.forward_normalis unchanged.Related
cute-dslvalue on--flashinfer-allreduce-fusion-backend, plus a measured B300 tuning table. It predates the Qwen stack landing, so it now duplicates the in-tree module; its tuning is the part worth carrying over here.CI States
Latest PR Test (Base): ❌ Run #33438515949
Latest PR Test (Extra): ❌ Run #33438515579
Latest PR Test (AMD ROCm 7.2): ❌ Run #33438515720