Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion vllm/compilation/passes/fusion/allreduce_rms_fusion.py
Original file line number Diff line number Diff line change
Expand Up @@ -939,7 +939,7 @@ def replacement(self):
def _replacement(
input: torch.Tensor, weight: torch.Tensor
) -> tuple[torch.Tensor, torch.Tensor]:
residual = torch.empty_like(input)
residual = torch.zeros_like(input)
allreduce = self.FUSED_AR_RMSNORM_OP(
input_=input,
residual=residual,
Expand Down
12 changes: 10 additions & 2 deletions vllm/model_executor/layers/layernorm.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,15 +90,23 @@ def forward_native(
x,
self.weight.data if self.pass_weight else None,
self.variance_epsilon,
self.variance_size_override,
*(

@ProExpertProg ProExpertProg May 7, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's just fix the patterns in the pass instead

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Investigated whether the variance_size_override argument mismatch between layernorm.py (4 args) and the fusion patterns (3 args) causes a pattern-matching failure. It does not on latest nightly (sha256:18aa8ce6c3f4bf61ae220750311f0f9526bd64e1b419052817accfca625c5f90).

PyTorch's C++ boxed dispatch layer (parseIValuesToPyArgsKwargs in torch/csrc/autograd/python_variable.cpp) strips trailing positional arguments that equal their schema defaults. Since variance_size has default=None in the op schema and variance_size_override is None for all standard LLM models, the 4th argument is stripped before it reaches the FX graph the fusion passes operate on. This behavior has been in PyTorch since May 2022 (55f55a4, PR #75905).

Graph dump evidence — tested on vllm/vllm-openai-rocm:nightly (fb1ac80, PyTorch 2.10.0+git8514f05) with Kimi-K2-Thinking-MXFP4 at TP=4, fresh container with zero variance_size patches:

__compiled_fn_1.BEFORE_PRE_GRAD.0.py (Dynamo trace) — rms_norm has 4 args, trailing None from self.variance_size_override:
rms_norm_default = torch.ops.vllm_ir.rms_norm.default(all_reduce, _get_data_attr, 1e-05, None)
__compiled_fn_1.Forward_graph.0.py (AOT Autograd re-trace via C++ dispatch) — trailing None stripped, 3 args:
rms_norm = torch.ops.vllm_ir.rms_norm.default(all_reduce, alias, 1e-05)
__compiled_fn_1.AFTER_POST_GRAD.0.py (post-fusion) — correctly replaced with the fused AITER op:

rocm_aiter_fused_allreduce_rmsnorm_default_121 = torch.ops.vllm.rocm_aiter_fused_allreduce_rmsnorm.default(where, full_default_2, arg3_1, 1e-05)

245 vllm_ir.rms_norm ops pre-fusion → 366 rocm_aiter_fused_allreduce_rmsnorm ops post-fusion (includes fused_add_rms_norm variants). GSM8K accuracy on Kimi-K2-Thinking-MXFP4: 0.948 (250 samples, 5-shot).

Recommendation: The variance_size_override fix is not needed. The empty_like → zeros_like fix already merged #41972

Does this align with your observation @akii96? if so i will close this PR

(self.variance_size_override,)
if self.variance_size_override is not None
else ()
),
)
else:
return ir.ops.fused_add_rms_norm.maybe_inplace(
x,
residual,
self.weight.data if self.pass_weight_add else None,
self.variance_epsilon,
self.variance_size_override,
*(
(self.variance_size_override,)
if self.variance_size_override is not None
else ()
),
)

def forward_cuda(
Expand Down
Loading