code: def get_launch_command(
      master_addr: str,
      master_port: int,
      nproc_per_node: int,
      user_script: str,
      user_args: List[str],
      node_rank: int,
      num_nodes: int,
      extra_launch_args: str = None,
  ) -> str:
      """
      Generate a command for distributed training.
  
      Args:
          master_addr (str): the host of the master node
          master_port (str): the port of the master node
          nproc_per_node (str): the number of processes to launch on each node
          user_script (str): the user Python file
          user_args (str): the arguments for the user script
          node_rank (int): the unique ID for the node
          num_nodes (int): the number of nodes to execute jobs
  
      Returns:
          cmd (str): the command the start distributed training
      """
  
      def _arg_dict_to_list(arg_dict):
          ret = []
  
          for k, v in arg_dict.items():
              if v:
                  ret.append(f"--{k}={v}")
              else:
                  ret.append(f"--{k}")
          return ret
  
      if extra_launch_args:
          extra_launch_args_dict = dict()
          for arg in extra_launch_args.split(","):
              if "=" in arg:
                  k, v = arg.split("=")
                  extra_launch_args_dict[k] = v
              else:
                  extra_launch_args_dict[arg] = None
          extra_launch_args = extra_launch_args_dict
      else:
          extra_launch_args = dict()
  
      torch_version = version.parse(torch.__version__)
      assert torch_version.major >= 1
  
      if torch_version.major == 1 and torch_version.minor < 9:
          # torch distributed launch cmd with torch < 1.9
          cmd = [
              sys.executable,
              "-m",
              "torch.distributed.launch",
              f"--nproc_per_node={nproc_per_node}",
              f"--master_addr={master_addr}",
              f"--master_port={master_port}",
              f"--nnodes={num_nodes}",
              f"--node_rank={node_rank}",
          ]
      else:
          # extra launch args for torch distributed launcher with torch >= 1.9
          default_torchrun_rdzv_args = dict(
              master_addr=master_addr, master_port=master_port
          )
  
          # update rdzv arguments
          for key in default_torchrun_rdzv_args.keys():
              if key in extra_launch_args:
                  value = extra_launch_args.pop(key)
                  default_torchrun_rdzv_args[key] = value
  
          if torch_version.major == 1 and torch_version.minor == 9:
              # torch distributed launch cmd with torch == 1.9
              cmd = [
                  sys.executable,
                  "-m",
                  "torch.distributed.run",
                  f"--nproc_per_node={nproc_per_node}",
                  f"--nnodes={num_nodes}",
                  f"--node_rank={node_rank}",
              ]
          else:
              # torch distributed launch cmd with torch > 1.9
              cmd = [
                  "torchrun",
                  f"--nproc_per_node={nproc_per_node}",
                  f"--nnodes={num_nodes}",
                  f"--node_rank={node_rank}",
              ]
          cmd += _arg_dict_to_list(default_torchrun_rdzv_args)
  
      cmd += (
          _arg_dict_to_list(extra_launch_args)
          + [user_script]
          + user_args
      )
      cmd = " ".join(cmd)
      return cmd
  
file_path: ColossalAI/colossalai/cli/launcher/run.py
imports: import os
  import sys
  from typing import List
  import click
  import torch
  from packaging import version
  from colossalai.context import Config
  from .hostinfo import HostInfo, HostInfoList
  from .multinode_runner import MultiNodeRunner
label_desc: Use image node_id 3 for calling a global function with example usage: get_launch_command(master_addr, master_port, nproc_per_node, user_script, user_args, node_rank, num_nodes, extra_launch_args) and returns: cmd, ret