-
Notifications
You must be signed in to change notification settings - Fork 4.4k
base strategy simplification #4001
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
027e064
17168af
8621dde
8687661
bb1ed10
358d076
cf3f930
557a1d9
39fd4a2
36c1711
2436abc
25b15a5
b0990ed
a3f8d6d
f1d3f87
67e70bf
80283cc
2132326
d0899ae
f051146
2192dae
91b0706
ca20c94
8894445
9aa2ffc
f2a3842
39b7aca
6579e03
b1c4f49
3ee2f72
1d394b0
c03e751
d8f2bcb
778a158
1e4e81e
4aea010
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -23,10 +23,9 @@ | |||||||||
| exchange_loaded_objects_gather_object, | ||||||||||
| ) | ||||||||||
| from megatron.core.dist_checkpointing.mapping import ShardedStateDict, StateDict, is_main_replica | ||||||||||
| from megatron.core.dist_checkpointing.strategies.base import ( | ||||||||||
| AsyncSaveShardedStrategy, | ||||||||||
| LoadShardedStrategy, | ||||||||||
| SaveShardedStrategy, | ||||||||||
| from megatron.core.dist_checkpointing.strategies.torch import ( | ||||||||||
| TorchDistLoadShardedStrategy, | ||||||||||
| TorchDistSaveShardedStrategy, | ||||||||||
| ) | ||||||||||
| from megatron.core.dist_checkpointing.utils import ( | ||||||||||
| _sharded_object_id, | ||||||||||
|
|
@@ -38,14 +37,13 @@ | |||||||||
| determine_global_metadata, | ||||||||||
| validate_sharding_integrity, | ||||||||||
| ) | ||||||||||
| from megatron.core.utils import get_pg_rank, get_pg_size | ||||||||||
|
|
||||||||||
| logger = logging.getLogger(__name__) | ||||||||||
|
|
||||||||||
| T = TypeVar('T', ShardedObject, ShardedTensor) | ||||||||||
|
|
||||||||||
|
|
||||||||||
| class FullyParallelSaveStrategyWrapper(AsyncSaveShardedStrategy): | ||||||||||
| class FullyParallelSaveStrategyWrapper: | ||||||||||
| """Wraps arbitrary strategy and distributes the save during `save`. | ||||||||||
|
|
||||||||||
| The save distribution happens without any *data* communication. | ||||||||||
|
|
@@ -60,7 +58,7 @@ class FullyParallelSaveStrategyWrapper(AsyncSaveShardedStrategy): | |||||||||
| described in `distribute_shards_to_ranks`. | ||||||||||
|
|
||||||||||
| Args: | ||||||||||
| strategy (SaveShardedStrategy): base strategy to wrap | ||||||||||
| strategy (TorchDistSaveShardedStrategy): base strategy to wrap | ||||||||||
| parallelization_group (ProcessGroup, optional): process group to use for save | ||||||||||
| distribution. Note that this doesn't have to match exactly the | ||||||||||
| data distribution, but should cover the replication pattern | ||||||||||
|
|
@@ -72,16 +70,20 @@ class FullyParallelSaveStrategyWrapper(AsyncSaveShardedStrategy): | |||||||||
|
|
||||||||||
| def __init__( | ||||||||||
| self, | ||||||||||
| strategy: SaveShardedStrategy, | ||||||||||
| strategy: TorchDistSaveShardedStrategy, | ||||||||||
| parallelization_group: Optional[torch.distributed.ProcessGroup] = None, | ||||||||||
|
Comment on lines
+73
to
74
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The old code inherited
Suggested change
Then below: self.backend = backend if backend is not None else strategy.backend
self.version = version if version is not None else strategy.version
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. no, it shouldn't. We want to ged rid of metadata in the future since we don't have different versiononing and only a single backend.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we not foresee a future where versioned checkpoints might be useful? |
||||||||||
| do_cache_distribution: bool = False, | ||||||||||
| backend: str = "torch_dist", | ||||||||||
| version: int = 1, | ||||||||||
| ): | ||||||||||
| super().__init__(strategy.backend, strategy.version) | ||||||||||
| """ """ | ||||||||||
| self.base_strategy = strategy | ||||||||||
| if parallelization_group is None: | ||||||||||
| parallelization_group = torch.distributed.group.WORLD | ||||||||||
| self.parallelization_group = parallelization_group | ||||||||||
| self.do_cache_distribution = do_cache_distribution | ||||||||||
| self.backend = backend | ||||||||||
| self.version = version | ||||||||||
|
|
||||||||||
| self.cached_distribution: Optional[ShardDistribution] = None | ||||||||||
|
|
||||||||||
|
|
@@ -92,10 +94,6 @@ def async_save( | |||||||||
| async_strategy: str = "nvrx", | ||||||||||
| ): | ||||||||||
| """ """ | ||||||||||
| if not isinstance(self.base_strategy, AsyncSaveShardedStrategy): | ||||||||||
| raise CheckpointingException( | ||||||||||
| f'Cannot apply async_save to non-async base strategy {self.base_strategy}' | ||||||||||
| ) | ||||||||||
| self.apply_saving_parallelization(sharded_state_dict) | ||||||||||
| return self.base_strategy.async_save(sharded_state_dict, checkpoint_dir, async_strategy) | ||||||||||
|
|
||||||||||
|
|
@@ -140,19 +138,14 @@ def apply_saving_parallelization(self, sharded_state_dict: ShardedStateDict) -> | |||||||||
| end = time() | ||||||||||
| logger.debug(f"parallel save sharding, time: {end - start}") | ||||||||||
|
|
||||||||||
| @property | ||||||||||
| def can_handle_sharded_objects(self): | ||||||||||
| """ """ | ||||||||||
| return self.base_strategy.can_handle_sharded_objects | ||||||||||
|
|
||||||||||
|
|
||||||||||
| class FullyParallelLoadStrategyWrapper(LoadShardedStrategy): | ||||||||||
| class FullyParallelLoadStrategyWrapper: | ||||||||||
| """Wraps arbitrary load strategy and distributes the load during `load`. | ||||||||||
|
|
||||||||||
| See `load` method docs for details. | ||||||||||
|
|
||||||||||
| Args: | ||||||||||
| strategy (LoadShardedStrategy): base strategy to wrap | ||||||||||
| strategy (TorchDistLoadShardedStrategy): base strategy to wrap | ||||||||||
| parallelization_group (ProcessGroup, optional): process group to use for load | ||||||||||
| distribution. Note that this doesn't have to match exactly the | ||||||||||
| data distribution, but should cover the replication pattern | ||||||||||
|
|
@@ -174,12 +167,11 @@ class FullyParallelLoadStrategyWrapper(LoadShardedStrategy): | |||||||||
|
|
||||||||||
| def __init__( | ||||||||||
| self, | ||||||||||
| strategy: LoadShardedStrategy, | ||||||||||
| strategy: TorchDistLoadShardedStrategy, | ||||||||||
| parallelization_group: Optional[torch.distributed.ProcessGroup] = None, | ||||||||||
| do_cache_distribution: bool = False, | ||||||||||
| exchange_algo: str = 'broadcast', | ||||||||||
| ): | ||||||||||
| super().__init__() | ||||||||||
| self.base_strategy = strategy | ||||||||||
| if parallelization_group is None: | ||||||||||
| parallelization_group = ( | ||||||||||
|
|
@@ -227,6 +219,7 @@ def load( | |||||||||
| a state dict that would be loaded with the underlying strategy | ||||||||||
| without this wrapper. | ||||||||||
| """ | ||||||||||
| from megatron.core.utils import get_pg_size | ||||||||||
|
|
||||||||||
| loaded_state_dict = {} | ||||||||||
|
|
||||||||||
|
|
@@ -403,11 +396,6 @@ def apply_loading_parallelization( | |||||||||
|
|
||||||||||
| return precomputed_distribution | ||||||||||
|
|
||||||||||
| @property | ||||||||||
| def can_handle_sharded_objects(self): | ||||||||||
| """ """ | ||||||||||
| return self.base_strategy.can_handle_sharded_objects | ||||||||||
|
|
||||||||||
| def load_tensors_metadata(self, checkpoint_dir: Path): | ||||||||||
| """ """ | ||||||||||
| return self.base_strategy.load_tensors_metadata(checkpoint_dir) | ||||||||||
|
|
@@ -416,14 +404,6 @@ def load_sharded_metadata(self, checkpoint_dir: Path): | |||||||||
| """ """ | ||||||||||
| return self.base_strategy.load_sharded_metadata(checkpoint_dir) | ||||||||||
|
|
||||||||||
| def check_backend_compatibility(self, loaded_version): | ||||||||||
| """ """ | ||||||||||
| return self.base_strategy.check_backend_compatibility(loaded_version) | ||||||||||
|
|
||||||||||
| def check_version_compatibility(self, loaded_version): | ||||||||||
| """ """ | ||||||||||
| return self.base_strategy.check_version_compatibility(loaded_version) | ||||||||||
|
|
||||||||||
|
|
||||||||||
| def distribute_main_replicas_with_precomputed_distribution( | ||||||||||
| sharded_state_dict: ShardedStateDict, | ||||||||||
|
|
@@ -455,6 +435,8 @@ def distribute_main_replicas_with_precomputed_distribution( | |||||||||
| rank1: A: 1, B: 0, C: 1 | ||||||||||
| rank2: A: 1, B: 1, C: 0 | ||||||||||
| """ | ||||||||||
| from megatron.core.utils import get_pg_rank, get_pg_size | ||||||||||
|
|
||||||||||
| if parallelization_group is None: | ||||||||||
| parallelization_group = torch.distributed.group.WORLD | ||||||||||
| if get_pg_size(group=parallelization_group) <= 1: | ||||||||||
|
|
||||||||||
Uh oh!
There was an error while loading. Please reload this page.