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
5 changes: 4 additions & 1 deletion megatron/core/models/gpt/fine_grained_callables.py
Original file line number Diff line number Diff line change
Expand Up @@ -669,14 +669,17 @@ def submodule_mtp_attn_forward(node, hidden_states):
node.chunk_state.mtp_hidden_states = list(torch.chunk(hidden_states, 1 + offset, dim=0))
hidden_states = node.chunk_state.mtp_hidden_states[offset]

input_ids, position_ids, decoder_input, hidden_states = layer._get_embeddings(
input_ids, position_ids, padding_mask, decoder_input, hidden_states = layer._get_embeddings(
input_ids=node.chunk_state.input_ids,
position_ids=node.chunk_state.position_ids,
embedding=node.chunk_state.model.embedding,
hidden_states=hidden_states,
packed_seq_params=node.chunk_state.packed_seq_params,
padding_mask=node.chunk_state.padding_mask,
)
node.chunk_state.input_ids = input_ids
node.chunk_state.position_ids = position_ids
node.chunk_state.padding_mask = padding_mask

# MTP Layer Preprocess
# norm, linear projection and transformer
Expand Down
3 changes: 3 additions & 0 deletions megatron/core/models/gpt/gpt_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -561,6 +561,7 @@ def forward(
loss_mask=loss_mask,
decoder_input=decoder_input,
attention_mask=attention_mask,
padding_mask=padding_mask,
inference_params=inference_params,
packed_seq_params=packed_seq_params,
sequence_len_offset=sequence_len_offset,
Expand All @@ -583,6 +584,7 @@ def _postprocess(
loss_mask=None,
decoder_input=None,
attention_mask=None,
padding_mask=None,
inference_params=None,
packed_seq_params=None,
sequence_len_offset=None,
Expand Down Expand Up @@ -626,6 +628,7 @@ def _postprocess(
rotary_pos_sin=rotary_pos_sin,
packed_seq_params=packed_seq_params,
sequence_len_offset=sequence_len_offset,
padding_mask=padding_mask,
embedding=self.embedding,
**(extra_block_kwargs or {}),
)
Expand Down
146 changes: 126 additions & 20 deletions megatron/core/ssm/gated_delta_net.py
Original file line number Diff line number Diff line change
Expand Up @@ -297,30 +297,81 @@ def forward(
# TODO: support inference
raise NotImplementedError("GDN does not support inference for now.")

if packed_seq_params is not None:
# TODO: support packed sequence
raise NotImplementedError("GDN does not support packed sequence for now.")
if packed_seq_params is not None and packed_seq_params.qkv_format == 'thd':
assert batch == 1, "Packed sequence expects batch dimension to be 1"
assert (
not self.config.deterministic_mode
), "Packed sequence does not support deterministic mode."

# Resolve cu_seqlens with alignment padding handling.
cu_seqlens_q = self._resolve_cu_seqlens(
packed_seq_params.cu_seqlens_q_padded,
packed_seq_params.cu_seqlens_q,
seq_len,
"cu_seqlens_q",
cp_size=self.cp_size,
)
cu_seqlens_kv = self._resolve_cu_seqlens(
packed_seq_params.cu_seqlens_kv_padded,
packed_seq_params.cu_seqlens_kv,
seq_len,
"cu_seqlens_kv",
cp_size=self.cp_size,
)
assert torch.equal(cu_seqlens_q, cu_seqlens_kv), (
"Currently only support cu_seqlens_q equals to cu_seqlens_kv, "
f"but got {cu_seqlens_q=} and {cu_seqlens_kv=}"
)
num_packed_seqs = cu_seqlens_q.shape[0] - 1
assert num_packed_seqs > 0, (
"Number of packed sequences must be greater than 0, "
f"but got {cu_seqlens_q=} and {cu_seqlens_kv=}"
)
else:
cu_seqlens_q = None
cu_seqlens_kv = None
Comment thread
yuzhongw-nvidia marked this conversation as resolved.

# Input projection
nvtx_range_push(suffix="in_proj")
qkvzba, _ = self.in_proj(hidden_states)
nvtx_range_pop(suffix="in_proj")

# CP All to All: CP to HP
qkvzba = tensor_a2a_cp2hp(
qkvzba,
seq_dim=0,
head_dim=-1,
cp_group=self.pg_collection.cp,
split_sections=[
self.qk_dim_local_tp,
self.qk_dim_local_tp,
self.v_dim_local_tp,
self.v_dim_local_tp,
self.num_value_heads // self.tp_size,
self.num_value_heads // self.tp_size,
],
)
if packed_seq_params is not None and packed_seq_params.qkv_format == 'thd':
unpacked_qkvzba = _unpack_sequence(qkvzba, cu_seqlens_q // self.cp_size, dim=0)
Comment thread
yuzhongw-nvidia marked this conversation as resolved.
outputs = []
for qkvzba_i in unpacked_qkvzba:
qkvzba_i = tensor_a2a_cp2hp(
qkvzba_i,
seq_dim=0,
head_dim=-1,
cp_group=self.pg_collection.cp,
split_sections=[
self.qk_dim_local_tp,
self.qk_dim_local_tp,
self.v_dim_local_tp,
self.v_dim_local_tp,
self.num_value_heads // self.tp_size,
self.num_value_heads // self.tp_size,
],
)
outputs.append(qkvzba_i)
qkvzba = torch.cat(outputs, dim=0)
Comment thread
yuzhongw-nvidia marked this conversation as resolved.
else:
qkvzba = tensor_a2a_cp2hp(
qkvzba,
seq_dim=0,
head_dim=-1,
cp_group=self.pg_collection.cp,
split_sections=[
self.qk_dim_local_tp,
self.qk_dim_local_tp,
self.v_dim_local_tp,
self.v_dim_local_tp,
self.num_value_heads // self.tp_size,
self.num_value_heads // self.tp_size,
],
)

# Transpose: s b x --> b s x
# From sbhd to bshd format
Expand Down Expand Up @@ -387,6 +438,7 @@ def forward(
activation=self.activation,
initial_state=None,
output_final_state=False,
cu_seqlens=cu_seqlens_q,
)
nvtx_range_pop(suffix="conv1d")

Expand Down Expand Up @@ -416,6 +468,7 @@ def forward(
initial_state=None,
output_final_state=False,
use_qk_l2norm_in_kernel=False,
cu_seqlens=cu_seqlens_q,
)
nvtx_range_pop(suffix="gated_delta_rule")

Expand All @@ -430,9 +483,19 @@ def forward(
norm_out = norm_out.transpose(0, 1).contiguous()

# CP all to all: HP to CP
norm_out = tensor_a2a_hp2cp(
norm_out, seq_dim=0, head_dim=-1, cp_group=self.pg_collection.cp
)
if packed_seq_params is not None and packed_seq_params.qkv_format == 'thd':
unpacked_norm_out = _unpack_sequence(norm_out, cu_seqlens_q, dim=0)
outputs = []
for norm_out_i in unpacked_norm_out:
norm_out_i = tensor_a2a_hp2cp(
norm_out_i, seq_dim=0, head_dim=-1, cp_group=self.pg_collection.cp
)
outputs.append(norm_out_i)
norm_out = torch.cat(outputs, dim=0)
else:
norm_out = tensor_a2a_hp2cp(
norm_out, seq_dim=0, head_dim=-1, cp_group=self.pg_collection.cp
)

# Output projection
nvtx_range_push(suffix="out_proj")
Expand Down Expand Up @@ -504,6 +567,32 @@ def _compute_g_and_beta(self, A_log_local_cp, dt_bias_local_cp, alpha, beta):
beta = beta.sigmoid()
return g, beta

def _resolve_cu_seqlens(
self, cu_seqlens_padded, cu_seqlens_actual, total_seq_len, name, cp_size: int = 1
):
"""Resolve cu_seqlens for packed sequence all-to-all, handling alignment padding."""
if cu_seqlens_padded is not None:
cu_seqlens = cu_seqlens_padded
else:
cu_seqlens = cu_seqlens_actual

total_cu = cu_seqlens[-1].cpu().item()
if total_cu != total_seq_len:
raise ValueError(
f"GDN: {name}[-1]={total_cu} does not match "
f"total_sequence_length={total_seq_len}. "
f"({cu_seqlens_padded=}, {cu_seqlens_actual=})."
)

seq_lengths = cu_seqlens[1:] - cu_seqlens[:-1]
if (seq_lengths % cp_size != 0).any():
raise ValueError(
f"All per-sequence lengths in cu_seqlens must be divisible by cp_size={cp_size}, "
f"but got lengths: {seq_lengths.tolist()}"
)

return cu_seqlens

def sharded_state_dict(self, prefix="", sharded_offsets=(), metadata=None, tp_group=None):
"""Provide a sharded state dictionary for distributed checkpointing."""
# Guard for cases metadata is not provided
Expand Down Expand Up @@ -602,6 +691,18 @@ def _backward_out_proj(self):
self.out_proj.backward_dw()


def _unpack_sequence(x, cu_seqlens, dim=1):
unpacked_x = []
cu_seqlens_list = cu_seqlens.tolist()
num_seqs = len(cu_seqlens_list) - 1
for i in range(num_seqs):
idx_start = cu_seqlens_list[i]
idx_end = cu_seqlens_list[i + 1]
chunked_index = [slice(None)] * dim + [slice(idx_start, idx_end)]
unpacked_x.append(x[tuple(chunked_index)])
return unpacked_x
Comment thread
yuzhongw-nvidia marked this conversation as resolved.


####################
# Sharded state dict utilities
####################
Expand Down Expand Up @@ -853,6 +954,7 @@ def torch_chunk_gated_delta_rule(
initial_state=None,
output_final_state=False,
use_qk_l2norm_in_kernel=False,
cu_seqlens=None,
):
# pylint: disable=line-too-long
'''
Expand All @@ -862,6 +964,10 @@ def torch_chunk_gated_delta_rule(
Reference: https://github.com/huggingface/transformers/blob/144c8ce2809a2e21914017652700e1ecb450501e/src/transformers/models/qwen3_next/modeling_qwen3_next.py#L470-L547
'''

assert (
cu_seqlens is None
), "cu_seqlens is not supported for torch_chunk_gated_delta_rule for now."

initial_dtype = query.dtype
if use_qk_l2norm_in_kernel:
query = l2norm(query, dim=-1, eps=1e-6)
Expand Down
26 changes: 22 additions & 4 deletions megatron/core/transformer/multi_token_prediction.py
Original file line number Diff line number Diff line change
Expand Up @@ -870,6 +870,7 @@ def _get_embeddings(
embedding: Callable,
hidden_states: torch.Tensor,
packed_seq_params: Optional[PackedSeqParams] = None,
padding_mask: Optional[torch.Tensor] = None,
):
"""
Preprocesses input data for the Multi-Token Prediction (MTP) layers.
Expand Down Expand Up @@ -901,12 +902,20 @@ def _get_embeddings(
cp_group=self.cp_group,
packed_seq_params=packed_seq_params,
)
if padding_mask is not None:
padding_mask, _ = roll_tensor(
padding_mask,
shifts=-1,
dims=-1,
cp_group=self.cp_group,
packed_seq_params=packed_seq_params,
)
# embedding
decoder_input = embedding(input_ids=input_ids, position_ids=position_ids)

hidden_states = make_viewless_tensor(inp=hidden_states, requires_grad=True, keep_graph=True)

return input_ids, position_ids, decoder_input, hidden_states
return input_ids, position_ids, padding_mask, decoder_input, hidden_states

def _concat_embeddings(self, hidden_states: torch.Tensor, decoder_input: torch.Tensor):
"""
Expand Down Expand Up @@ -940,6 +949,7 @@ def _proj_and_transformer_layer(
hidden_states: Tensor,
decoder_input: Tensor,
attention_mask: Optional[torch.Tensor] = None,
padding_mask: Optional[torch.Tensor] = None,
context: Optional[torch.Tensor] = None,
context_mask: Optional[torch.Tensor] = None,
rotary_pos_emb: Optional[torch.Tensor] = None,
Expand Down Expand Up @@ -980,6 +990,7 @@ def _proj_and_transformer_layer(
hidden_states = self.mtp_model_layer(
hidden_states=hidden_states,
attention_mask=attention_mask,
padding_mask=padding_mask,
rotary_pos_emb=rotary_pos_emb,
inference_context=inference_params,
packed_seq_params=packed_seq_params,
Expand All @@ -998,6 +1009,7 @@ def _proj_and_transformer_layer(
inference_params=inference_params,
packed_seq_params=packed_seq_params,
sequence_len_offset=sequence_len_offset,
padding_mask=padding_mask,
)

hidden_states = self._postprocess(hidden_states)
Expand Down Expand Up @@ -1107,6 +1119,7 @@ def forward(
position_ids: Tensor,
hidden_states: Tensor,
attention_mask: Tensor,
padding_mask: Optional[Tensor] = None,
context: Optional[Tensor] = None,
context_mask: Optional[Tensor] = None,
rotary_pos_emb: Optional[Tensor] = None,
Expand Down Expand Up @@ -1141,9 +1154,10 @@ def forward(
[s, b, h], and optionally the updated context tensor if cross-attention is used.
"""
assert context is None, "multi token prediction + cross attention is not yet supported."
input_ids, position_ids, decoder_input, hidden_states = self._get_embeddings(
input_ids, position_ids, padding_mask, decoder_input, hidden_states = self._get_embeddings(
input_ids=input_ids,
position_ids=position_ids,
padding_mask=padding_mask,
embedding=embedding,
hidden_states=hidden_states,
packed_seq_params=packed_seq_params,
Expand All @@ -1155,6 +1169,7 @@ def forward(
hidden_states=hidden_states,
decoder_input=decoder_input,
attention_mask=attention_mask,
padding_mask=padding_mask,
context=context,
context_mask=context_mask,
rotary_pos_emb=rotary_pos_emb,
Expand All @@ -1170,6 +1185,7 @@ def forward(
hidden_states=hidden_states,
decoder_input=decoder_input,
attention_mask=attention_mask,
padding_mask=padding_mask,
context=context,
context_mask=context_mask,
rotary_pos_emb=rotary_pos_emb,
Expand All @@ -1181,7 +1197,7 @@ def forward(
sequence_len_offset=sequence_len_offset,
)

return hidden_states, input_ids, position_ids
return hidden_states, input_ids, position_ids, padding_mask

def sharded_state_dict(
self, prefix: str = '', sharded_offsets: tuple = (), metadata: Optional[dict] = None
Expand Down Expand Up @@ -1428,6 +1444,7 @@ def forward(
position_ids: Tensor,
hidden_states: Tensor,
attention_mask: Tensor,
padding_mask: Optional[Tensor] = None,
context: Optional[Tensor] = None,
context_mask: Optional[Tensor] = None,
rotary_pos_emb: Optional[Tensor] = None,
Expand Down Expand Up @@ -1458,11 +1475,12 @@ def forward(
hidden_states = hidden_states_list[offset]
for iteration in range(self.config.mtp_num_layers):
layer_idx = 0 if self.mtp_use_repeated_layer else iteration
(hidden_states, input_ids, position_ids) = self.layers[layer_idx](
(hidden_states, input_ids, position_ids, padding_mask) = self.layers[layer_idx](
input_ids=input_ids,
position_ids=position_ids,
hidden_states=hidden_states,
attention_mask=attention_mask,
padding_mask=padding_mask,
inference_params=inference_params,
rotary_pos_emb=rotary_pos_emb,
rotary_pos_cos=rotary_pos_cos,
Expand Down
Loading
Loading