class_docstr: 复原了 paddle 的 launch_collective 函数，将其简化后集成到一个类里
  仅支持每个机器单卡的情况。
class_docstr_tok: ["\u590d\u539f\u4e86","paddle","\u7684","launch_collective","\u51fd\u6570\uff0c\u5c06\u5176\u7b80\u5316\u540e\u96c6\u6210\u5230\u4e00\u4e2a\u7c7b\u91cc","\u4ec5\u652f\u6301\u6bcf\u4e2a\u673a\u5668\u5355\u5361\u7684\u60c5\u51b5\u3002"]
docstr: 从 sub_trainers 中获取各个 rank 的信息，并且使用 subprocess.Popen 建立新的子进程。
docstr_tok: ["\u4ece","sub_trainers","\u4e2d\u83b7\u53d6\u5404\u4e2a","rank","\u7684\u4fe1\u606f\uff0c\u5e76\u4e14\u4f7f\u7528","subprocess.Popen","\u5efa\u7acb\u65b0\u7684\u5b50\u8fdb\u7a0b\u3002"]
code: def open_subprocess(self):
      """
      从 sub_trainers 中获取各个 rank 的信息，并且使用 subprocess.Popen 建立新的子进程。
      """
  
      if __main__.__spec__ is None:
          # Script called as `python a/b/c.py`
          # when user is using hydra find the absolute path
          path_lib = os.path.abspath
  
          # pull out the commands used to run the script and resolve the abs file path
          command = sys.argv
          try:
              full_path = path_lib(command[0])
          except Exception:
              full_path = os.path.abspath(command[0])
  
          command[0] = full_path
          # use the same python interpreter and actually running
          command = [sys.executable] + command
      else:  # Script called as `python -m a.b.c`
          command = [
              sys.executable,
              "-m",
              __main__.__spec__.name,
          ] + sys.argv[1:]
  
      current_env = copy.copy(self.global_envs)
      for idx, t in enumerate(self.sub_trainers):
          # 根据不同的 rank 设置环境变量
          proc_env = {
              # global_rank
              "PADDLE_TRAINER_ID": f"{t.rank}",
              "PADDLE_CURRENT_ENDPOINT": f"{t.endpoint}",
              # rank
              "PADDLE_RANK_IN_NODE": f"{idx}",
              "PADDLE_LOCAL_DEVICE_IDS": ",".join(
                  [str(g) for g in t.devices]
              ),
          }
  
          if len(t.devices) > 0:
              proc_env["FLAGS_selected_gpus"] = "%s" % ",".join(
                  [str(g) for g in t.devices]
              )
              proc_env["FLAGS_selected_devices"] = "%s" % ",".join(
                  [str(g) for g in t.devices]
              )
  
          current_env.update(proc_env)
  
          if (
              os.environ.get(FASTNLP_GLOBAL_SEED) is None
              and FASTNLP_GLOBAL_SEED in current_env
          ):
              del current_env[FASTNLP_GLOBAL_SEED]
  
          if idx != 0:
              # 子进程
              if os.environ.get(FASTNLP_LOG_LEVEL, None) is None:
                  current_env[FASTNLP_LOG_LEVEL] = "warning"
              proc = distributed_open_proc(
                  self.output_from_new_proc,
                  command,
                  current_env,
                  t.rank,
              )
          else:
              # 更新当前的环境变量
              os.environ.update(current_env)
  
imports: import os
  import sys
  import __main__
  import tempfile
  import copy
  from typing import List
  from fastNLP.core.drivers.utils import distributed_open_proc
  from fastNLP.envs.env import FASTNLP_DISTRIBUTED_CHECK, FASTNLP_LOG_LEVEL, FASTNLP_GLOBAL_SEED, FASTNLP_GLOBAL_RANK
  from fastNLP.core.utils import get_paddle_device_id
  from .utils import find_free_ports
label_desc: Use image node_id 4 for calling the FleetLauncher obj's underlying member method code with example usage: obj.open_subprocess() without return types