class_docstr: VecEnv that runs multiple environments in parallel in subproceses and communicates with them via pipes.
  Recommended to use when num_envs > 1 and step() can be a bottleneck.
class_docstr_tok: ["VecEnv","that","runs","multiple","environments","in","parallel","in","subproceses","and","communicates","with","them","via","pipes",".","Recommended","to","use","when","num_envs",">","1","and","step","(",")","can","be","a","bottleneck","."]
docstr: Arguments:
  
  env_fns: iterable of callables -  functions that create environments to run in subprocesses. Need to be cloud-pickleable
  in_series: number of environments to run in series in a single process
  (e.g. when len(env_fns) == 12 and in_series == 3, it will run 4 processes, each running 3 envs in series)
docstr_tok: ["Arguments",":","env_fns",":","iterable","of","callables","-","functions","that","create","environments","to","run","in","subprocesses",".","Need","to","be","cloud-pickleable","in_series",":","number","of","environments","to","run","in","series","in","a","single","process","(","e.g",".","when","len","(","env_fns",")","==","12","and","in_series","==","3",",","it","will","run","4","processes",",","each","running","3","envs","in","series",")"]
code: def __init__(
      self, env_fns, spaces=None, context="spawn", in_series=1
  ):
      """
      Arguments:
  
      env_fns: iterable of callables -  functions that create environments to run in subprocesses. Need to be cloud-pickleable
      in_series: number of environments to run in series in a single process
      (e.g. when len(env_fns) == 12 and in_series == 3, it will run 4 processes, each running 3 envs in series)
      """
      self.waiting = False
      self.closed = False
      self.in_series = in_series
      nenvs = len(env_fns)
      assert (
          nenvs % in_series == 0
      ), "Number of envs must be divisible by number of envs to run in series"
      self.nremotes = nenvs // in_series
      env_fns = np.array_split(env_fns, self.nremotes)
      ctx = mp.get_context(context)
      self.remotes, self.work_remotes = zip(
          *[ctx.Pipe() for _ in range(self.nremotes)]
      )
      self.ps = [
          ctx.Process(
              target=worker,
              args=(work_remote, remote, CloudpickleWrapper(env_fn)),
          )
          for (work_remote, remote, env_fn) in zip(
              self.work_remotes, self.remotes, env_fns
          )
      ]
      for p in self.ps:
          p.daemon = True  # if the main process crashes, we should not cause things to hang
          with clear_mpi_env_vars():
              p.start()
      for remote in self.work_remotes:
          remote.close()
  
      self.remotes[0].send(("get_spaces_spec", None))
      observation_space, action_space, self.spec = (
          self.remotes[0].recv().x
      )
      self.viewer = None
      VecEnv.__init__(self, nenvs, observation_space, action_space)
  
file_path: baselines/baselines/common/vec_env/subproc_vec_env.py
imports: import multiprocessing
  import numpy
  from .vec_env import VecEnv, CloudpickleWrapper, clear_mpi_env_vars
label_desc: Use image node_id 1 to create a new SubprocVecEnv object from inherited base classes: VecEnv with example: obj = SubprocVecEnv(env_fns, spaces, context, in_series)