code: def allocate_cpu(local_size):
      cpu_mt = os.getenv("BYTEPS_MULTITHREADED_CPU", "1").lower() in [
          "1",
          "true",
      ]
  
      def get_numa_info():
          """
          returns a list of list, each sub list is the cpu ids of a numa node. e.g
          [[0,1,2,3], [4,5,6,7]]
          """
          ret = []
          if os.path.exists(NUMA_PATH):
              items = os.listdir(NUMA_PATH)
              nodes = list(
                  filter(lambda str: str.startswith("node"), items)
              )
              if nodes:
                  for node in nodes:
                      items = os.listdir(os.path.join(NUMA_PATH, node))
                      cpus = [
                          re.findall("cpu\d+", cpu) for cpu in items
                      ]
                      cpus = list(filter(lambda x: x, cpus))
                      cpu_ids = [
                          int(cpu[0].split("cpu")[1]) for cpu in cpus
                      ]
                      cpu_ids = sorted(cpu_ids)
                      if cpu_mt:
                          cpu_ids = cpu_ids[: len(cpu_ids) // 2]
                      ret.append(cpu_ids)
          else:
              print("NUMA PATH %s NOT FOUND" % NUMA_PATH)
          return ret
  
      def _get_allocation(nodes, quota, cpu_num, cpu_blacklist):
          if quota < 1:
              raise ValueError("quota should be no less than 1")
          ret = []
          for node in nodes:
              if len(node) < quota:
                  continue
              split_index = []
              for i in range(1, quota):
                  if node[i] != node[i - 1] + 1:
                      split_index.append(i)
              quota_bck = quota
              last_idx = 0
              for idx in split_index:
                  ret.append(node[last_idx:idx])
                  quota -= idx - last_idx
                  last_idx = idx
              curr_alloc = node[last_idx : last_idx + quota]
              curr_alloc = [
                  item
                  for item in curr_alloc
                  if item not in cpu_blacklist
              ]
              ret.append(curr_alloc)
              if cpu_mt:
                  curr_alloc = [x + cpu_num for x in curr_alloc]
                  curr_alloc = [
                      item
                      for item in curr_alloc
                      if item not in cpu_blacklist
                  ]
                  ret.append(curr_alloc)
              for idx in sorted(range(quota_bck), reverse=True):
                  del node[idx]
              return ret
          return ret
  
      def _get_quota(nodes, local_size):
          # default quota is the number of physical cores for non-root processess
          default_quota = cpu_num // local_size
          default_quota = int(
              os.getenv("BYTEPS_NUMA_DEFAULT_QUOTA", default_quota)
          )
          while (
              default_quota >= 1
              and default_quota * local_size > cpu_num
          ):
              default_quota -= 1
  
          # root quota is the number of cpus for root processess
          # root does more work, thus using more cpus
          root_quota = cpu_num - default_quota * (local_size - 1)
          if int(os.getenv("BYTEPS_NUMA_ROOT_QUOTA", 0)):
              root_quota = int(os.getenv("BYTEPS_NUMA_ROOT_QUOTA", 0))
  
          node_size = len(nodes[0])
          if cpu_mt:
              node_size //= 2
          while root_quota >= 1 and root_quota > node_size:
              root_quota -= 1
          return [default_quota] * (local_size - 1) + [root_quota]
  
      nodes = get_numa_info()
      if not nodes:
          return None
      cpu_num = reduce(lambda x, y: (x + len(y)), nodes, 0)
      quota_list = _get_quota(nodes, local_size)
      cpu_blacklist = os.getenv("BYTEPS_CPU_BLACKLIST", "-1")
      cpu_blacklist = [int(item) for item in cpu_blacklist.split(",")]
      ret = []
      for quota in quota_list:
          while quota > 0:
              allocation = _get_allocation(
                  nodes, quota, cpu_num, cpu_blacklist
              )
              if allocation:
                  ret.append(allocation)
                  break
              else:
                  quota -= 1
  
      return ret
  
file_path: byteps/launcher/launch.py
imports: from __future__ import print_function
  import os
  import re
  import subprocess
  import threading
  import sys
  import time
  from functools import reduce
label_desc: Use image node_id 1 for calling a global function with example usage: allocate_cpu(local_size) and returns: ret, ret, ret, unknown, None, ret