Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions pytorch_lightning/strategies/ddp_spawn.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,10 @@ def _is_single_process_single_device(self):
def _configure_launcher(self):
self._launcher = _SpawnLauncher(self)

@property
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we move the property up to join the others?

def is_interactive_compatible(self) -> bool:
return True
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

well, unfortunately no longer #7550 :(((


def setup(self, trainer: "pl.Trainer") -> None:
os.environ["MASTER_PORT"] = str(self.cluster_environment.main_port)
super().setup(trainer)
Expand Down
4 changes: 4 additions & 0 deletions pytorch_lightning/strategies/dp.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ def node_rank(self) -> int:
def world_size(self) -> int:
return 1

@property
def is_interactive_compatible(self) -> bool:
return True

def setup(self, trainer: "pl.Trainer") -> None:
# model needs to be moved to the device before it is wrapped
self.model_to_device()
Expand Down
4 changes: 4 additions & 0 deletions pytorch_lightning/strategies/tpu_spawn.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@ def world_size(self) -> int:
def root_device(self) -> torch.device:
return xm.xla_device()

@property
def is_interactive_compatible(self) -> bool:
return True

@staticmethod
def _validate_dataloader(dataloaders: Union[List[DataLoader], DataLoader]) -> None:
if not isinstance(dataloaders, list):
Expand Down
34 changes: 15 additions & 19 deletions pytorch_lightning/trainer/connectors/accelerator_connector.py
Original file line number Diff line number Diff line change
Expand Up @@ -593,6 +593,21 @@ def _init_strategy(self) -> None:
else:
raise RuntimeError(f"{self.strategy} is not valid type: {self.strategy}")

from pytorch_lightning.utilities import _IS_INTERACTIVE

is_interactive_compatible = (
self.strategy.is_interactive_compatible if hasattr(self.strategy, "is_interactive_compatible") else False
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should these specific hasattr checks could be formalized as traits or mixins? someone has to go deep into the code to realize these specific properties need to be added to their strategy for this to work. we had the same discussion for backward sync

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not add it to the base class and have it default to False?

)
if _IS_INTERACTIVE and not is_interactive_compatible:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do the _IS_INTERACTIVE check first. you can return early if it's not interactive. then you only need to check the strategy's property afterward instead of always checking it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to have strategy object to get the is_interactive_compatible property.

Copy link
Contributor

@carmocca carmocca Feb 18, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think Ananth means:

if _IS_INTERACTIVE and hasattr(self.strategy, "is_interactive_compatible") and not self.strategy.is_interactive_compatible:
    raise ...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if not _IS_INTERACTIVE:
    return

if hasattr(self.strategy, "is_interactive_compatible") and not self.strategy.is_interactive_compatible:
    raise

raise MisconfigurationException(
f"`Trainer(strategy={self.strategy.strategy_name!r})` or"
f" `Trainer(accelerator={self.strategy.strategy_name!r})` is not compatible with an interactive"
" environment. Run your code as a script, or choose one of the compatible backends, for example:"
"dp, ddp_spawn, ddp_shard_spawn or tpu_spawn"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"dp, ddp_spawn, ddp_shard_spawn or tpu_spawn"
" dp, ddp_sharded_spawn or tpu_spawn."

" In case you are spawning processes yourself, make sure to include the Trainer"
" creation inside the worker function."
)

def _check_and_init_precision(self) -> PrecisionPlugin:
self._validate_precision_choice()
if isinstance(self._precision_plugin_flag, PrecisionPlugin):
Expand Down Expand Up @@ -713,25 +728,6 @@ def _lazy_init_strategy(self) -> None:
self.strategy.set_world_ranks()
self.strategy._configure_launcher()

from pytorch_lightning.utilities import _IS_INTERACTIVE

# TODO move is_compatible logic to strategy API
interactive_compatible_strategy = (
DataParallelStrategy.strategy_name,
DDPSpawnStrategy.strategy_name,
DDPSpawnShardedStrategy.strategy_name,
TPUSpawnStrategy.strategy_name,
)
if _IS_INTERACTIVE and self.strategy.strategy_name not in interactive_compatible_strategy:
raise MisconfigurationException(
f"`Trainer(strategy={self.strategy.strategy_name!r})` or"
f" `Trainer(accelerator={self.strategy.strategy_name!r})` is not compatible with an interactive"
" environment. Run your code as a script, or choose one of the compatible backends:"
f" {', '.join(interactive_compatible_strategy)}."
" In case you are spawning processes yourself, make sure to include the Trainer"
" creation inside the worker function."
)

# TODO: should be moved to _check_strategy_and_fallback().
# Current test check precision first, so keep this check here to meet error order
if isinstance(self.accelerator, TPUAccelerator) and not isinstance(
Expand Down
14 changes: 0 additions & 14 deletions pytorch_lightning/utilities/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,20 +124,6 @@ class DistributedType(LightningEnum, metaclass=_OnAccessEnumMeta):
DDP_SHARDED_SPAWN = "ddp_sharded_spawn"
DDP_FULLY_SHARDED = "ddp_fully_sharded"

@staticmethod
def interactive_compatible_types() -> list[DistributedType]:
"""Returns a list containing interactive compatible DistributeTypes."""
return [
DistributedType.DP,
DistributedType.DDP_SPAWN,
DistributedType.DDP_SHARDED_SPAWN,
DistributedType.TPU_SPAWN,
]

def is_interactive_compatible(self) -> bool:
"""Returns whether self is interactive compatible."""
return self in DistributedType.interactive_compatible_types()

def deprecate(self) -> None:
rank_zero_deprecation(
"`DistributedType` Enum has been deprecated in v1.6 and will be removed in v1.8."
Expand Down