Validate a separator model across multiple GPUs with a unified API. Runs validation either in Distributed Data Parallel (DDP) mode—detected via `torch.distributed.is_initialized()`—or, if DDP is not active, via multi-processing / single-GPU execution using the provided `device
(
model: torch.nn.Module,
args,
config: ConfigDict,
device_ids: Optional[List[int]] = None,
verbose: bool = False
)
| 694 | |
| 695 | |
| 696 | def valid_multi_gpu( |
| 697 | model: torch.nn.Module, |
| 698 | args, |
| 699 | config: ConfigDict, |
| 700 | device_ids: Optional[List[int]] = None, |
| 701 | verbose: bool = False |
| 702 | ) -> Tuple[Dict[str, float], Dict]: |
| 703 | """ |
| 704 | Validate a separator model across multiple GPUs with a unified API. |
| 705 | |
| 706 | Runs validation either in Distributed Data Parallel (DDP) mode—detected via |
| 707 | `torch.distributed.is_initialized()`—or, if DDP is not active, via |
| 708 | multi-processing / single-GPU execution using the provided `device_ids`. |
| 709 | Collects per-track metrics, aggregates them into per-instrument/per-metric |
| 710 | arrays, and computes per-metric averages. |
| 711 | |
| 712 | Behavior: |
| 713 | * DDP mode: splits the dataset across ranks and gathers metrics; only rank 0 |
| 714 | returns results, while other ranks return `(None, None)`. |
| 715 | * Non-DDP: launches parallel workers when `len(device_ids) > 1`, otherwise |
| 716 | runs on a single device/CPU. |
| 717 | |
| 718 | Args: |
| 719 | model (torch.nn.Module): Trained model to evaluate. |
| 720 | args: Runtime arguments (e.g., metrics list, store dir). |
| 721 | config (ConfigDict): Configuration with inference/training settings. |
| 722 | device_ids (Optional[List[int]]): GPU device IDs for non-DDP parallelism. |
| 723 | If None or length is 1, runs on a single device. |
| 724 | verbose (bool, optional): If True, print progress/logs. Defaults to False. |
| 725 | |
| 726 | Returns: |
| 727 | Tuple[Dict[str, float], Dict]: A pair `(metric_avg, all_metrics)` where |
| 728 | - `metric_avg` maps metric name to its average score, |
| 729 | - `all_metrics` is a nested dict `{metric: {instrument: List[float]}}`. |
| 730 | In DDP mode, non-zero ranks return `(None, None)`. |
| 731 | """ |
| 732 | |
| 733 | start_time = time.time() |
| 734 | |
| 735 | inference = getattr(config, "inference", None) |
| 736 | if inference is None and isinstance(config, dict): |
| 737 | inference = config.get("inference", {}) |
| 738 | extension = getattr(inference, "extension", None) |
| 739 | if extension is None: |
| 740 | if isinstance(inference, dict): |
| 741 | extension = inference.get("extension", getattr(args, "extension", "wav")) |
| 742 | else: |
| 743 | extension = getattr(args, "extension", "wav") |
| 744 | |
| 745 | all_mixtures_path = get_mixture_paths(args, verbose, config, extension) |
| 746 | |
| 747 | ddp_mode = dist.is_initialized() |
| 748 | |
| 749 | if ddp_mode: |
| 750 | rank = dist.get_rank() |
| 751 | world_size = dist.get_world_size() |
| 752 | |
| 753 | device = torch.device(f"cuda:{rank}") |
no test coverage detected