Skip to content

Commit a5e17dc

Browse files
authored
[ckpt] fix: Skip unavailable RNG shards after DP resize (#5988)
Signed-off-by: Yu Yao <yaoyu.094@gmail.com>
1 parent 2fdc85e commit a5e17dc

2 files changed

Lines changed: 23 additions & 4 deletions

File tree

‎src/megatron/bridge/training/checkpointing.py‎

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -610,13 +610,14 @@ def get_rng_state(
610610
return rng_state_list
611611

612612

613-
def _align_rng_state_sharded_metadata(rng_state: ShardedObject, checkpoint_name: str) -> ShardedObject:
613+
def _align_rng_state_sharded_metadata(rng_state: ShardedObject, checkpoint_name: str) -> ShardedObject | None:
614614
"""Align RNG load metadata with the layout stored in a torch-dist checkpoint.
615615
616616
Newer MCore checkpoints shard RNG state across PP, TP, and DP/CP, while
617617
older checkpoints encode DP as a replica ID. Keep the generated metadata
618618
when its exact key exists; otherwise adopt a unique stored layout whose
619-
PP/TP prefix matches this rank.
619+
PP/TP prefix matches this rank. Return ``None`` when this rank is outside
620+
the stored DP/CP extent so the caller can keep its freshly initialized RNG.
620621
"""
621622
checkpoint_path = Path(checkpoint_name)
622623
if not (checkpoint_path / ".metadata").is_file():
@@ -627,17 +628,21 @@ def _align_rng_state_sharded_metadata(rng_state: ShardedObject, checkpoint_name:
627628
return rng_state
628629

629630
prefix = rng_state.global_offset[:2]
630-
matches = [
631+
compatible_layouts = [
631632
metadata
632633
for metadata in sharded_metadata.values()
633634
if isinstance(metadata, ShardedObject)
634635
and metadata.key == rng_state.key
635636
and metadata.global_offset[:2] == prefix
636637
and len(metadata.global_offset) == len(rng_state.global_offset) + 1
637-
and metadata.global_offset[-1] == rng_state.replica_id
638638
and metadata.replica_id == 0
639639
]
640+
matches = [metadata for metadata in compatible_layouts if metadata.global_offset[-1] == rng_state.replica_id]
640641
if len(matches) != 1:
642+
if compatible_layouts and all(
643+
rng_state.replica_id >= metadata.global_shape[-1] for metadata in compatible_layouts
644+
):
645+
return None
641646
return rng_state
642647

643648
stored = matches[0]
@@ -3015,6 +3020,9 @@ def _load_checkpoint_from_path(
30153020
)
30163021
if ckpt_type != CheckpointType.LOCAL:
30173022
gen_sd_rng_state = _align_rng_state_sharded_metadata(gen_sd_rng_state, checkpoint_name)
3023+
if gen_sd_rng_state is None:
3024+
ignore_rng_state = True
3025+
print_rank_0("RNG state has no shard for this DP/CP rank; using freshly initialized RNG state")
30183026
else:
30193027
ignore_rng_state = True
30203028
gen_sd_rng_state = None

‎tests/unit_tests/training/test_checkpointing.py‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6051,6 +6051,17 @@ def test_adopts_unique_dp_cp_sharded_layout(self, mock_strategy, _mock_is_file):
60516051
assert result.global_offset == (1, 3, 5)
60526052
assert result.replica_id == 0
60536053

6054+
@patch("megatron.bridge.training.checkpointing.Path.is_file", return_value=True)
6055+
@patch("megatron.bridge.training.checkpointing.TorchDistLoadShardedStrategy")
6056+
def test_returns_none_without_a_dp_cp_shard_for_this_rank(self, mock_strategy, _mock_is_file):
6057+
rng_state = self._rng(replica_id=5)
6058+
stored = [self._rng(global_offset=(1, 3, rank), global_shape=(2, 4, 4), replica_id=0) for rank in range(4)]
6059+
mock_strategy.return_value.load_sharded_metadata.return_value = {item.unique_key: item for item in stored}
6060+
6061+
result = _align_rng_state_sharded_metadata(rng_state, "/checkpoint")
6062+
6063+
assert result is None
6064+
60546065
@pytest.mark.parametrize("stored", [{}, None])
60556066
@patch("megatron.bridge.training.checkpointing.Path.is_file", return_value=True)
60566067
@patch("megatron.bridge.training.checkpointing.TorchDistLoadShardedStrategy")

0 commit comments

Comments
 (0)