class_docstr: Launches processes that run a given function in parallel, and joins them all at the end.
  
  The main process in which this launcher is invoked creates N so-called worker processes (using
  :func:`torch.multiprocessing.start_processes`) that run the given function.
  Worker processes have a rank that ranges from 0 to N - 1.
  
  Note:
      - This launcher requires all objects to be pickleable.
      - It is important that the entry point to the program/script is guarded by ``if __name__ == "__main__"``.
      - With start method 'fork' the user must ensure that no CUDA context gets created in the main process before
        the launcher is invoked. E.g., one should avoid creating cuda tensors or calling ``torch.cuda.*`` functions
        before calling ``Trainer.fit``.
  
  Args:
      strategy: A reference to the strategy that is used together with this launcher.
      start_method: The method how to start the processes.
          - 'spawn': The default start method. Requires all objects to be pickleable.
          - 'fork': Preferable for IPython/Jupyter environments where 'spawn' is not available. Not available on
            the Windows platform for example.
          - 'forkserver': Alternative implementation to 'fork'.
docstr: Launches processes that run the given function in parallel.
  
  The function is allowed to have a return value. However, when all processes join, only the return value
  of worker process 0 gets returned from this `launch` method in the main process.
  
  Arguments:
      function: The entry point for all launched processes.
      *args: Optional positional arguments to be passed to the given function.
      trainer: Optional reference to the :class:`~lightning.pytorch.trainer.trainer.Trainer` for which
          a selected set of attributes get restored in the main process after processes join.
      **kwargs: Optional keyword arguments to be passed to the given function.
docstr_tok: ["Launches","processes","that","run","the","given","function","in","parallel",".","The","function","is","allowed","to","have","a","return","value",".","However",",","when","all","processes","join",",","only","the","return","value","of","worker","process","0","gets","returned","from","this","`","launch","`","method","in","the","main","process",".","Arguments",":","function",":","The","entry","point","for","all","launched","processes",".","*","args",":","Optional","positional","arguments","to","be","passed","to","the","given","function",".","trainer",":","Optional","reference","to","the",":","class",":","`","~lightning.pytorch.trainer.trainer.Trainer","`","for","which","a","selected","set","of","attributes","get","restored","in","the","main","process","after","processes","join",".","*","*","kwargs",":","Optional","keyword","arguments","to","be","passed","to","the","given","function","."]
code: def launch(
      self,
      function: Callable,
      *args: Any,
      trainer: Optional["pl.Trainer"] = None,
      **kwargs: Any,
  ) -> Any:
      """Launches processes that run the given function in parallel.
  
      The function is allowed to have a return value. However, when all processes join, only the return value
      of worker process 0 gets returned from this `launch` method in the main process.
  
      Arguments:
          function: The entry point for all launched processes.
          *args: Optional positional arguments to be passed to the given function.
          trainer: Optional reference to the :class:`~lightning.pytorch.trainer.trainer.Trainer` for which
              a selected set of attributes get restored in the main process after processes join.
          **kwargs: Optional keyword arguments to be passed to the given function.
  
      """
      if self._start_method in ("fork", "forkserver"):
          _check_bad_cuda_fork()
      if self._start_method == "spawn":
          _check_missing_main_guard()
      if (
          self._already_fit
          and trainer is not None
          and trainer.state.fn == TrainerFn.FITTING
      ):
          # resolving https://github.com/Lightning-AI/lightning/issues/18775 will lift this restriction
          raise NotImplementedError(
              "Calling `trainer.fit()` twice on the same Trainer instance using a spawn-based strategy is not"
              " supported. You can work around this limitation by creating a new Trainer instance and passing the"
              " `fit(ckpt_path=...)` argument."
          )
  
      # The default cluster environment in Lightning chooses a random free port number
      # This needs to be done in the main process here before starting processes to ensure each rank will connect
      # through the same port
      assert self._strategy.cluster_environment is not None
      os.environ["MASTER_PORT"] = str(
          self._strategy.cluster_environment.main_port
      )
  
      context = mp.get_context(self._start_method)
      return_queue = context.SimpleQueue()
  
      if self._start_method == "spawn":
          global_states = _GlobalStateSnapshot.capture()
          process_args = [
              trainer,
              function,
              args,
              kwargs,
              return_queue,
              global_states,
          ]
      else:
          process_args = [trainer, function, args, kwargs, return_queue]
  
      process_context = mp.start_processes(
          self._wrapping_function,
          args=process_args,
          nprocs=self._strategy.num_processes,
          start_method=self._start_method,
          join=False,  # we will join ourselves to get the process references
      )
      self.procs = process_context.processes
      while not process_context.join():
          pass
  
      worker_output = return_queue.get()
      if trainer is None:
          return worker_output
  
      self._already_fit |= trainer.state.fn == TrainerFn.FITTING
      self._recover_results_in_main_process(worker_output, trainer)
      return worker_output.trainer_results
  
imports: import logging
  import os
  import queue
  import tempfile
  from contextlib import suppress
  from dataclasses import dataclass
  from typing import Any, Callable, Dict, List, Literal, NamedTuple, Optional, Union
  import numpy
  import torch
  import torch.backends.cudnn
  import torch.multiprocessing
  from lightning_utilities.core.apply_func import apply_to_collection
  from torch import Tensor
  from typing_extensions import override
  import lightning.pytorch
  from lightning.fabric.strategies.launchers.multiprocessing import _check_bad_cuda_fork, _check_missing_main_guard, _disable_module_memory_sharing
  from lightning.fabric.utilities import move_data_to_device
  from lightning.fabric.utilities.distributed import _set_num_threads_if_needed
  from lightning.fabric.utilities.seed import _collect_rng_states, _set_rng_states
  from lightning.fabric.utilities.types import _PATH
  from lightning.pytorch.accelerators import CPUAccelerator
  from lightning.pytorch.strategies.launchers.launcher import _Launcher
  from lightning.pytorch.trainer.connectors.signal_connector import _SIGNUM
  from lightning.pytorch.trainer.states import TrainerFn, TrainerState
  from lightning.pytorch.utilities.rank_zero import rank_zero_debug
label_desc: Use image node_id 3 for calling the _MultiProcessingLauncher obj's underlying member method code with example usage: obj.launch(function) and returns: worker_output, worker_output