Skip to content
Merged
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
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ repos:
exclude_types: ["python", "jupyter", "shell", "gitignore"]

- repo: https://github.com/python/black
rev: 19.10b0
rev: 21.12b0
hooks:
- id: black
language_version: python3.8
Expand Down
8 changes: 4 additions & 4 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,11 +109,11 @@ If you modify the code, you will most probably also need to code some tests to e

- naming convention for files `test_*.py`, e.g. `test_precision.py`
- naming of testing functions `def test_*`, e.g. `def test_precision_on_random_data()`
- if test function should run on GPU, please **make sure to add `cuda`** in the test name, e.g. `def test_something_on_cuda()`.
- if test function should run on GPU, please **make sure to add `cuda`** in the test name, e.g. `def test_something_on_cuda()`.
Additionally, we may want to decorate it with `@pytest.mark.skipif(not torch.cuda.is_available(), reason="Skip if no GPU")`.
For more examples, please see https://github.com/pytorch/ignite/blob/master/tests/ignite/engine/test_create_supervised.py
- if test function checks distributed configuration, we have to mark the test as `@pytest.mark.distributed` and additional
conditions depending on the intended checks. For example, please see
- if test function checks distributed configuration, we have to mark the test as `@pytest.mark.distributed` and additional
conditions depending on the intended checks. For example, please see
https://github.com/pytorch/ignite/blob/master/tests/ignite/metrics/test_accuracy.py


Expand All @@ -131,7 +131,7 @@ format and check codebase for compliance with PEP8.
If you choose not to use pre-commit, you can take advantage of IDE extensions configured to black format or invoke
black manually to format files and commit them.

To install `flake8`, `black==19.10b0`, `isort==5.7.0` and `mypy`, please run
To install `flake8`, `black==21.12b0`, `isort==5.7.0` and `mypy`, please run
```bash
bash ./tests/run_code_style.sh install
```
Expand Down
7 changes: 3 additions & 4 deletions ignite/distributed/comp_models/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ def _encode_str(x: str, device: torch.device, size: int) -> torch.Tensor:
return padded_x.unsqueeze(0)

def _get_max_length(self, x: str, device: torch.device) -> int:
size = torch.tensor([len(x),], device=device)
size = torch.tensor([len(x)], device=device)
size = self._do_all_reduce(size, "MAX")
return cast(int, size.item())

