Skip to content

Commit 58ae3c8

Browse files
committed
[None][perf] Remove redundant allreduce
1 parent d4f56c8 commit 58ae3c8

1 file changed

Lines changed: 52 additions & 12 deletions

File tree

tensorrt_llm/_torch/models/modeling_deepseekv4.py

Lines changed: 52 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,18 @@ def _resolve_enable_fused_hc(config: PretrainedConfig) -> bool:
234234
return bool(getattr(config, "enable_fused_hc", True))
235235

236236

237+
def _resolve_skip_premoe_allreduce() -> bool:
238+
"""Resolve whether to skip the redundant PRE_MOE_FUSION allreduce.
239+
240+
When enabled (default), the RMSNorm is folded into hc_ffn.fused_hc's
241+
epilogue and the allreduce in forward_MoE is skipped — the data is
242+
already full after attention's internal o_b_proj allreduce.
243+
Set TRTLLM_DSV4_SKIP_PREMOE_ALLREDUCE=0 for ablation (baseline behavior).
244+
"""
245+
env = os.environ.get("TRTLLM_DSV4_SKIP_PREMOE_ALLREDUCE", "1")
246+
return env not in ("0", "false", "False")
247+
248+
237249
def _copy_deepseek_v4_fused_a_weight_scale(
238250
module: Linear, fused_a: torch.Tensor, fused_a_scale: torch.Tensor
239251
) -> None:
@@ -1860,6 +1872,13 @@ def __init__(
18601872
# layers already take). Env var TRTLLM_MHC_ENABLE_FUSED_HC overrides the
18611873
# config attr (set to "0" to force-disable for validation/rollback).
18621874
self.enable_fused_hc = _resolve_enable_fused_hc(config)
1875+
# Skip-premoe-allreduce: when fused_hc is active AND PRE_MOE_FUSION is
1876+
# on, fold post_attention_layernorm into hc_ffn.fused_hc and skip the
1877+
# redundant allreduce in forward_MoE (the data is already full after
1878+
# attention's internal o_b_proj allreduce).
1879+
self.skip_premoe_allreduce = (
1880+
_resolve_skip_premoe_allreduce() and self.enable_fused_hc
1881+
)
18631882
self.next_layer_layernorm: RMSNorm = None
18641883
# Finalized in DeepseekV4ForCausalLM.post_load_weights once the full layer
18651884
# list is visible: a layer may defer its hc_ffn.post_mapping only if
@@ -2000,11 +2019,26 @@ def forward(
20002019
if spec_metadata is not None and spec_metadata.is_layer_capture(self.layer_idx):
20012020
self.fusion_config.POST_MOE_FUSION = False
20022021
if self.enable_fused_hc:
2022+
# When skip_premoe_allreduce is active, fold post_attention_layernorm
2023+
# into fused_hc so layer_input emerges already RMSNorm-normalized.
2024+
# This lets us skip the redundant allreduce+norm in forward_MoE.
2025+
_norm_w = (
2026+
self.post_attention_layernorm.weight
2027+
if self.skip_premoe_allreduce and self.fusion_config.PRE_MOE_FUSION
2028+
else None
2029+
)
2030+
_norm_eps = (
2031+
self.post_attention_layernorm.variance_epsilon
2032+
if _norm_w is not None
2033+
else 0.0
2034+
)
20032035
residual, post_mix, comb_mix, layer_input = self.hc_ffn.fused_hc(
20042036
x_prev=x_attn,
20052037
residual_prev=residual,
20062038
post_mix_prev=post_mix,
20072039
comb_mix_prev=comb_mix,
2040+
norm_weight=_norm_w,
2041+
norm_eps=_norm_eps,
20082042
)
20092043
else:
20102044
# Break fused_hc into post_mapping and pre_mapping as separate ops.
@@ -2104,18 +2138,24 @@ def _run_MoE(hidden_states, hidden_states_fp4, do_finalize, input_ids):
21042138
)
21052139

21062140
if self.fusion_config.PRE_MOE_FUSION:
2107-
# In DeepSeek-V4 the external residual connection is handled by mHC
2108-
# (hc_ffn.post_mapping), so there is no residual to add here.
2109-
# Use fused allreduce + RMSNorm (no residual addition).
2110-
hidden_states = self.allreduce(
2111-
hidden_states,
2112-
all_reduce_params=AllReduceParams(
2113-
fusion_op=AllReduceFusionOp.RMS_NORM,
2114-
norm_weight=self.post_attention_layernorm.weight,
2115-
eps=self.post_attention_layernorm.variance_epsilon,
2116-
trigger_completion_at_end=False,
2117-
),
2118-
)
2141+
if self.skip_premoe_allreduce:
2142+
# Optimization: RMSNorm was already folded into hc_ffn.fused_hc's
2143+
# epilogue, and the data is already full (attention's o_b_proj
2144+
# allreduced it). Skip the redundant allreduce+norm entirely.
2145+
pass
2146+
else:
2147+
# Baseline: fused allreduce + RMSNorm (no residual addition).
2148+
# In DeepSeek-V4 the external residual connection is handled by
2149+
# mHC (hc_ffn.post_mapping), so there is no residual to add here.
2150+
hidden_states = self.allreduce(
2151+
hidden_states,
2152+
all_reduce_params=AllReduceParams(
2153+
fusion_op=AllReduceFusionOp.RMS_NORM,
2154+
norm_weight=self.post_attention_layernorm.weight,
2155+
eps=self.post_attention_layernorm.variance_epsilon,
2156+
trigger_completion_at_end=False,
2157+
),
2158+
)
21192159
else:
21202160
# No fusion: just normalize.
21212161
hidden_states = self.post_attention_layernorm(hidden_states)

0 commit comments

Comments
 (0)