Skip to content

Commit 4cfb6a6

Browse files
committed
Fuse permute+pad and unpermute+unpad ops for FP8/FP4 precision
This can remove explicit padding/unpadding around GroupedMLP, which improves throughput and reduces peak memory usage Signed-off-by: xiaoxi-wangfj <690912414@qq.com>
1 parent d2bd9fa commit 4cfb6a6

5 files changed

Lines changed: 80 additions & 12 deletions

File tree

megatron/core/extensions/transformer_engine.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2328,6 +2328,14 @@ def fused_apply_rotary_pos_emb_thd(
23282328
fused_sort_chunks_by_index_with_probs = None
23292329
fused_unpermute = None
23302330

2331+
try:
2332+
from transformer_engine.pytorch.permutation import moe_permute_and_pad_with_probs
2333+
2334+
fused_permute_and_pad_with_probs = moe_permute_and_pad_with_probs
2335+
2336+
except ImportError:
2337+
fused_permute_and_pad_with_probs = None
2338+
23312339
try:
23322340
from transformer_engine.pytorch.cross_entropy import parallel_cross_entropy
23332341

megatron/core/transformer/moe/moe_utils.py

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
fused_compute_score_for_moe_aux_loss,
2020
fused_moe_aux_loss,
2121
fused_permute,
22+
fused_permute_and_pad_with_probs,
2223
fused_permute_with_probs,
2324
fused_sort_chunks_by_index,
2425
fused_sort_chunks_by_index_with_probs,
@@ -227,6 +228,8 @@ def permute(
227228
num_out_tokens: Optional[int] = None,
228229
fused: bool = False,
229230
drop_and_pad: bool = False,
231+
tokens_per_expert: Optional[torch.Tensor] = None,
232+
align_size: int = -1,
230233
):
231234
"""Permute the tokens and probs based on the mask.
232235
Tokens with the same designated expert will be grouped together.
@@ -257,11 +260,18 @@ def permute(
257260
return permuted_input, None, sorted_indices
258261

259262
if fused and probs is not None:
260-
if not HAVE_TE or fused_permute_with_probs is None:
261-
raise ValueError(
262-
"fused_permute_with_probs is not available. Please install TE >= 2.1.0."
263+
if tokens_per_expert is not None and align_size > 0:
264+
return fused_permute_and_pad_with_probs(
265+
tokens, probs, routing_map, tokens_per_expert, align_size
266+
)
267+
else:
268+
if not HAVE_TE or fused_permute_with_probs is None:
269+
raise ValueError(
270+
"fused_permute_with_probs is not available. Please install TE >= 2.1.0."
271+
)
272+
return fused_permute_with_probs(
273+
tokens, probs, routing_map, num_out_tokens=num_out_tokens
263274
)
264-
return fused_permute_with_probs(tokens, probs, routing_map, num_out_tokens=num_out_tokens)
265275

266276
num_tokens, hidden = tokens.shape
267277
num_experts = routing_map.shape[1]
@@ -315,6 +325,7 @@ def unpermute(
315325
routing_map: torch.Tensor = None,
316326
fused: bool = False,
317327
drop_and_pad: bool = False,
328+
pad_offsets: Optional[torch.Tensor] = None,
318329
):
319330
"""
320331
Restore the original order of tokens after permutation. If probs are provided, it
@@ -344,7 +355,11 @@ def unpermute(
344355
if not HAVE_TE or fused_unpermute is None:
345356
raise ValueError("fused_unpermute is not available. Please install TE >= 2.1.0.")
346357
return fused_unpermute(
347-
permuted_tokens, sorted_indices, merging_probs=probs, restore_shape=restore_shape
358+
permuted_tokens,
359+
sorted_indices,
360+
merging_probs=probs,
361+
restore_shape=restore_shape,
362+
pad_offsets=pad_offsets,
348363
)
349364

350365
_, hidden = restore_shape

megatron/core/transformer/moe/token_dispatcher.py

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1258,13 +1258,29 @@ def get_permuted_hidden_states_by_experts(self, hidden_states: torch.Tensor) ->
12581258

12591259
self.hidden_shape_before_permute = hidden_states.shape
12601260
assert self.dispatched_probs.dtype == torch.float32, "DeepEP only supports float32 probs"
1261-
hidden_states, permuted_probs, self.reversed_mapping_for_combine = permute(
1262-
hidden_states,
1263-
self.dispatched_routing_map,
1264-
probs=self.dispatched_probs,
1265-
num_out_tokens=self.tokens_per_expert.sum().item(),
1266-
fused=self.permute_fusion,
1267-
)
1261+
if self.config.moe_permute_padding_for_quantization:
1262+
(
1263+
hidden_states,
1264+
permuted_probs,
1265+
self.reversed_mapping_for_combine,
1266+
self.pad_offsets,
1267+
self.tokens_per_expert,
1268+
) = permute(
1269+
hidden_states,
1270+
self.dispatched_routing_map,
1271+
probs=self.dispatched_probs,
1272+
fused=self.permute_fusion,
1273+
tokens_per_expert=self.tokens_per_expert,
1274+
align_size=get_align_size_for_quantization(self.config),
1275+
)
1276+
else:
1277+
hidden_states, permuted_probs, self.reversed_mapping_for_combine = permute(
1278+
hidden_states,
1279+
self.dispatched_routing_map,
1280+
probs=self.dispatched_probs,
1281+
num_out_tokens=self.tokens_per_expert.sum().item(),
1282+
fused=self.permute_fusion,
1283+
)
12681284
if self.router_dtype == "fp64":
12691285
permuted_probs = permuted_probs.to(torch.float64)
12701286
return hidden_states, permuted_probs
@@ -1276,6 +1292,9 @@ def get_restored_hidden_states_by_experts(self, hidden_states: torch.Tensor) ->
12761292
restore_shape=self.hidden_shape_before_permute,
12771293
routing_map=self.dispatched_routing_map,
12781294
fused=self.permute_fusion,
1295+
pad_offsets=(
1296+
self.pad_offsets if self.config.moe_permute_padding_for_quantization else None
1297+
),
12791298
)
12801299
return hidden_states
12811300

megatron/core/transformer/transformer_config.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -496,6 +496,12 @@ class TransformerConfig(ModelParallelConfig):
496496
"""[Compatibility alias for moe_router_padding_for_quantization]
497497
Enabling this will also enable moe_router_padding_for_quantization."""
498498

499+
moe_permute_padding_for_quantization: Optional[bool] = False
500+
"""Enable padding during MoE token permutation and corresponding unpadding during unpermutation
501+
so that the number of tokens in each expert's permuted block is aligned to a multiple of 16 / 32
502+
for quantized precisions such as FP8 and FP4. This can remove explicit padding/
503+
unpadding around GroupedMLP kernels, which improves throughput and reduces peak memory usage."""
504+
499505
moe_router_num_groups: Optional[int] = None
500506
"""Number of groups to divide experts into for group-limited routing.
501507
When using group-limited routing:
@@ -1419,6 +1425,22 @@ def __post_init__(self):
14191425
"moe_router_padding_for_quantization."
14201426
)
14211427

1428+
if self.moe_permute_padding_for_quantization:
1429+
if self.fp8 is None and self.fp4 is None:
1430+
raise ValueError(
1431+
"moe_permute_padding_for_quantization requires a quantized precision recipe(e.g., fp8 or fp4) to be enabled."
1432+
)
1433+
1434+
if not self.moe_permute_fusion:
1435+
raise ValueError(
1436+
"moe_permute_padding_for_quantization currently requires fused permute."
1437+
)
1438+
1439+
from megatron.core.transformer.moe.moe_utils import fused_permute_and_pad_with_probs
1440+
1441+
if fused_permute_and_pad_with_probs is None:
1442+
raise ValueError("fused_permute_and_pad_with_probs is not available. Please install TE >= 2.12.0.")
1443+
14221444
if (
14231445
self.moe_router_topk == 1
14241446
and self.moe_router_score_function == "softmax"

megatron/training/arguments.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3207,6 +3207,10 @@ def _add_moe_args(parser):
32073207
group.add_argument('--moe-router-padding-for-fp8', action='store_true',
32083208
help='[Compatibility alias for --moe-router-padding-for-quantization] '
32093209
'Enabling this will also enable --moe-router-padding-for-quantization.')
3210+
group.add_argument('--moe-permute-padding-for-quantization', action='store_true',
3211+
help='Enable padding during MoE token permutation (and unpadding during unpermutation) '
3212+
'so that the number of tokens in each expert permuted block is aligned to a multiple of 16/32 for FP8/FP4 precision. '
3213+
'This can remove explicit padding/unpadding around GroupedMLP, which improves throughput and reduces peak memory usage.')
32103214
group.add_argument('--moe-aux-loss-coeff', type=float, nargs='+', default=0.0,
32113215
help='Scaling coefficient for the aux loss: a starting value of 1e-2 is recommended.')
32123216
group.add_argument('--moe-z-loss-coeff', type=float, default=None,

0 commit comments

Comments
 (0)