Expand Down Expand Up @@ -245,7 +245,7 @@ def broadcast(
if rank != src:
tensor = torch.empty(1, device=device, dtype=torch.float)
else:
tensor = torch.tensor([tensor,], device=device, dtype=torch.float)
tensor = torch.tensor([tensor], device=device, dtype=torch.float)
elif isinstance(tensor, str):
tensor_to_str = True
max_length = self._get_max_length(tensor, device)
Expand Down Expand Up @@ -281,8 +281,7 @@ def barrier(self) -> None:


class _SerialModel(ComputationModel):
"""Private class defines non-distributed computation model for code compatibility with other distributed models.
"""
"""Private class defines non-distributed computation model for code compatibility with other distributed models."""

name = "serial"
available_backends = ()
Expand Down
6 changes: 2 additions & 4 deletions ignite/distributed/comp_models/horovod.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,7 @@
HOROVOD = "horovod"

class _HorovodDistModel(ComputationModel):
"""Private class for `Horovod <https://horovod.readthedocs.io/en/stable/>`_ distributed computation model.
"""
"""Private class for `Horovod <https://horovod.readthedocs.io/en/stable/>`_ distributed computation model."""

name = "horovod-dist"

Expand Down Expand Up @@ -60,8 +59,7 @@ def create_from_backend(backend: str = HOROVOD, **kwargs: Any) -> "_HorovodDistM
return _HorovodDistModel(backend, **kwargs)

def __init__(self, backend: Optional[str] = None, **kwargs: Any) -> None:
"""This is a private method. Please, use `create_from_backend` or `create_from_context`
"""
"""This is a private method. Please, use `create_from_backend` or `create_from_context`"""
super(_HorovodDistModel, self).__init__()
if backend is not None:
self._create_from_backend(backend, **kwargs)
Expand Down
8 changes: 3 additions & 5 deletions ignite/distributed/comp_models/native.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,7 @@ def __init__(
rank: Optional[int] = None,
**kwargs: Any,
) -> None:
"""This is a private method. Please, use `create_from_backend` or `create_from_context`
"""
"""This is a private method. Please, use `create_from_backend` or `create_from_context`"""
super(_NativeDistModel, self).__init__()
self._env_backup = None # type: Optional[Dict[str, str]]
self._local_rank = None # type: Optional[int]
Expand Down Expand Up @@ -177,7 +176,7 @@ def _compute_node_and_local_ranks(rank: int, hostnames: List[Tuple[str, ...]]) -
from collections import Counter

c = Counter(hostnames) # type: Counter
sizes = torch.tensor([0,] + list(c.values()))
sizes = torch.tensor([0] + list(c.values()))
cumsum_sizes = torch.cumsum(sizes, dim=0)
node_rank = (rank // cumsum_sizes[1:]).clamp(0, 1).sum().item()
local_rank = rank - cumsum_sizes[node_rank].item()
Expand Down Expand Up @@ -503,8 +502,7 @@ def _expand_hostlist(nodelist: str) -> List[str]:
return result_hostlist

def _setup_ddp_vars_from_slurm_env(environ: Dict[str, str]) -> Dict[str, Union[str, int]]:
"""Method to setup DDP env vars required by PyTorch from SLURM env
"""
"""Method to setup DDP env vars required by PyTorch from SLURM env"""
# 1) Tools like enroot can have hooks to translate slurm env vars to RANK, LOCAL_RANK, WORLD_SIZE etc
# See https://github.com/NVIDIA/enroot/blob/v3.1.0/conf/hooks/extra/50-slurm-pytorch.sh
# 2) User can use torch.distributed.launch tool to schedule on N local GPUs using 1 node, 1 task by SLURM
Expand Down
11 changes: 5 additions & 6 deletions ignite/distributed/comp_models/xla.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,7 @@ def create_from_backend(backend: str = XLA_TPU, **kwargs: Any) -> "_XlaDistModel
return _XlaDistModel(backend=backend, **kwargs)

def __init__(self, backend: Optional[str] = None, **kwargs: Any):
"""This is a private method. Please, use `create_from_backend` or `create_from_context`
"""
"""This is a private method. Please, use `create_from_backend` or `create_from_context`"""
super(_XlaDistModel, self).__init__()
if backend is not None:
self._create_from_backend(backend, **kwargs)
Expand All @@ -65,7 +64,7 @@ def _init_from_context(self) -> None:

def _compute_nproc_per_node(self) -> int:
tensor = torch.tensor([self.get_local_rank() + 1.0], dtype=torch.float).to(self.device())
xm.all_reduce("max", [tensor,])
xm.all_reduce("max", [tensor])
return int(tensor.item())

def get_local_rank(self) -> int:
Expand Down Expand Up @@ -142,22 +141,22 @@ def _do_all_reduce(self, tensor: torch.Tensor, op: str = "SUM") -> torch.Tensor:
if op not in self._reduce_op_map:
raise ValueError(f"Unsupported reduction operation: '{op}'")
op = self._reduce_op_map[op]
xm.all_reduce(op, [tensor,])
xm.all_reduce(op, [tensor])
return tensor

def _do_all_gather(self, tensor: torch.Tensor) -> torch.Tensor:
# from https://github.com/jysohn23/xla/blob/model-parallel-colab/Gather_Scatter_Broadcast_PyTorch_XLA.ipynb
group_size = self.get_world_size()
output = torch.zeros((group_size,) + tensor.shape, dtype=tensor.dtype, device=tensor.device)
output[self.get_rank() % group_size] = tensor
xm.all_reduce("sum", [output,])
xm.all_reduce("sum", [output])
return output.reshape(-1, *output.shape[2:])

def _do_broadcast(self, tensor: torch.Tensor, src: int) -> torch.Tensor:
# from https://github.com/jysohn23/xla/blob/model-parallel-colab/Gather_Scatter_Broadcast_PyTorch_XLA.ipynb
if src != self.get_rank():
tensor.fill_(0.0)
xm.all_reduce("sum", [tensor,])
xm.all_reduce("sum", [tensor])
return tensor

def barrier(self) -> None:
Expand Down
4 changes: 1 addition & 3 deletions ignite/distributed/launcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -327,9 +327,7 @@ def __enter__(self) -> "Parallel":
f"Initialized distributed launcher with backend: '{self.backend}'"
)
msg = "\n\t".join([f"{k}: {v}" for k, v in self._spawn_params.items() if v is not None])
self._logger.info( # type: ignore[attr-defined]
f"- Parameters to spawn processes: \n\t{msg}"
)
self._logger.info(f"- Parameters to spawn processes: \n\t{msg}") # type: ignore[attr-defined]

return self

Expand Down
19 changes: 7 additions & 12 deletions ignite/distributed/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,26 +133,24 @@ def model_name() -> str:


def get_world_size() -> int:
"""Returns world size of current distributed configuration. Returns 1 if no distributed configuration.
"""
"""Returns world size of current distributed configuration. Returns 1 if no distributed configuration."""
if _need_to_sync and isinstance(_model, _SerialModel):
sync(temporary=True)

return _model.get_world_size()


def get_rank() -> int:
"""Returns process rank within current distributed configuration. Returns 0 if no distributed configuration.
"""
"""Returns process rank within current distributed configuration. Returns 0 if no distributed configuration."""
if _need_to_sync and isinstance(_model, _SerialModel):
sync(temporary=True)

return _model.get_rank()


def get_local_rank() -> int:
"""Returns local process rank within current distributed configuration. Returns 0 if no distributed configuration.
"""
"""Returns local process rank within current distributed configuration.
Returns 0 if no distributed configuration."""
if _need_to_sync and isinstance(_model, _SerialModel):
sync(temporary=True)

Expand Down Expand Up @@ -190,8 +188,7 @@ def get_node_rank() -> int:


def hostname() -> str:
"""Returns host name for current process within current distributed configuration.
"""
"""Returns host name for current process within current distributed configuration."""
return socket.gethostname()


Expand Down Expand Up @@ -422,8 +419,7 @@ def broadcast(


def barrier() -> None:
"""Helper method to synchronize all processes.
"""
"""Helper method to synchronize all processes."""
if _need_to_sync and isinstance(_model, _SerialModel):
sync(temporary=True)

Expand Down Expand Up @@ -543,8 +539,7 @@ def finalize() -> None:


def show_config() -> None:
"""Helper method to display distributed configuration via ``logging``.
"""
"""Helper method to display distributed configuration via ``logging``."""

# setup parallel logger
logger = setup_logger(__name__)
Expand Down
4 changes: 1 addition & 3 deletions ignite/engine/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,7 @@
def _prepare_batch(
batch: Sequence[torch.Tensor], device: Optional[Union[str, torch.device]] = None, non_blocking: bool = False
) -> Tuple[Union[torch.Tensor, Sequence, Mapping, str, bytes], ...]:
"""Prepare batch for training: pass to a device with options.

"""
"""Prepare batch for training: pass to a device with options."""
x, y = batch
return (
convert_tensor(x, device=device, non_blocking=non_blocking),
Expand Down
8 changes: 4 additions & 4 deletions ignite/engine/engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -446,14 +446,14 @@ def fire_event(self, event_name: Any) -> None:
return self._fire_event(event_name)

def terminate(self) -> None:
"""Sends terminate signal to the engine, so that it terminates completely the run after the current iteration.
"""
"""Sends terminate signal to the engine, so that it terminates completely the run after
the current iteration."""
self.logger.info("Terminate signaled. Engine will stop after current iteration is finished.")
self.should_terminate = True

def terminate_epoch(self) -> None:
"""Sends terminate signal to the engine, so that it terminates the current epoch after the current iteration.
"""
"""Sends terminate signal to the engine, so that it terminates the current epoch
after the current iteration."""
self.logger.info(
"Terminate current epoch is signaled. "
"Current epoch iteration will stop after current iteration is finished."
Expand Down
2 changes: 1 addition & 1 deletion ignite/handlers/checkpoint.py
Original file line number Diff line number Diff line change
Expand Up @@ -451,7 +451,7 @@ def _setup_checkpoint(self) -> Dict[str, Dict[Any, Any]]:

@staticmethod
def setup_filename_pattern(
with_prefix: bool = True, with_score: bool = True, with_score_name: bool = True, with_global_step: bool = True,
with_prefix: bool = True, with_score: bool = True, with_score_name: bool = True, with_global_step: bool = True
) -> str:
"""Helper method to get the default filename pattern for a checkpoint.

Expand Down
2 changes: 1 addition & 1 deletion ignite/handlers/lr_finder.py
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ def plot(
]
for lr in sug_lr:
ax.scatter(
lr, corresponding_loss, color="red" if len(sug_lr) == 1 else None, s=75, marker="o", zorder=3,
lr, corresponding_loss, color="red" if len(sug_lr) == 1 else None, s=75, marker="o", zorder=3
)

# handle skip_end=0 properly
Expand Down
10 changes: 3 additions & 7 deletions ignite/handlers/param_scheduler.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,7 @@ class BaseParamScheduler(metaclass=ABCMeta):

"""

def __init__(
self, param_name: str, save_history: bool = False,
):
def __init__(self, param_name: str, save_history: bool = False):
self.param_name = param_name
self.event_index = 0
self._save_history = save_history
Expand Down Expand Up @@ -497,8 +495,7 @@ class CosineAnnealingScheduler(CyclicalScheduler):
"""

def get_param(self) -> float:
"""Method to get current optimizer's parameter value
"""
"""Method to get current optimizer's parameter value"""
cycle_progress = self.event_index / self.cycle_size
return self.start_value + ((self.end_value - self.start_value) / 2) * (1 - math.cos(math.pi * cycle_progress))

Expand Down Expand Up @@ -782,8 +779,7 @@ def __call__(self, engine: Optional[Engine], name: Optional[str] = None) -> None
super(LRScheduler, self).__call__(engine, name)

def get_param(self) -> Union[float, List[float]]:
"""Method to get current optimizer's parameter value
"""
"""Method to get current optimizer's parameter value"""
# Emulate context manager for pytorch>=1.4
self.lr_scheduler._get_lr_called_within_step = True # type: ignore[attr-defined]
lr_list = cast(List[float], self.lr_scheduler.get_lr())
Expand Down
2 changes: 1 addition & 1 deletion ignite/handlers/state_param_scheduler.py
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ class ExpStateScheduler(StateParamScheduler):
"""

def __init__(
self, initial_value: float, gamma: float, param_name: str, save_history: bool = False, create_new: bool = False,
self, initial_value: float, gamma: float, param_name: str, save_history: bool = False, create_new: bool = False
):
super(ExpStateScheduler, self).__init__(param_name, save_history, create_new)
self.initial_value = initial_value
Expand Down
8 changes: 4 additions & 4 deletions ignite/handlers/time_profilers.py
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ def get_results(self) -> Dict[str, Dict[str, Any]]:
[
("processing_stats", self._compute_basic_stats(self.processing_times)),
("dataflow_stats", self._compute_basic_stats(self.dataflow_times)),
("event_handlers_stats", event_handlers_stats,),
("event_handlers_stats", event_handlers_stats),
(
"event_handlers_names",
{str(e.name).replace(".", "_") + "_names": v for e, v in self.event_handlers_names.items()},
Expand Down Expand Up @@ -601,7 +601,7 @@ def get_results(self) -> List[List[Union[str, float]]]:
for h in self.event_handlers_times[e]
]
)
total_eh_time = round(float(total_eh_time), 5,)
total_eh_time = round(float(total_eh_time), 5)

def compute_basic_stats(
times: Union[Sequence, torch.Tensor]
Expand Down Expand Up @@ -681,9 +681,9 @@ def write_results(self, output_path: str) -> None:
# pad all tensors to have same length
cols = [torch.nn.functional.pad(x, pad=(0, max_len - x.numel()), mode="constant", value=0) for x in cols]

results_dump = torch.stack(cols, dim=1,).numpy()
results_dump = torch.stack(cols, dim=1).numpy()

results_df = pd.DataFrame(data=results_dump, columns=headers,)
results_df = pd.DataFrame(data=results_dump, columns=headers)
results_df.to_csv(output_path, index=False)

@staticmethod
Expand Down
4 changes: 2 additions & 2 deletions ignite/handlers/timing.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@


class Timer:
""" Timer object can be used to measure (average) time between events.
"""Timer object can be used to measure (average) time between events.

Args:
average: if True, then when ``.value()`` method is called, the returned value
Expand Down Expand Up @@ -96,7 +96,7 @@ def attach(
resume: Optional[Events] = None,
step: Optional[Events] = None,
) -> "Timer":
""" Register callbacks to control the timer.
"""Register callbacks to control the timer.

Args:
engine: Engine that this timer will be attached to.
Expand Down
8 changes: 4 additions & 4 deletions ignite/metrics/classification_report.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,15 +106,15 @@ def ClassificationReport(
"""

# setup all the underlying metrics
precision = Precision(average=False, is_multilabel=is_multilabel, output_transform=output_transform, device=device,)
recall = Recall(average=False, is_multilabel=is_multilabel, output_transform=output_transform, device=device,)
precision = Precision(average=False, is_multilabel=is_multilabel, output_transform=output_transform, device=device)
recall = Recall(average=False, is_multilabel=is_multilabel, output_transform=output_transform, device=device)
fbeta = Fbeta(beta, average=False, precision=precision, recall=recall)
averaged_precision = precision.mean()
averaged_recall = recall.mean()
averaged_fbeta = fbeta.mean()

def _wrapper(
recall_metric: Metric, precision_metric: Metric, f: Metric, a_recall: Metric, a_precision: Metric, a_f: Metric,
recall_metric: Metric, precision_metric: Metric, f: Metric, a_recall: Metric, a_precision: Metric, a_f: Metric
) -> Union[Collection[str], Dict]:
p_tensor, r_tensor, f_tensor = precision_metric, recall_metric, f
if p_tensor.shape != r_tensor.shape:
Expand All @@ -141,4 +141,4 @@ def _wrapper(
def _get_label_for_class(idx: int) -> str:
return labels[idx] if labels else str(idx)

return MetricsLambda(_wrapper, recall, precision, fbeta, averaged_recall, averaged_precision, averaged_fbeta,)
return MetricsLambda(_wrapper, recall, precision, fbeta, averaged_recall, averaged_precision, averaged_fbeta)
Loading