Run fn(*args) in a single process or spawn n_procs distributed workers. fn and args must be picklable (top-level functions, dataclasses, etc.) because mp.spawn serializes them across processes. Do not pass lambdas. If the process was launched by torchrun (RANK env var is set), skips
(fn: Callable, n_procs: int, *args)
| 33 | |
| 34 | |
| 35 | def run_maybe_distributed(fn: Callable, n_procs: int, *args) -> None: |
| 36 | """Run fn(*args) in a single process or spawn n_procs distributed workers. |
| 37 | |
| 38 | fn and args must be picklable (top-level functions, dataclasses, etc.) |
| 39 | because mp.spawn serializes them across processes. Do not pass lambdas. |
| 40 | |
| 41 | If the process was launched by torchrun (RANK env var is set), skips |
| 42 | mp.spawn and uses the torchrun-provided environment directly. |
| 43 | """ |
| 44 | if _is_torchrun(): |
| 45 | _torchrun_worker(fn, args) |
| 46 | elif n_procs > 1: |
| 47 | print(f"Running {fn.__name__} with {n_procs} processes") |
| 48 | |
| 49 | mp.spawn( |
| 50 | _distributed_worker, |
| 51 | args=(n_procs, _find_free_port(), fn, args), |
| 52 | nprocs=n_procs, |
| 53 | join=True, |
| 54 | ) |
| 55 | else: |
| 56 | print(f"Running {fn.__name__} single-process") |
| 57 | fn(*args) |
| 58 | |
| 59 | |
| 60 | def _is_torchrun() -> bool: |