Skip to content
Open
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
1 change: 1 addition & 0 deletions mamba_builders.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ def mamba_builder(args, pre_process, post_process, vp_stage=None, config=None, p
rotary_percent=args.rotary_percent,
rotary_base=args.rotary_base,
pg_collection=pg_collection,
vp_stage=vp_stage,
)

for l in range(model.decoder.num_layers_per_pipeline_rank):
Expand Down
30 changes: 27 additions & 3 deletions megatron/core/models/common/language_module/language_module.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
from megatron.core.process_groups_config import ProcessGroupCollection
from megatron.core.transformer.enums import AttnBackend, CudaGraphScope
from megatron.core.transformer.module import MegatronModule
from megatron.core.transformer.multi_token_prediction import tie_word_embeddings_state_dict
from megatron.core.transformer.transformer_config import TransformerConfig
from megatron.core.transformer.utils import ensure_metadata_has_dp_cp_group
from megatron.core.utils import (
Expand Down Expand Up @@ -255,12 +256,20 @@ def setup_embeddings_and_output_layer(self) -> None:
LanguageModule.embedding_warning_printed = True

def shared_embedding_or_output_weight(self) -> Tensor:
"""Gets the emedding weight or output logit weights when share embedding and output weights set to True.
"""Gets the embedding weight or output logit weights when share embedding and output weights set to True
or when use Multi-Token Prediction (MTP).

Returns:
Tensor: During pre processing it returns the input embeddings weight while during post processing it returns the final output layers weight
Tensor: During pre processing or MTP process it returns the input embeddings weight while during post processing it returns the final output layers weight
"""
if self.pre_process:
if self.pre_process or getattr(self, 'mtp_process', False):
# Multi-Token Prediction (MTP) need both embedding layer and output layer.
# So there will be both embedding layer and output layer in the mtp process stage.
# When share_embeddings_and_output_weights is True, the embedding weight is the
# canonical shared weight and is passed to the output layer during forward.
assert hasattr(
self, 'embedding'
), f"embedding is needed in this pipeline stage, but it is not initialized."
return self.embedding.word_embeddings.weight
elif self.post_process:
return self.output_layer.weight
Expand Down Expand Up @@ -293,6 +302,21 @@ def sharded_state_dict(
output_layer_weight_key = f'{prefix}output_layer.weight'
output_layer_bias_key = f'{prefix}output_layer.bias'

# Multi-Token Prediction (MTP) needs embedding layer in mtp process stage.
# If MTP is not placed in the pre processing stage, we need to maintain a copy of
# embedding layer in the mtp process stage and tie it to the embedding in the pre
# processing stage.
# Note: MTP loss is computed at post_process stage, so the output_layer on mtp_process
# rank doesn't need special tying - it's not used for loss computation.
if getattr(self, 'mtp_process', False) and not self.pre_process:
emb_weight = self.embedding.word_embeddings.weight
tie_word_embeddings_state_dict(
sharded_state_dict,
emb_weight,
first_stage_word_emb_key,
tp_group=self.tp_group,
dp_cp_group=metadata['dp_cp_group'],
)
if self.share_embeddings_and_output_weights:
self.tie_embeddings_and_output_weights_state_dict(
sharded_state_dict, output_layer_weight_key, first_stage_word_emb_key, metadata
Expand Down
2 changes: 1 addition & 1 deletion megatron/core/models/common/model_chunk_schedule_plan.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ def _build_callable_nodes(self, event, comp_stream, comm_stream, extra_args):

# get flags for latter use
is_mtp = isinstance(self.layer, MultiTokenPredictionLayer)
transformer_layer = self.layer.transformer_layer if is_mtp else self.layer
transformer_layer = self.layer.mtp_model_layer if is_mtp else self.layer
is_moe = isinstance(transformer_layer.mlp, MoELayer)
num_local_experts = transformer_layer.mlp.num_local_experts if is_moe else None

Expand Down
4 changes: 2 additions & 2 deletions megatron/core/models/gpt/fine_grained_callables.py
Original file line number Diff line number Diff line change
Expand Up @@ -638,9 +638,9 @@ def build_mtp_layer_callables(layer):
multi-token prediction layer nodes (attention, MLP, etc.)
"""

forward_funcs, backward_dw = build_transformer_layer_callables(layer.transformer_layer)
forward_funcs, backward_dw = build_transformer_layer_callables(layer.mtp_model_layer)
attn_forward, dispatch_forward, mlp_forward, combine_forward, _ = forward_funcs
is_moe = isinstance(layer.transformer_layer.mlp, MoELayer)
is_moe = isinstance(layer.mtp_model_layer.mlp, MoELayer)
assert is_moe, "MTP layer in a2a overlap only supports MoE layer for now."

def submodule_mtp_attn_forward(node, hidden_states):
Expand Down
2 changes: 1 addition & 1 deletion megatron/core/models/gpt/gpt_layer_specs.py
Original file line number Diff line number Diff line change
Expand Up @@ -753,7 +753,7 @@ def get_gpt_mtp_block_spec_for_backend(
raise ValueError(f"Invalid spec: {spec}")

mtp_layer_spec = get_mtp_layer_spec_for_backend(
transformer_layer_spec=transformer_layer_spec, backend=backend
mtp_model_layer_spec=transformer_layer_spec, backend=backend
)
mtp_num_layers = config.mtp_num_layers if config.mtp_num_layers else 0
mtp_layer_specs = [mtp_layer_spec] * mtp_num_layers
Expand Down
49 changes: 6 additions & 43 deletions megatron/core/models/gpt/gpt_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import torch
from torch import Tensor

from megatron.core import parallel_state, tensor_parallel
from megatron.core import tensor_parallel
from megatron.core.config_logger import has_config_logger_enabled, log_config_to_disk
from megatron.core.dist_checkpointing.mapping import ShardedStateDict
from megatron.core.inference.contexts import BaseInferenceContext
Expand All @@ -29,11 +29,9 @@
from megatron.core.transformer.enums import CudaGraphScope, ModelType
from megatron.core.transformer.linear_cross_entropy import LinearCrossEntropyModule
from megatron.core.transformer.multi_token_prediction import (
MTPLossAutoScaler,
MTPLossLoggingHelper,
MultiTokenPredictionBlock,
roll_tensor,
tie_word_embeddings_state_dict,
mtp_on_this_rank,
process_mtp_loss,
)
from megatron.core.transformer.spec_utils import ModuleSpec
from megatron.core.transformer.transformer_block import TransformerBlock
Expand Down Expand Up @@ -209,7 +207,9 @@ def __init__(
self.rotary_base = rotary_base
self.rotary_scaling = rope_scaling
self.mtp_block_spec = mtp_block_spec
self.mtp_process = mtp_block_spec is not None
self.mtp_process = mtp_block_spec is not None and mtp_on_this_rank(
self.config, ignore_virtual=False, vp_stage=vp_stage
)

self.fuse_linear_cross_entropy = (
self.config.cross_entropy_loss_fusion
Expand Down Expand Up @@ -855,27 +855,6 @@ def _postprocess(

return loss

def shared_embedding_or_output_weight(self) -> Tensor:
"""Gets the embedding weight or output logit weights when share input embedding and
output weights set to True or when use Multi-Token Prediction (MTP) feature.

Returns:
Tensor: During pre processing or MTP process it returns the input embeddings weight.
Otherwise, during post processing it returns the final output layers weight.
"""
if self.pre_process or self.mtp_process:
# Multi-Token Prediction (MTP) need both embedding layer and output layer.
# So there will be both embedding layer and output layer in the mtp process stage.
# In this case, if share_embeddings_and_output_weights is True, the shared weights
# will be stored in embedding layer, and output layer will not have any weight.
assert hasattr(
self, 'embedding'
), f"embedding is needed in this pipeline stage, but it is not initialized."
return self.embedding.word_embeddings.weight
elif self.post_process:
return self.output_layer.weight
return None

def build_schedule_plan(
self,
input_ids: Tensor,
Expand Down Expand Up @@ -966,20 +945,4 @@ def sharded_state_dict(
output_extra_state and output_extra_state.data
), f'Expected output layer extra state to be empty, got: {output_extra_state}'

# Multi-Token Prediction (MTP) need embedding layer in mtp process stage.
# If MTP is not placed in the pre processing stage, we need to maintain a copy of
# embedding layer in the mtp process stage and tie it to the embedding in the pre
# processing stage.
# Now MTP loss is computed in post processing stage, so the output_layer is not needed.
if self.mtp_process and not self.pre_process:
emb_weight_key = f'{prefix}embedding.word_embeddings.weight'
emb_weight = self.embedding.word_embeddings.weight
tie_word_embeddings_state_dict(
sharded_state_dict,
emb_weight,
emb_weight_key,
tp_group=self.tp_group,
dp_cp_group=metadata['dp_cp_group'],
)

return sharded_state_dict
33 changes: 33 additions & 0 deletions megatron/core/models/mamba/mamba_layer_specs.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved.

from megatron.core.extensions.transformer_engine import (
TEColumnParallelLinear,
TEDotProductAttention,
TELayerNormColumnParallelLinear,
TENorm,
Expand All @@ -19,20 +20,49 @@
from megatron.core.transformer.attention import SelfAttention, SelfAttentionSubmodules
from megatron.core.transformer.enums import AttnMaskType
from megatron.core.transformer.mlp import MLP, MLPSubmodules
from megatron.core.transformer.multi_token_prediction import (
MultiTokenPredictionBlock,
MultiTokenPredictionBlockSubmodules,
MultiTokenPredictionLayer,
MultiTokenPredictionLayerSubmodules,
)
from megatron.core.transformer.spec_utils import ModuleSpec
from megatron.core.transformer.transformer_layer import (
MoETransformerLayer,
TransformerLayer,
TransformerLayerSubmodules,
)

# This should be private and should not be used outside of this file.
moe = get_moe_module_spec(
use_te=True,
num_experts=8, # Can be any positive integer (must not be None).
moe_grouped_gemm=True,
moe_use_legacy_grouped_gemm=False,
)


# MTP block spec for Mamba - provides norms and projection only.
# Inner layers are built by MultiTokenPredictionLayer using nested MambaStack
_mamba_mtp_block_spec = ModuleSpec(
module=MultiTokenPredictionBlock,
submodules=MultiTokenPredictionBlockSubmodules(
layer_specs=[
ModuleSpec(
module=MultiTokenPredictionLayer,
submodules=MultiTokenPredictionLayerSubmodules(
enorm=TENorm,
hnorm=TENorm,
eh_proj=TEColumnParallelLinear,
mtp_model_layer=None, # Built via pattern + mamba_submodules
layer_norm=TENorm,
),
)
]
),
)


mamba_stack_spec = ModuleSpec(
module=MambaStack,
submodules=MambaStackSubmodules(
Expand Down Expand Up @@ -87,9 +117,11 @@
pre_mlp_layernorm=TENorm, mlp=moe, mlp_bda=get_bias_dropout_add
),
),
mtp_block_spec=_mamba_mtp_block_spec,
),
)


mamba_inference_stack_spec = ModuleSpec(
module=MambaStack,
submodules=MambaStackSubmodules(
Expand Down Expand Up @@ -147,5 +179,6 @@
pre_mlp_layernorm=TENorm, mlp=moe, mlp_bda=get_bias_dropout_add
),
),
mtp_block_spec=_mamba_mtp_block_spec,
),
)
Loading