Repository: Project-MONAI/MONAI
File: monai/apps/nnunet/nnunetv2_runner.py (Python)

Code before:
        Args:
            config: configuration that should be trained. Examples: "2d", "3d_fullres", "3d_lowres".
            fold: fold of the 5-fold cross-validation. Should be an int between 0 and 4.
            gpu_id: an integer to select the device to use, or a str/tuple of device indices used for multi-GPU
                training (e.g., "0,1"). Default: 0.
        from nnunetv2.run.run_training import run_training
            kwargs: this optional parameter allows you to specify additional arguments in
                ``nnunetv2.run.run_training.run_training``. Currently supported args are
                    - trainer_class_name: name of the custom trainer class. Default: "nnUNetTrainer".
                    - plans_identifier: custom plans identifier. Default: "nnUNetPlans".
                    - pretrained_weights: path to nnU-Net checkpoint file to be used as pretrained model. Will only be
                        used when actually training. Beta. Use with caution. Default: False.
                    - use_compressed_data: True to use compressed data for training. Reading compressed data is much
                        more CPU and (potentially) RAM intensive and should only be used if you know what you are
                        doing. Default: False.
                    - export_validation_probabilities: True to save softmax predictions from final validation as npz
                        files (in addition to predicted segmentations). Needed for finding the best ensemble.
                        Default: False.
                    - continue_training: continue training from latest checkpoint. Default: False.
                    - only_run_validation: True to run the validation only. Requires training to have finished.
                        Default: False.
                    - disable_checkpointing: True to disable checkpointing. Ideal for testing things out and you
                        don't want to flood your hard drive with checkpoints. Default: False.
        """
        if isinstance(gpu_id, str):
            gpu_id = tuple(map(int, gpu_id.replace('"', "").split(",")))

        if isinstance(gpu_id, tuple):
            if len(gpu_id) > 1:
                gpu_ids_str = ""
                for _i in range(len(gpu_id)):
                    gpu_ids_str += f"{gpu_id[_i]},"
                os.environ["CUDA_VISIBLE_DEVICES"] = gpu_ids_str[:-1]
            else:
                os.environ["CUDA_VISIBLE_DEVICES"] = f"{gpu_id[0]}"
        else:
            os.environ["CUDA_VISIBLE_DEVICES"] = f"{gpu_id}"

        from nnunetv2.run.run_training import run_training

        if isinstance(gpu_id, int):
            run_training(dataset_name_or_id=self.dataset_name_or_id, configuration=config, fold=fold, **kwargs)
        else:
            run_training(
                dataset_name_or_id=self.dataset_name_or_id,
                configuration=config,
                fold=fold,
                num_gpus=len(gpu_id),
                **kwargs,
            )


Review comment (suggestion):
I think it may be safer to make `gpu_id` a list of int numbers, in case user provides some weird input with comma.
```
gpu_id = tuple([int(x) for x in gpu_id.split(",")])
```

Code after:
        self.extract_fingerprints(fpe, npfp, verify_dataset_integrity, clean, verbose)
        self.plan_experiments(pl, gpu_memory_target, preprocessor_name, overwrite_target_spacing, overwrite_plans_name)

        if not no_pp:
            self.preprocess(c, n_proc, overwrite_plans_name, verbose)

    def train_single_model(self, config: Any, fold: int, gpu_id: tuple | list | int = 0, **kwargs: Any) -> None:
        """
        Run the training on a single GPU with one specified configuration provided.
        Note: this will override the environment variable `CUDA_VISIBLE_DEVICES`.

        Args:
            config: configuration that should be trained. Examples: "2d", "3d_fullres", "3d_lowres".
            fold: fold of the 5-fold cross-validation. Should be an int between 0 and 4.
            gpu_id: an integer to select the device to use, or a tuple/list of GPU device indices used for multi-GPU
                training (e.g., (0,1)). Default: 0.
        from nnunetv2.run.run_training import run_training
            kwargs: this optional parameter allows you to specify additional arguments in
                ``nnunetv2.run.run_training.run_training``. Currently supported args are
                    - trainer_class_name: name of the custom trainer class. Default: "nnUNetTrainer".
                    - plans_identifier: custom plans identifier. Default: "nnUNetPlans".
                    - pretrained_weights: path to nnU-Net checkpoint file to be used as pretrained model. Will only be
                        used when actually training. Beta. Use with caution. Default: False.
                    - use_compressed_data: True to use compressed data for training. Reading compressed data is much
                        more CPU and (potentially) RAM intensive and should only be used if you know what you are
                        doing. Default: False.
                    - continue_training: continue training from latest checkpoint. Default: False.
                    - only_run_validation: True to run the validation only. Requires training to have finished.
                        Default: False.
                    - disable_checkpointing: True to disable checkpointing. Ideal for testing things out and you
                        don't want to flood your hard drive with checkpoints. Default: False.
        """
        if "num_gpus" in kwargs:
            kwargs.pop("num_gpus")
            logger.warning("please use gpu_id to set the GPUs to use")

        if isinstance(gpu_id, tuple) or isinstance(gpu_id, list):
            if len(gpu_id) > 1:
                gpu_ids_str = ""
                for _i in range(len(gpu_id)):
                    gpu_ids_str += f"{gpu_id[_i]},"
                os.environ["CUDA_VISIBLE_DEVICES"] = gpu_ids_str[:-1]
            else:
                os.environ["CUDA_VISIBLE_DEVICES"] = f"{gpu_id[0]}"
        else:
            os.environ["CUDA_VISIBLE_DEVICES"] = f"{gpu_id}"

        from nnunetv2.run.run_training import run_training

        if isinstance(gpu_id, int) or len(gpu_id) == 1:
            run_training(