Download frameworks/slime/docker/patch/latest/megatron.patch from SeanWang0027/rose-opd-implementation: direct link, hf CLI and curl.
- Browser
- Download file 37.1 kB
-
https://huggingface.co/SeanWang0027/rose-opd-implementation/resolve/main/frameworks/slime/docker/patch/latest/megatron.patch
- Command line
-
hf download hf://SeanWang0027/rose-opd-implementation/frameworks/slime/docker/patch/latest/megatron.patch
-
curl -L -o megatron.patch https://huggingface.co/SeanWang0027/rose-opd-implementation/resolve/main/frameworks/slime/docker/patch/latest/megatron.patch
37.1 kB
| diff --git a/megatron/core/dist_checkpointing/strategies/common.py b/megatron/core/dist_checkpointing/strategies/common.py | |
| index 41c21d93d..ef80f72d6 100644 | |
| --- a/megatron/core/dist_checkpointing/strategies/common.py | |
| +++ b/megatron/core/dist_checkpointing/strategies/common.py | |
| class TorchCommonLoadStrategy(LoadCommonStrategy): | |
| msc = MultiStorageClientFeature.import_package() | |
| return msc.torch.load(load_path, map_location='cpu') | |
| else: | |
| - return torch.load(load_path, map_location='cpu') | |
| + return torch.load(load_path, map_location='cpu', weights_only=False) | |
| except FileNotFoundError as e: | |
| err_msg = f'Common file {load_path} does not exist' | |
| if MultiStorageClientFeature.is_enabled(): | |
| diff --git a/megatron/core/dist_checkpointing/strategies/torch.py b/megatron/core/dist_checkpointing/strategies/torch.py | |
| index 5a1ea308d..aa701237f 100644 | |
| --- a/megatron/core/dist_checkpointing/strategies/torch.py | |
| +++ b/megatron/core/dist_checkpointing/strategies/torch.py | |
| class MCoreLoadPlanner(DefaultLoadPlanner): | |
| def _validate_global_shapes(self, metadata, sharded_tensors): | |
| for sh_ten in sharded_tensors: | |
| if sh_ten.key not in metadata.state_dict_metadata: | |
| - raise KeyError( | |
| - f"{sh_ten.key} from model not in state dict:" | |
| - f" {sorted(metadata.state_dict_metadata.keys())}" | |
| - ) | |
| + # raise KeyError( | |
| + # f"{sh_ten.key} from model not in state dict:" | |
| + # f" {sorted(metadata.state_dict_metadata.keys())}" | |
| + # ) | |
| + print(f"{sh_ten.key} from model not in state dict, will skip") | |
| + continue | |
| loaded_shape = metadata.state_dict_metadata[sh_ten.key].size | |
| expected_shape = self._expected_shape(sh_ten) | |
| if loaded_shape != expected_shape: | |
| class MCoreLoadPlanner(DefaultLoadPlanner): | |
| tensor_metadata = self.metadata.state_dict_metadata | |
| metadata_with_sizes = [ | |
| (tensor_metadata[key], tensor_metadata[key].size, sharded_tensor) | |
| - for key, sharded_tensor in self.allow_shape_mismatch_sharded_tensors.items() | |
| + for key, sharded_tensor in self.allow_shape_mismatch_sharded_tensors.items() if key in tensor_metadata | |
| ] | |
| try: | |
| # Temporarily set sizes to expected shapes | |
| class TorchDistLoadShardedStrategy(LoadShardedStrategy): | |
| planner=MCoreLoadPlanner( | |
| shapes_validation_sharded_tensors=flexible_shape_sharded_tensors, | |
| allow_shape_mismatch_sharded_tensors=allow_shape_mismatch_sharded_tensors, | |
| + allow_partial_load=True, | |
| ), | |
| ) | |
| diff --git a/megatron/core/extensions/transformer_engine.py b/megatron/core/extensions/transformer_engine.py | |
| index acb93ef78..d239db4ab 100644 | |
| --- a/megatron/core/extensions/transformer_engine.py | |
| +++ b/megatron/core/extensions/transformer_engine.py | |
| class TELinear(te.pytorch.Linear): | |
| ) | |
| for param in self.parameters(): | |
| + setattr(param, "parallel_mode", parallel_mode) | |
| if is_expert: | |
| # Reduce the gradient on the expert_data_parallel group for expert linear layers | |
| setattr(param, "allreduce", not self.expert_parallel) | |
| class TEDotProductAttention(te.pytorch.DotProductAttention): | |
| if HAVE_TE and is_te_min_version("1.9.0.dev0"): | |
| + def ceil_div(x: int, y: int) -> int: | |
| + return (x + y - 1) // y | |
| + | |
| + class _FakeInt4QuantizationSTE(torch.autograd.Function): | |
| + @staticmethod | |
| + def forward(ctx, x, group_size): | |
| + m, n = x.shape | |
| + block_size_m, block_size_n = 1, group_size | |
| + | |
| + | |
| + m_padded = ceil_div(m, block_size_m) * block_size_m | |
| + n_padded = ceil_div(n, block_size_n) * block_size_n | |
| + | |
| + x_padded = torch.zeros( | |
| + (m_padded, n_padded), | |
| + dtype=x.dtype, device=x.device | |
| + ) | |
| + x_padded[:m, :n] = x | |
| + | |
| + x_view = x_padded.view( | |
| + m_padded // block_size_m, | |
| + block_size_m, | |
| + n_padded // block_size_n, | |
| + block_size_n | |
| + ) | |
| + | |
| + x_max = x_view.abs().float().amax(dim=(1, 3), keepdim=True) | |
| + q_max = 7 | |
| + x_scale = x_max / q_max | |
| + | |
| + x_scale = x_scale.clamp(min=1e-5) | |
| + | |
| + x_div = x_view / x_scale | |
| + x_round = torch.round(x_div) | |
| + | |
| + x_q_clamped = x_round.clamp(-q_max, q_max) | |
| + | |
| + x_dequant_view = x_q_clamped * x_scale | |
| + | |
| + x_dequant_full = x_dequant_view.view_as(x_padded) | |
| + x_out = x_dequant_full[:m, :n].contiguous().to(x.dtype) | |
| + | |
| + return x_out | |
| + | |
| + @staticmethod | |
| + def backward(ctx, grad_output): | |
| + return grad_output, None | |
| + | |
| + def fake_int4_quantization_ste(x, group_size): | |
| + x_out = _FakeInt4QuantizationSTE.apply(x, group_size) | |
| + | |
| + if hasattr(x, 'main_grad'): | |
| + x_out.main_grad = x.main_grad | |
| + | |
| + return x_out | |
| class TEGroupedLinear(te.pytorch.GroupedLinear): | |
| """ | |
| if HAVE_TE and is_te_min_version("1.9.0.dev0"): | |
| _is_first_microbatch = ( | |
| None if self.disable_parameter_transpose_cache else self.is_first_microbatch | |
| ) | |
| + | |
| out = super().forward(x, m_splits, is_first_microbatch=_is_first_microbatch) | |
| self.is_first_microbatch = False | |
| if HAVE_TE and is_te_min_version("1.9.0.dev0"): | |
| return out | |
| return out, None | |
| + def _get_weight_tensors(self): | |
| + """Get the weight tensors of the module.""" | |
| + weight_tensors = super()._get_weight_tensors() | |
| + | |
| + if os.getenv("OPEN_TRAINING_INT4_FAKE_QAT_FLAG", "0") == "1": | |
| + group_size = int(os.getenv("OPEN_TRAINING_INT4_GROUP_SIZE", "128")) | |
| + | |
| + weight_tensors = [ | |
| + fake_int4_quantization_ste(w, group_size) | |
| + for w in weight_tensors | |
| + ] | |
| + | |
| + return weight_tensors | |
| + | |
| def _encode_extra_state(self, state): | |
| # TE 2.0 changed the format of extra_state to be a byte tensor | |
| if is_te_min_version("2.0.0"): | |
| diff --git a/megatron/core/fusions/fused_mla_yarn_rope_apply.py b/megatron/core/fusions/fused_mla_yarn_rope_apply.py | |
| index 1fd5dcfae..c9aeef1f0 100644 | |
| --- a/megatron/core/fusions/fused_mla_yarn_rope_apply.py | |
| +++ b/megatron/core/fusions/fused_mla_yarn_rope_apply.py | |
| def rotary_fwd_kv_kernel( | |
| SIN, | |
| emb_dim: tl.constexpr, | |
| k_dim: tl.constexpr, | |
| + k_dim_ceil: tl.constexpr, | |
| v_dim: tl.constexpr, | |
| head_num: tl.constexpr, | |
| batch_size, | |
| def rotary_fwd_kv_kernel( | |
| cos_right = tl.load(COS + token_idx * emb_dim + emb_dim // 2 + tl.arange(0, emb_dim // 2)) | |
| sin_right = tl.load(SIN + token_idx * emb_dim + emb_dim // 2 + tl.arange(0, emb_dim // 2)) | |
| - KV_ptr = KV + pid_m * stride_kv_seq + pid_head * BLOCK_H * stride_kv_nheads | |
| - kv_off = tl.arange(0, BLOCK_H)[:, None] * stride_kv_nheads | |
| - mask = kv_off < head_num * stride_kv_nheads | |
| - k_in_off = kv_off + tl.arange(0, k_dim)[None, :] | |
| - v_in_off = kv_off + k_dim + tl.arange(0, v_dim)[None, :] | |
| - k = tl.load(KV_ptr + k_in_off, mask=mask) | |
| - v = tl.load(KV_ptr + v_in_off, mask=mask) | |
| + KV_ptr = KV + pid_m * stride_kv_seq # + pid_head * BLOCK_H * stride_kv_nheads | |
| + ki_range = tl.arange(0, BLOCK_H)[:, None] + pid_head * BLOCK_H | |
| + kj_range = tl.arange(0, k_dim_ceil)[None, :] | |
| + mask_k = (ki_range < head_num) & (kj_range < k_dim) | |
| + mask_v = ki_range < head_num | |
| + k_off = ki_range * stride_kv_nheads + kj_range | |
| + if v_dim > 0: | |
| + v_off = ki_range * stride_kv_nheads + k_dim + tl.arange(0, v_dim)[None, :] | |
| + v = tl.load(KV_ptr + v_off, mask=mask_v) | |
| + else: | |
| + v = tl.zeros((BLOCK_H, 1), dtype=KV.dtype.element_ty) | |
| + k = tl.load(KV_ptr + k_off, mask=mask_k) | |
| - K_ptr = O_KEY + pid_m * stride_k_seq + pid_head * BLOCK_H * stride_k_nheads | |
| - V_ptr = O_VALUE + pid_m * stride_v_seq + pid_head * BLOCK_H * stride_v_nheads | |
| + K_ptr = O_KEY + pid_m * stride_k_seq # + pid_head * BLOCK_H * stride_k_nheads | |
| + V_ptr = O_VALUE + pid_m * stride_v_seq # + pid_head * BLOCK_H * stride_v_nheads | |
| - k_out_off = tl.arange(0, BLOCK_H)[:, None] * stride_k_nheads + tl.arange(0, k_dim)[None, :] | |
| - v_out_off = tl.arange(0, BLOCK_H)[:, None] * stride_v_nheads + tl.arange(0, v_dim)[None, :] | |
| - tl.store(K_ptr + k_out_off, k, mask=mask) | |
| - tl.store(V_ptr + v_out_off, v, mask=mask) | |
| + k_out_off = ki_range * stride_k_nheads + kj_range | |
| + tl.store(K_ptr + k_out_off, k, mask=mask_k) | |
| + if v_dim > 0: | |
| + v_out_off = ki_range * stride_v_nheads + tl.arange(0, v_dim)[None, :] | |
| + tl.store(V_ptr + v_out_off, v, mask=mask_v) | |
| EMB = K_POS_EMB + pid_m * stride_emb_seq | |
| # x1 = t[..., 0::2], x2 = t[..., 1::2] | |
| def rotary_fwd_kv_kernel( | |
| x_left = x_left.expand_dims(0).broadcast_to(BLOCK_H, emb_dim // 2) | |
| x_right = x_right.expand_dims(0).broadcast_to(BLOCK_H, emb_dim // 2) | |
| + x_range = tl.arange(0, BLOCK_H)[:, None] + pid_head * BLOCK_H | |
| + mask_x = x_range < head_num | |
| x_left_off = ( | |
| - tl.arange(0, BLOCK_H)[:, None] * stride_k_nheads | |
| + x_range * stride_k_nheads | |
| + k_dim | |
| + tl.arange(0, emb_dim // 2)[None, :] | |
| ) | |
| x_right_off = x_left_off + emb_dim // 2 | |
| - tl.store(K_ptr + x_left_off, x_left, mask=mask) | |
| - tl.store(K_ptr + x_right_off, x_right, mask=mask) | |
| + tl.store(K_ptr + x_left_off, x_left, mask=mask_x) | |
| + tl.store(K_ptr + x_right_off, x_right, mask=mask_x) | |
| @triton.autotune( | |
| def rotary_bwd_kv_kernel( | |
| SIN, | |
| emb_dim: tl.constexpr, | |
| k_dim: tl.constexpr, | |
| + k_dim_ceil: tl.constexpr, | |
| v_dim: tl.constexpr, | |
| head_num: tl.constexpr, | |
| batch_size, | |
| def rotary_bwd_kv_kernel( | |
| else: | |
| token_idx = _get_thd_token_idx(cu_seqlens_kv, pid_m, seq_num, cp_rank, cp_size) | |
| - dKV_ptr = dKV + pid_m * stride_dkv_seq + pid_head * BLOCK_H * stride_dkv_nheads | |
| - dkv_off = tl.arange(0, BLOCK_H)[:, None] * stride_dkv_nheads | |
| - mask = dkv_off < head_num * stride_dkv_nheads | |
| - dk_out_off = dkv_off + tl.arange(0, k_dim)[None, :] | |
| - dv_out_off = dkv_off + k_dim + tl.arange(0, v_dim)[None, :] | |
| - | |
| - dK_ptr = dK + pid_m * stride_dk_seq + pid_head * BLOCK_H * stride_dk_nheads | |
| - dV_ptr = dV + pid_m * stride_dv_seq + pid_head * BLOCK_H * stride_dv_nheads | |
| - dk_in_off = tl.arange(0, BLOCK_H)[:, None] * stride_dk_nheads + tl.arange(0, k_dim)[None, :] | |
| - dv_in_off = tl.arange(0, BLOCK_H)[:, None] * stride_dv_nheads + tl.arange(0, v_dim)[None, :] | |
| - dk = tl.load(dK_ptr + dk_in_off, mask=mask) | |
| - dv = tl.load(dV_ptr + dv_in_off, mask=mask) | |
| - tl.store(dKV_ptr + dk_out_off, dk, mask=mask) | |
| - tl.store(dKV_ptr + dv_out_off, dv, mask=mask) | |
| + dKV_ptr = dKV + pid_m * stride_dkv_seq # + pid_head * BLOCK_H * stride_dkv_nheads | |
| + ki_range = tl.arange(0, BLOCK_H)[:, None] + pid_head * BLOCK_H | |
| + kj_range = tl.arange(0, k_dim_ceil)[None, :] | |
| + mask_k = (ki_range < head_num) & (kj_range < k_dim) | |
| + mask_v = ki_range < head_num | |
| + dk_out_off = ki_range * stride_dkv_nheads + kj_range | |
| + | |
| + dK_ptr = dK + pid_m * stride_dk_seq # + pid_head * BLOCK_H * stride_dk_nheads | |
| + dV_ptr = dV + pid_m * stride_dv_seq # + pid_head * BLOCK_H * stride_dv_nheads | |
| + dk_in_off = ki_range * stride_dk_nheads + kj_range | |
| + | |
| + dk = tl.load(dK_ptr + dk_in_off, mask=mask_k) | |
| + tl.store(dKV_ptr + dk_out_off, dk, mask=mask_k) | |
| + | |
| + if v_dim > 0: | |
| + dv_out_off = ki_range * stride_dkv_nheads + k_dim + tl.arange(0, v_dim)[None, :] | |
| + dv_in_off = ki_range * stride_dv_nheads + tl.arange(0, v_dim)[None, :] | |
| + dv = tl.load(dV_ptr + dv_in_off, mask=mask_v) | |
| + tl.store(dKV_ptr + dv_out_off, dv, mask=mask_v) | |
| if pid_head == 0: | |
| x_left_accum = tl.zeros((BLOCK_H, emb_dim // 2), dtype=tl.float32) | |
| x_right_accum = tl.zeros((BLOCK_H, emb_dim // 2), dtype=tl.float32) | |
| for i in tl.static_range(triton.cdiv(head_num, BLOCK_H)): | |
| - dK_ptr = dK + pid_m * stride_dk_seq + i * BLOCK_H * stride_dk_nheads | |
| - x_off = tl.arange(0, BLOCK_H)[:, None] * stride_dk_nheads + k_dim | |
| + dK_ptr = dK + pid_m * stride_dk_seq # + i * BLOCK_H * stride_dk_nheads | |
| + x_off = tl.arange(0, BLOCK_H)[:, None] * stride_dk_nheads + k_dim + i * BLOCK_H * stride_dk_nheads | |
| mask = x_off < head_num * stride_dk_nheads | |
| x_left_off = x_off + tl.arange(0, emb_dim // 2)[None, :] | |
| x_right_off = x_left_off + emb_dim // 2 | |
| class ApplyMLARotaryEmbKV(torch.autograd.Function): | |
| o_key = kv.new_empty(total_seqlen, nheads, emb_dim + k_dim) | |
| o_value = kv.new_empty(total_seqlen, nheads, v_dim) | |
| + k_dim_ceil = triton.next_power_of_2(k_dim) | |
| grid = lambda META: (total_seqlen, triton.cdiv(nheads, META["BLOCK_H"])) | |
| rotary_fwd_kv_kernel[grid]( | |
| class ApplyMLARotaryEmbKV(torch.autograd.Function): | |
| sin, | |
| emb_dim, | |
| k_dim, | |
| + k_dim_ceil, | |
| v_dim, | |
| nheads, | |
| batch_size, | |
| class ApplyMLARotaryEmbKV(torch.autograd.Function): | |
| d_kv = dk.new_empty(total_seqlen, nheads, ctx.k_dim + ctx.v_dim) | |
| d_emb = dk.new_empty(total_seqlen, 1, ctx.emb_dim) | |
| + k_dim_ceil = triton.next_power_of_2(ctx.k_dim) | |
| grid = lambda META: (total_seqlen, triton.cdiv(nheads, META["BLOCK_H"])) | |
| rotary_bwd_kv_kernel[grid]( | |
| class ApplyMLARotaryEmbKV(torch.autograd.Function): | |
| sin, | |
| ctx.emb_dim, | |
| ctx.k_dim, | |
| + k_dim_ceil, | |
| ctx.v_dim, | |
| nheads, | |
| batch_size, | |
| diff --git a/megatron/core/models/common/embeddings/rotary_pos_embedding.py b/megatron/core/models/common/embeddings/rotary_pos_embedding.py | |
| index 5d7b69cd3..2e0a26815 100644 | |
| --- a/megatron/core/models/common/embeddings/rotary_pos_embedding.py | |
| +++ b/megatron/core/models/common/embeddings/rotary_pos_embedding.py | |
| class MultimodalRotaryEmbedding(nn.Module): | |
| # shape (seq_length, bs, 1, 2 * dim) | |
| emb = emb[..., None, :].transpose(0, 1).contiguous() | |
| + packed_seq = packed_seq_params is not None and packed_seq_params.qkv_format == 'thd' | |
| if packed_seq_params is not None and packed_seq_params.local_cp_size is not None: | |
| if packed_seq_params.local_cp_size > 1: | |
| # Set CP group to dynamic CP group for CP slicing | |
| class MultimodalRotaryEmbedding(nn.Module): | |
| cp_group = None | |
| else: | |
| cp_group = self.cp_group | |
| - if cp_group is not None and cp_group.size() > 1: | |
| + # For THD (packed sequence) format, skip CP slicing here — it is handled | |
| + # per-sequence inside _apply_rotary_pos_emb_thd instead (same as RotaryEmbedding). | |
| + if cp_group is not None and cp_group.size() > 1 and not packed_seq: | |
| # slice rotary_pos_emb along sequence dimension and select the parition of the current | |
| # CP rank | |
| emb = get_pos_emb_on_this_cp_rank(emb, 0, cp_group) | |
| diff --git a/megatron/core/models/common/language_module/language_module.py b/megatron/core/models/common/language_module/language_module.py | |
| index 13d74aa52..060898a7a 100644 | |
| --- a/megatron/core/models/common/language_module/language_module.py | |
| +++ b/megatron/core/models/common/language_module/language_module.py | |
| class LanguageModule(MegatronModule): | |
| assert ( | |
| column_parallel_linear is not None | |
| ), "column_parallel_linear cannot be None when not using fused linear cross entropy." | |
| - logits, _ = column_parallel_linear(hidden, **col_linear_kwargs) | |
| + # output | |
| + output_layer_params = {k: v.detach() for k, v in column_parallel_linear.named_parameters()} | |
| + output_layer_buffers = dict(column_parallel_linear.named_buffers()) | |
| + logits, _ = torch.func.functional_call( | |
| + column_parallel_linear, | |
| + {**output_layer_params, **output_layer_buffers}, | |
| + (hidden,), | |
| + col_linear_kwargs, | |
| + ) | |
| return self.compute_language_model_loss(labels, logits) | |
| diff --git a/megatron/core/models/gpt/gpt_layer_specs.py b/megatron/core/models/gpt/gpt_layer_specs.py | |
| index e21127b87..712793853 100755 | |
| --- a/megatron/core/models/gpt/gpt_layer_specs.py | |
| +++ b/megatron/core/models/gpt/gpt_layer_specs.py | |
| def get_gpt_layer_with_transformer_engine_spec( | |
| use_kitchen: bool = False, | |
| use_te_activation_func: bool = False, | |
| fallback_to_eager_attn: bool = False, | |
| + post_self_attn_layernorm: bool = False, | |
| + post_mlp_layernorm: bool = False, | |
| ) -> ModuleSpec: | |
| """Use this spec to use lower-level Transformer Engine modules (required for fp8 training). | |
| def get_gpt_layer_with_transformer_engine_spec( | |
| mlp=mlp, | |
| sharded_state_dict_keys_map=sharded_state_dict_keys_map, | |
| normalization=normalization, | |
| + post_self_attn_layernorm=post_self_attn_layernorm, | |
| + post_mlp_layernorm=post_mlp_layernorm, | |
| ) | |
| def get_transformer_layer_spec_for_backend( | |
| mlp: ModuleSpec, | |
| sharded_state_dict_keys_map: Optional[dict] = None, | |
| normalization: Optional[str] = None, | |
| + post_self_attn_layernorm: bool = False, | |
| + post_mlp_layernorm: bool = False, | |
| ) -> ModuleSpec: | |
| """Helper function to get module spec for TransformerLayer""" | |
| def get_transformer_layer_spec_for_backend( | |
| input_layernorm=input_layernorm, | |
| self_attention=attention, | |
| self_attn_bda=get_bias_dropout_add, | |
| + post_self_attn_layernorm=TENorm if post_self_attn_layernorm else IdentityOp, | |
| pre_mlp_layernorm=pre_mlp_layernorm, | |
| mlp=mlp, | |
| mlp_bda=get_bias_dropout_add, | |
| + post_mlp_layernorm=TENorm if post_mlp_layernorm else IdentityOp, | |
| sharded_state_dict_keys_map=sharded_state_dict_keys_map, | |
| ), | |
| ) | |
| diff --git a/megatron/core/models/gpt/gpt_model.py b/megatron/core/models/gpt/gpt_model.py | |
| index a1230568c..1fd52f65a 100644 | |
| --- a/megatron/core/models/gpt/gpt_model.py | |
| +++ b/megatron/core/models/gpt/gpt_model.py | |
| class GPTModel(LanguageModule): | |
| *, | |
| inference_params: Optional[BaseInferenceContext] = None, | |
| loss_mask: Optional[Tensor] = None, | |
| + mtp_kwargs: Optional[dict] = {}, | |
| ) -> Tensor: | |
| """Forward function of the GPT Model This function passes the input tensors | |
| through the embedding layer, and then the decoder and finally into the post | |
| class GPTModel(LanguageModule): | |
| runtime_gather_output=runtime_gather_output, | |
| extra_block_kwargs=extra_block_kwargs, | |
| inference_context=inference_context, | |
| + mtp_kwargs=mtp_kwargs, | |
| ) | |
| def _postprocess( | |
| class GPTModel(LanguageModule): | |
| runtime_gather_output=None, | |
| extra_block_kwargs=None, | |
| inference_context=None, | |
| + mtp_kwargs={}, | |
| ): | |
| """Postprocesses decoder hidden states to generate logits or compute loss. | |
| class GPTModel(LanguageModule): | |
| output_weight = None | |
| if self.share_embeddings_and_output_weights: | |
| output_weight = self.shared_embedding_or_output_weight() | |
| - if mtp_in_postprocess: | |
| + | |
| + if mtp_in_postprocess and mtp_kwargs.get('mtp_labels', None) is not None: | |
| hidden_states = self.mtp( | |
| input_ids=input_ids, | |
| position_ids=position_ids, | |
| class GPTModel(LanguageModule): | |
| return hidden_states | |
| # Skip when mtp_num_layers is None or 0 | |
| - if self.config.mtp_num_layers: | |
| - mtp_labels = labels.clone() | |
| + if self.config.mtp_num_layers and mtp_kwargs.get('mtp_labels', None) is not None: | |
| + mtp_labels = mtp_kwargs['mtp_labels'].clone() | |
| + mtp_labels, _ = roll_tensor(mtp_labels, shifts=-1, dims=-1, cp_group=self.cp_group, packed_seq_params=packed_seq_params) | |
| + | |
| hidden_states_list = torch.chunk(hidden_states, 1 + self.config.mtp_num_layers, dim=0) | |
| hidden_states = hidden_states_list[0] | |
| if loss_mask is None: | |
| # if loss_mask is not provided, use all ones as loss_mask | |
| loss_mask = torch.ones_like(mtp_labels) | |
| + else: | |
| + # Otherwise, roll the loss_mask to keep up with the mtp_labels | |
| + loss_mask, _ = roll_tensor(loss_mask, shifts=-1, dims=-1, cp_group=self.cp_group, packed_seq_params=packed_seq_params) | |
| for mtp_layer_number in range(self.config.mtp_num_layers): | |
| # Calc loss for the current Multi-Token Prediction (MTP) layers. | |
| mtp_labels, _ = roll_tensor( | |
| class GPTModel(LanguageModule): | |
| sequence_parallel_enabled=self.output_layer.sequence_parallel, | |
| column_parallel_linear=self.output_layer, | |
| col_linear_kwargs={ | |
| - 'weight': output_weight, | |
| + 'weight': output_weight.detach() if output_weight else None, | |
| 'runtime_gather_output': runtime_gather_output, | |
| }, | |
| ) | |
| diff --git a/megatron/core/optimizer/distrib_optimizer.py b/megatron/core/optimizer/distrib_optimizer.py | |
| index 6e093f96f..eac21a3ea 100644 | |
| --- a/megatron/core/optimizer/distrib_optimizer.py | |
| +++ b/megatron/core/optimizer/distrib_optimizer.py | |
| class DistributedOptimizer(MixedPrecisionOptimizer): | |
| # TE FusedAdam will not accumulate step for empty param groups, so we need to | |
| # align the step across param groups. | |
| param_group["step"] = int(step) | |
| + if "step" in param_group and param_group["step"] is None: | |
| + del param_group["step"] | |
| # Grad scaler state. | |
| if self.grad_scaler: | |
| class DistributedOptimizer(MixedPrecisionOptimizer): | |
| if key == 'padding': | |
| tensors[key] = LocalNonpersistentObject(tensors[key]) | |
| continue | |
| + if key == 'step': | |
| + continue | |
| assert tensors[key].shape == (gbuf_local_end - gbuf_local_start,), ( | |
| tensors[key].shape, | |
| gbuf_local_start, | |
| diff --git a/megatron/core/parallel_state.py b/megatron/core/parallel_state.py | |
| index a273002b9..4f821cfd5 100644 | |
| --- a/megatron/core/parallel_state.py | |
| +++ b/megatron/core/parallel_state.py | |
| from typing import Callable, List, Optional | |
| import numpy as np | |
| import torch | |
| +import torch.distributed as dist | |
| from .utils import GlobalMemoryBuffer, is_torch_min_version | |
| diff --git a/megatron/core/pipeline_parallel/p2p_communication.py b/megatron/core/pipeline_parallel/p2p_communication.py | |
| index ac839c21f..f18309217 100644 | |
| --- a/megatron/core/pipeline_parallel/p2p_communication.py | |
| +++ b/megatron/core/pipeline_parallel/p2p_communication.py | |
| def _batched_p2p_ops( | |
| ops = [] | |
| if tensor_send_prev is not None: | |
| send_prev_op = torch.distributed.P2POp( | |
| - torch.distributed.isend, tensor_send_prev, prev_pipeline_rank, group | |
| + torch.distributed.isend, tensor_send_prev, prev_pipeline_rank, | |
| ) | |
| ops.append(send_prev_op) | |
| if tensor_recv_prev is not None: | |
| recv_prev_op = torch.distributed.P2POp( | |
| - torch.distributed.irecv, tensor_recv_prev, prev_pipeline_rank, group | |
| + torch.distributed.irecv, tensor_recv_prev, prev_pipeline_rank, | |
| ) | |
| ops.append(recv_prev_op) | |
| if tensor_send_next is not None: | |
| send_next_op = torch.distributed.P2POp( | |
| - torch.distributed.isend, tensor_send_next, next_pipeline_rank, group | |
| + torch.distributed.isend, tensor_send_next, next_pipeline_rank, | |
| ) | |
| ops.append(send_next_op) | |
| if tensor_recv_next is not None: | |
| recv_next_op = torch.distributed.P2POp( | |
| - torch.distributed.irecv, tensor_recv_next, next_pipeline_rank, group | |
| + torch.distributed.irecv, tensor_recv_next, next_pipeline_rank, | |
| ) | |
| ops.append(recv_next_op) | |
| if len(ops) > 0: | |
| diff --git a/megatron/core/transformer/moe/moe_utils.py b/megatron/core/transformer/moe/moe_utils.py | |
| index 28cff06f5..58dc4bb70 100644 | |
| --- a/megatron/core/transformer/moe/moe_utils.py | |
| +++ b/megatron/core/transformer/moe/moe_utils.py | |
| def topk_routing_with_score_function( | |
| else: | |
| return torch.topk(scores, k=topk, dim=1) | |
| + from slime.utils.routing_replay import get_routing_replay_compute_topk | |
| + compute_topk = get_routing_replay_compute_topk(compute_topk) | |
| + | |
| if score_function == "softmax": | |
| if use_pre_softmax: | |
| scores = torch.softmax(logits, dim=-1, dtype=torch.float32).type_as(logits) | |
| diff --git a/megatron/core/transformer/moe/router.py b/megatron/core/transformer/moe/router.py | |
| index 16fc9d9af..517944f25 100644 | |
| --- a/megatron/core/transformer/moe/router.py | |
| +++ b/megatron/core/transformer/moe/router.py | |
| class TopKRouter(Router): | |
| self.global_tokens_per_expert = None | |
| self.ga_steps = None | |
| + from slime.utils.routing_replay import register_routing_replay | |
| + register_routing_replay(self) | |
| + | |
| def _maintain_float32_expert_bias(self): | |
| """ | |
| Maintain the expert bias in float32. | |
| diff --git a/megatron/core/transformer/multi_token_prediction.py b/megatron/core/transformer/multi_token_prediction.py | |
| index a8f4abfcd..f33f6f05e 100755 | |
| --- a/megatron/core/transformer/multi_token_prediction.py | |
| +++ b/megatron/core/transformer/multi_token_prediction.py | |
| from typing import Callable, List, Optional, Union | |
| import torch | |
| from torch import Tensor | |
| +import warnings | |
| from megatron.core import InferenceParams, parallel_state, tensor_parallel | |
| from megatron.core.dist_checkpointing.mapping import ShardedStateDict | |
| class MultiTokenPredictionLayer(MegatronModule): | |
| cp_group=self.cp_group, | |
| packed_seq_params=packed_seq_params, | |
| ) | |
| - position_ids, _ = roll_tensor( | |
| - position_ids, | |
| - shifts=-1, | |
| - dims=-1, | |
| - cp_group=self.cp_group, | |
| - packed_seq_params=packed_seq_params, | |
| - ) | |
| + if position_ids is not None: | |
| + position_ids, _ = roll_tensor( | |
| + position_ids, | |
| + 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) | |
| + decoder_input = decoder_input.detach() | |
| - hidden_states = make_viewless_tensor(inp=hidden_states, requires_grad=True, keep_graph=True) | |
| + hidden_states = make_viewless_tensor(inp=hidden_states, requires_grad=True, keep_graph=False) | |
| return input_ids, position_ids, decoder_input, hidden_states | |
| class MultiTokenPredictionLayer(MegatronModule): | |
| return hidden_states | |
| def _checkpointed_forward(self, forward_func, *args, **kwargs): | |
| + """Wrap `forward_func` with activation checkpointing while only passing tensors. | |
| + | |
| + Non-tensor arguments (e.g., configuration objects, None) are captured via closure so | |
| + that checkpoint implementations never receive them directly, avoiding save_for_backward | |
| + issues with non-tensor inputs. | |
| + """ | |
| + | |
| + # TODO(jiajun): Is there any better implementation here? | |
| + positional_specs = [] | |
| + kw_specs = [] | |
| + tensor_args: List[torch.Tensor] = [] | |
| + | |
| + for arg in args: | |
| + if torch.is_tensor(arg): | |
| + positional_specs.append(('tensor', len(tensor_args))) | |
| + tensor_args.append(arg) | |
| + else: | |
| + positional_specs.append(('const', arg)) | |
| + | |
| + for key, value in kwargs.items(): | |
| + if torch.is_tensor(value): | |
| + kw_specs.append((key, ('tensor', len(tensor_args)))) | |
| + tensor_args.append(value) | |
| + else: | |
| + kw_specs.append((key, ('const', value))) | |
| + | |
| + def run(*flat_tensor_args): | |
| + rebuilt_args = [] | |
| + for spec_type, payload in positional_specs: | |
| + if spec_type == 'tensor': | |
| + rebuilt_args.append(flat_tensor_args[payload]) | |
| + else: | |
| + rebuilt_args.append(payload) | |
| + | |
| + rebuilt_kwargs = {} | |
| + for key, (spec_type, payload) in kw_specs: | |
| + if spec_type == 'tensor': | |
| + rebuilt_kwargs[key] = flat_tensor_args[payload] | |
| + else: | |
| + rebuilt_kwargs[key] = payload | |
| + | |
| + return forward_func(*rebuilt_args, **rebuilt_kwargs) | |
| + | |
| + tensor_args_tuple = tuple(tensor_args) | |
| + | |
| def checkpoint_handler(): | |
| """Determines whether to use the `te_checkpoint` or `tensor_parallel.checkpoint`""" | |
| if self.config.fp8: | |
| class MultiTokenPredictionLayer(MegatronModule): | |
| self.config.distribute_saved_activations, | |
| tensor_parallel.random.get_cuda_rng_tracker, | |
| parallel_state.get_tensor_model_parallel_group(), | |
| - *args, | |
| - **kwargs, | |
| + *tensor_args_tuple, | |
| ) | |
| else: | |
| return tensor_parallel.checkpoint( | |
| - forward_func, self.config.distribute_saved_activations, *args, *kwargs.values() | |
| + run, self.config.distribute_saved_activations, *tensor_args_tuple | |
| ) | |
| if self.config.recompute_method == 'uniform': | |
| diff --git a/megatron/core/transformer/transformer_config.py b/megatron/core/transformer/transformer_config.py | |
| index e2705bd9f..a0aa109b5 100644 | |
| --- a/megatron/core/transformer/transformer_config.py | |
| +++ b/megatron/core/transformer/transformer_config.py | |
| class TransformerConfig(ModelParallelConfig): | |
| attention_output_gate: bool = False | |
| """Whether to apply output gate to the attention layers.""" | |
| + post_self_attn_layernorm: bool = False | |
| + post_mlp_layernorm: bool = False | |
| + | |
| test_mode: bool = False | |
| """Whether to run real-time tests.""" | |
| diff --git a/megatron/core/transformer/transformer_layer.py b/megatron/core/transformer/transformer_layer.py | |
| index 3ea405770..5a42001b9 100644 | |
| --- a/megatron/core/transformer/transformer_layer.py | |
| +++ b/megatron/core/transformer/transformer_layer.py | |
| class TransformerLayerSubmodules: | |
| input_layernorm: Union[ModuleSpec, type] = IdentityOp | |
| self_attention: Union[ModuleSpec, type] = IdentityOp | |
| self_attn_bda: Union[ModuleSpec, type] = IdentityFuncOp | |
| + post_self_attn_layernorm: Union[ModuleSpec, type] = IdentityOp | |
| pre_cross_attn_layernorm: Union[ModuleSpec, type] = IdentityOp | |
| cross_attention: Union[ModuleSpec, type] = IdentityOp | |
| class TransformerLayerSubmodules: | |
| pre_mlp_layernorm: Union[ModuleSpec, type] = IdentityOp | |
| mlp: Union[ModuleSpec, type] = IdentityOp | |
| mlp_bda: Union[ModuleSpec, type] = IdentityFuncOp | |
| + post_mlp_layernorm: Union[ModuleSpec, type] = IdentityOp | |
| # Mapping for sharded tensor keys to be applied in `sharded_state_dict` method | |
| sharded_state_dict_keys_map: Dict[str, str] = field(default_factory=dict) | |
| class TransformerLayer(GraphableMegatronModule, BaseTransformerLayer): | |
| # [Module 3: BiasDropoutFusion] | |
| self.self_attn_bda = build_module(submodules.self_attn_bda) | |
| + self.post_self_attn_layernorm = build_module( | |
| + submodules.post_self_attn_layernorm, | |
| + config=self.config, | |
| + hidden_size=self.config.hidden_size, | |
| + eps=self.config.layernorm_epsilon, | |
| + ) | |
| + | |
| # [Module 4: Post SelfAttention] Optional Layernorm after self-attn | |
| self.pre_cross_attn_layernorm = build_module( | |
| submodules.pre_cross_attn_layernorm, | |
| class TransformerLayer(GraphableMegatronModule, BaseTransformerLayer): | |
| self.is_moe_layer = isinstance(self.mlp, MoELayer) | |
| + self.post_mlp_layernorm = build_module( | |
| + submodules.post_mlp_layernorm, | |
| + config=self.config, | |
| + hidden_size=self.config.hidden_size, | |
| + eps=self.config.layernorm_epsilon | |
| + ) | |
| + | |
| self.recompute_input_layernorm = False | |
| self.recompute_pre_mlp_layernorm = False | |
| self.recompute_mlp = False | |
| class TransformerLayer(GraphableMegatronModule, BaseTransformerLayer): | |
| attention_output_with_bias[0] | |
| ) | |
| + attention_output, attention_output_bias = attention_output_with_bias | |
| + attention_output = self.post_self_attn_layernorm(attention_output) | |
| + attention_output_with_bias = (attention_output, attention_output_bias) | |
| + | |
| # TODO: could we move `bias_dropout_add_exec_handler` itself | |
| # inside the module provided in the `bias_dropout_add_spec` module? | |
| nvtx_range_push(suffix="self_attn_bda") | |
| class TransformerLayer(GraphableMegatronModule, BaseTransformerLayer): | |
| else: | |
| mlp_output_with_bias = self.mlp(pre_mlp_layernorm_output) | |
| + mlp_output, mlp_output_bias = mlp_output_with_bias | |
| + mlp_output = self.post_mlp_layernorm(mlp_output) | |
| + mlp_output_with_bias = (mlp_output, mlp_output_bias) | |
| + | |
| if self.recompute_pre_mlp_layernorm: | |
| # discard the output of the pre-mlp layernorm and register the recompute | |
| # as a gradient hook of mlp_output_with_bias[0] | |
| diff --git a/megatron/training/arguments.py b/megatron/training/arguments.py | |
| index b267c8a81..83736acdc 100644 | |
| --- a/megatron/training/arguments.py | |
| +++ b/megatron/training/arguments.py | |
| def core_transformer_config_from_args(args, config_class=None): | |
| kw_args['inference_sampling_seed'] = args.seed | |
| + kw_args['post_self_attn_layernorm'] = args.post_self_attn_layernorm | |
| + kw_args['post_mlp_layernorm'] = args.post_mlp_layernorm | |
| + | |
| # handle quantization config | |
| # NOTE: Kitchen arguments are only added to the namespace when | |
| # Kitchen library is available. | |
| def _add_network_size_args(parser): | |
| action='store_true', | |
| help='If set, use original BERT residula connection ' | |
| 'ordering.') | |
| + group.add_argument('--post-self-attn-layernorm', action='store_true', | |
| + help='If set, use post self attention layernorm.') | |
| + group.add_argument('--post-mlp-layernorm', action='store_true', | |
| + help='If set, use post MLP layernorm.') | |
| + group.add_argument('--use-gated-attention', action='store_true', | |
| + help='If set, use gated attention as in Qwen3Next') | |
| group.add_argument('--openai-gelu', action='store_true', | |
| help='Use OpenAIs GeLU implementation. This option' | |
| 'should not be used unless for backward compatibility' | |
| diff --git a/megatron/training/tokenizer/tokenizer.py b/megatron/training/tokenizer/tokenizer.py | |
| index 13b7526ca..6c590f653 100644 | |
| --- a/megatron/training/tokenizer/tokenizer.py | |
| +++ b/megatron/training/tokenizer/tokenizer.py | |
| class _HuggingFaceTokenizer(MegatronLegacyTokenizer): | |
| # TODO(bnorick): download tokenizer once to lustre and use force offline to make sure all tasks read it from there | |
| self._tokenizer = transformers.AutoTokenizer.from_pretrained( | |
| pretrained_model_name_or_path=pretrained_model_name_or_path, | |
| - trust_remote_code=trust_remote_code, | |
| + trust_remote_code=True, | |
| **kwargs, | |
| ) | |
| self._vocab = self._tokenizer.get_vocab() | |