2021-07-30 10:31:08 +00:00
|
|
|
import os
|
|
|
|
from pathlib import Path
|
|
|
|
from typing import Any, Dict, Union
|
2021-02-22 00:02:31 +00:00
|
|
|
|
|
|
|
import pytest
|
|
|
|
import torch
|
2021-03-23 08:35:51 +00:00
|
|
|
|
2021-03-22 11:43:53 +00:00
|
|
|
from pytorch_lightning import Trainer
|
2021-02-22 00:02:31 +00:00
|
|
|
from pytorch_lightning.accelerators import CPUAccelerator
|
|
|
|
from pytorch_lightning.plugins import SingleDevicePlugin
|
2021-08-13 16:35:31 +00:00
|
|
|
from pytorch_lightning.plugins.io.torch_plugin import TorchCheckpointIO
|
2021-06-07 10:37:09 +00:00
|
|
|
from pytorch_lightning.plugins.precision.precision_plugin import PrecisionPlugin
|
2021-03-22 11:43:53 +00:00
|
|
|
from tests.helpers.boring_model import BoringModel
|
2021-02-22 00:02:31 +00:00
|
|
|
|
|
|
|
|
2021-03-22 11:43:53 +00:00
|
|
|
@pytest.mark.parametrize("delay_dispatch", [True, False])
|
|
|
|
def test_plugin_setup_optimizers_in_pre_dispatch(tmpdir, delay_dispatch):
|
2021-09-06 12:49:09 +00:00
|
|
|
"""Test when using a custom training type plugin that delays setup optimizers, we do not call setup optimizers
|
|
|
|
till ``pre_dispatch``."""
|
2021-03-22 11:43:53 +00:00
|
|
|
|
|
|
|
class TestModel(BoringModel):
|
|
|
|
def on_fit_start(self):
|
|
|
|
if delay_dispatch:
|
|
|
|
# Ensure we haven't setup optimizers if we've delayed dispatch
|
|
|
|
assert len(self.trainer.optimizers) == 0
|
|
|
|
else:
|
|
|
|
assert len(self.trainer.optimizers) > 0
|
|
|
|
|
|
|
|
def on_fit_end(self):
|
|
|
|
assert len(self.trainer.optimizers) > 0
|
|
|
|
|
|
|
|
class CustomPlugin(SingleDevicePlugin):
|
|
|
|
@property
|
|
|
|
def setup_optimizers_in_pre_dispatch(self) -> bool:
|
|
|
|
return delay_dispatch
|
|
|
|
|
|
|
|
model = TestModel()
|
2021-11-17 22:41:50 +00:00
|
|
|
trainer = Trainer(default_root_dir=tmpdir, fast_dev_run=True, strategy=CustomPlugin(device=torch.device("cpu")))
|
2021-03-22 11:43:53 +00:00
|
|
|
trainer.fit(model)
|
2021-06-07 10:37:09 +00:00
|
|
|
|
|
|
|
|
2021-07-30 10:31:08 +00:00
|
|
|
def test_restore_checkpoint_after_pre_dispatch_default():
|
2021-09-06 12:49:09 +00:00
|
|
|
"""Assert default for restore_checkpoint_after_pre_dispatch is False."""
|
2021-07-30 10:31:08 +00:00
|
|
|
plugin = SingleDevicePlugin(torch.device("cpu"))
|
|
|
|
accelerator = CPUAccelerator(training_type_plugin=plugin, precision_plugin=PrecisionPlugin())
|
2021-10-14 15:38:22 +00:00
|
|
|
assert not accelerator.training_type_plugin.restore_checkpoint_after_pre_dispatch
|
2021-07-30 10:31:08 +00:00
|
|
|
assert not plugin.restore_checkpoint_after_pre_dispatch
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.parametrize("restore_after_pre_dispatch", [True, False])
|
|
|
|
def test_restore_checkpoint_after_pre_dispatch(tmpdir, restore_after_pre_dispatch):
|
2021-09-06 12:49:09 +00:00
|
|
|
"""Test to ensure that if restore_checkpoint_after_pre_dispatch is True, then we only load the state after pre-
|
|
|
|
dispatch is called."""
|
2021-07-30 10:31:08 +00:00
|
|
|
|
|
|
|
class TestPlugin(SingleDevicePlugin):
|
|
|
|
predispatched_called = False
|
|
|
|
|
|
|
|
def pre_dispatch(self) -> None:
|
|
|
|
super().pre_dispatch()
|
|
|
|
self.predispatched_called = True
|
|
|
|
|
|
|
|
@property
|
|
|
|
def restore_checkpoint_after_pre_dispatch(self) -> bool:
|
|
|
|
return restore_after_pre_dispatch
|
|
|
|
|
2021-08-23 20:12:18 +00:00
|
|
|
def load_checkpoint(self, checkpoint_path: Union[str, Path]) -> Dict[str, Any]:
|
2021-07-30 10:31:08 +00:00
|
|
|
assert self.predispatched_called == restore_after_pre_dispatch
|
2021-08-23 20:12:18 +00:00
|
|
|
return super().load_checkpoint(checkpoint_path)
|
2021-07-30 10:31:08 +00:00
|
|
|
|
|
|
|
model = BoringModel()
|
|
|
|
trainer = Trainer(default_root_dir=tmpdir, fast_dev_run=True)
|
|
|
|
trainer.fit(model)
|
|
|
|
|
|
|
|
checkpoint_path = os.path.join(tmpdir, "model.pt")
|
|
|
|
trainer.save_checkpoint(checkpoint_path)
|
|
|
|
|
2021-08-13 16:35:31 +00:00
|
|
|
plugin = TestPlugin(torch.device("cpu"), checkpoint_io=TorchCheckpointIO())
|
2021-07-30 10:31:08 +00:00
|
|
|
accelerator = CPUAccelerator(training_type_plugin=plugin, precision_plugin=PrecisionPlugin())
|
|
|
|
|
2021-10-14 15:38:22 +00:00
|
|
|
assert accelerator.training_type_plugin.restore_checkpoint_after_pre_dispatch == restore_after_pre_dispatch
|
2021-07-30 10:31:08 +00:00
|
|
|
assert plugin.restore_checkpoint_after_pre_dispatch == restore_after_pre_dispatch
|
|
|
|
|
2021-10-25 19:05:31 +00:00
|
|
|
trainer = Trainer(default_root_dir=tmpdir, accelerator=accelerator, fast_dev_run=True)
|
|
|
|
trainer.fit(model, ckpt_path=checkpoint_path)
|
2021-07-30 10:31:08 +00:00
|
|
|
for func in (trainer.test, trainer.validate, trainer.predict):
|
|
|
|
accelerator.training_type_plugin.predispatched_called = False
|
|
|
|
func(model, ckpt_path=checkpoint_path)
|