-
Notifications
You must be signed in to change notification settings - Fork 5k
Fix ZeRO-3 checkpoint tag selection during weight reconstruction #8501
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
base: master
Are you sure you want to change the base?
Changes from all commits
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 |
|---|---|---|
|
|
@@ -20,6 +20,69 @@ | |
| import pytest | ||
|
|
||
|
|
||
| class TestZeROCheckpointTag(DistributedTest): | ||
|
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.
This non-merge commit has no AGENTS.md reference: AGENTS.md:L8-L8 Useful? React with 👍 / 👎. |
||
| world_size = [1, 2] | ||
|
|
||
| @pytest.mark.parametrize('tag,save_latest,load_optimizer_states,load_module_only', [ | ||
| ('earlier', True, False, False), | ||
| ('earlier', False, False, False), | ||
| ('earlier', True, False, True), | ||
| ('earlier', False, False, True), | ||
| ('earlier', True, True, False), | ||
| (None, True, False, False), | ||
| ]) | ||
| def test_load_requested_tag(self, tmpdir, tag, save_latest, load_optimizer_states, load_module_only): | ||
| config = { | ||
| 'train_micro_batch_size_per_gpu': 1, | ||
| 'zero_allow_untested_optimizer': True, | ||
| 'zero_optimization': { | ||
| 'stage': 3, | ||
| 'reduce_bucket_size': 1000, | ||
| 'stage3_prefetch_bucket_size': 1000, | ||
| }, | ||
| } | ||
|
|
||
| def make_engine(): | ||
| model = torch.nn.Linear(4, 2) | ||
| optimizer = torch.optim.Adam(model.parameters(), lr=0.1) | ||
| return deepspeed.initialize(model=model, optimizer=optimizer, config=config)[0] | ||
|
|
||
| def snapshot(engine): | ||
| with deepspeed.zero.GatheredParameters(list(engine.module.parameters())): | ||
| return {name: value.detach().clone() for name, value in engine.module.state_dict().items()} | ||
|
|
||
| source = make_engine() | ||
| target = None | ||
| try: | ||
| snapshots = {} | ||
| for checkpoint_tag in ('earlier', 'later'): | ||
| loss = source(torch.ones(1, 4, device=source.device)).square().mean() | ||
| source.backward(loss) | ||
| source.step() | ||
| snapshots[checkpoint_tag] = snapshot(source) | ||
| source.save_checkpoint(tmpdir, | ||
| tag=checkpoint_tag, | ||
| client_state={'label': checkpoint_tag}, | ||
| save_latest=save_latest) | ||
|
|
||
| assert any(not torch.equal(snapshots['earlier'][name], value) | ||
| for name, value in snapshots['later'].items()) | ||
| target = make_engine() | ||
| load_path, client_state = target.load_checkpoint(tmpdir, | ||
| tag=tag, | ||
| load_optimizer_states=load_optimizer_states, | ||
| load_module_only=load_module_only) | ||
| expected_tag = tag if tag is not None else 'later' | ||
| assert load_path is not None | ||
| assert client_state['label'] == expected_tag | ||
| for name, value in snapshot(target).items(): | ||
| torch.testing.assert_close(value, snapshots[expected_tag][name], rtol=0, atol=0) | ||
| finally: | ||
| if target is not None: | ||
| target.destroy() | ||
| source.destroy() | ||
|
|
||
|
|
||
| class TestZeROCheckpoint(DistributedTest): | ||
| world_size = 2 | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When a checkpoint was saved with a numeric tag and the caller later uses the same numeric value in
load_checkpoint, this ZeRO-3 path now passes the integer directly toget_fp32_state_dict_from_zero_checkpoint, whoseos.path.join(checkpoint_dir, tag)raisesTypeError. This previously worked with the defaultsave_latest=Truebecause reconstruction re-read the stringified tag fromlatest, andsave_checkpointexplicitly supports such values by applyingstr(tag); normalize the resolved load tag similarly before forwarding it.Useful? React with 👍 / 👎.