Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
33 changes: 5 additions & 28 deletions tensorrt_llm/_torch/modules/fused_moe/configurable_moe.py
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,7 @@ def determine_communication_method(
2. Validates if current AllToAll strategy can be used for given workload
3. Falls back to AllGather if current strategy cannot be used (logs info message)

After calling this method, use _is_using_alltoall() to check which method is active.
After calling this method, use enable_alltoall to check which method is active.

Args:
all_rank_num_tokens: Token counts per rank
Expand Down Expand Up @@ -347,23 +347,6 @@ def determine_communication_method(
# Switch to AllGather (always works)
self.comm = AllGatherReduceScatter(mapping=self.mapping)

def _is_using_alltoall(self) -> bool:
"""
Check if current communication strategy uses alltoall

Returns:
True: Strategy uses alltoall (NVLINK, DeepEP, etc.)
False: Strategy uses allgather (AllGatherReduceScatter or None)

Note: Can be called anytime. If comm is None, returns False (no alltoall).
Typically called after determine_communication_method() to get accurate result.
"""
if self.comm is None:
return False # No strategy means no alltoall

# AllGather uses allgather, all others use alltoall
return not isinstance(self.comm, AllGatherReduceScatter)

def _create_comm_strategy_auto(self) -> Communication:
"""
Auto-create the best communication strategy based on hardware and configuration
Expand Down Expand Up @@ -792,11 +775,7 @@ def _forward_multiple_chunks(

Same as original implementation - chunking logic is backend-agnostic

Note: use_all_to_all is determined internally via _is_using_alltoall()

"""
# Determine if using alltoall
use_all_to_all = self._is_using_alltoall()
# ========== Chunk preparation ==========
if self.use_dp:
# When using DP: need all ranks' token counts for reducescatter
Expand All @@ -810,7 +789,7 @@ def _forward_multiple_chunks(
chunk_size_list = all_rank_chunk_size_list[self.rank]

# For alltoall, replace 0 with 1 (avoid empty tensor)
if use_all_to_all:
if self.enable_alltoall:
all_rank_num_tokens_list = [
[1 if val == 0 else val for val in val_list]
for val_list in all_rank_num_tokens_list
Expand All @@ -824,7 +803,7 @@ def _forward_multiple_chunks(
router_logits_list = router_logits.split(chunk_size_list)

# Determine if we need multiple streams for overlapped execution
use_multi_stream = not use_all_to_all and self.aux_stream is not None
use_multi_stream = not self.enable_alltoall and self.aux_stream is not None

# ========== Setup auxiliary stream ==========
if use_multi_stream:
Expand Down Expand Up @@ -1064,17 +1043,15 @@ def _get_backend_kwargs(
# Only the non-alltoall case is considered for profiling in the warmup phase.
# Therefore, to get the correct tactics during the actual inference, the inputs to the tuner
# should be the same as when not using alltoall.
if self._is_using_alltoall():
kwargs["enable_alltoall"] = self.enable_alltoall
if self.enable_alltoall:
if all_rank_num_tokens is not None:
kwargs["tuner_num_tokens"] = sum(all_rank_num_tokens)
else:
kwargs["tuner_num_tokens"] = (
x.shape[0] * self.mapping.tp_size if x is not None else None
)
kwargs["tuner_top_k"] = self.routing_method.top_k
else:
kwargs["tuner_num_tokens"] = None
kwargs["tuner_top_k"] = None

# Get moe_output for NVLinkOneSided backend
kwargs["moe_output"] = self._get_nvlink_onesided_moe_output(
Expand Down
2 changes: 2 additions & 0 deletions tensorrt_llm/_torch/modules/fused_moe/create_moe.py
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ def create_moe_backend(
swiglu_beta=swiglu_beta,
swiglu_limit=swiglu_limit,
init_load_balancer=init_load_balancer,
without_comm=without_comm,
activation_type=activation_type,
)
elif moe_cls == WideEPMoE:
Expand Down Expand Up @@ -255,6 +256,7 @@ def create_moe_backend(
weight_loading_mode=weight_loading_mode,
apply_router_weight_on_input=apply_router_weight_on_input,
layer_idx=layer_idx,
without_comm=without_comm,
)
elif moe_cls == TritonFusedMoE:
assert not apply_router_weight_on_input, "apply_router_weight_on_input is not supported in TritonFusedMoE."
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,7 @@ def run_moe(
tuner_num_tokens: Optional[int] = None,
tuner_top_k: Optional[int] = None,
moe_output: Optional[torch.Tensor] = None,
enable_alltoall: Optional[bool] = None,
) -> torch.Tensor:
"""
Run MoE computation with Cutlass backend.
Expand All @@ -421,6 +422,7 @@ def run_moe(
tuner_num_tokens: Number of tokens for profiling tuner (optional)
tuner_top_k: Top-k value for profiling tuner (optional)
moe_output: Pre-allocated output buffer (optional)
enable_alltoall: Whether alltoall communication is enabled (optional). If None, defaults to self.enable_alltoall.

Returns:
final_hidden_states: Output tensor from MoE computation
Expand All @@ -433,6 +435,9 @@ def run_moe(
elif self.has_w4a16_mxfp4:
weight_dtype = torch.uint8

if enable_alltoall is None:
enable_alltoall = self.enable_alltoall

result = torch.ops.trtllm.fused_moe(
x,
token_selected_experts,
Expand All @@ -454,7 +459,7 @@ def run_moe(
ep_rank=self.ep_rank,
cluster_size=self.cluster_size,
cluster_rank=self.cluster_rank,
enable_alltoall=self.enable_alltoall,
enable_alltoall=enable_alltoall,
use_deepseek_fp8_block_scale=self.has_deepseek_fp8_block_scales,
use_w4_group_scaling=self.has_w4afp8 or self.has_w4a16_mxfp4,
use_int8_woq_per_channel=self.has_int8_woq_per_channel,
Expand Down
Loading