class_docstr: Subclass of argparse ArgumentParser which adds optional calls to sample from lists or ranges
  Also enables running optimizations across parallel processes
class_docstr_tok: ["Subclass","of","argparse","ArgumentParser","which","adds","optional","calls","to","sample","from","lists","or","ranges","Also","enables","running","optimizations","across","parallel","processes"]
docstr: Runs optimization across gpus with cuda drivers
  :param train_function:
  :param nb_trials:
  :param gpu_ids: List of strings like: ['0', '1, 3']
  :param nb_workers:
  :return:
docstr_tok: ["Runs","optimization","across","gpus","with","cuda","drivers",":","param","train_function",":",":","param","nb_trials",":",":","param","gpu_ids",":","List","of","strings","like",":","[","'","0","'",",","'","1",",","3","'","]",":","param","nb_workers",":",":","return",":"]
code: def optimize_trials_parallel_gpu(
      self,
      train_function,
      nb_trials,
      trials,
      gpu_ids,
      nb_workers=4,
  ):
      """
      Runs optimization across gpus with cuda drivers
      :param train_function:
      :param nb_trials:
      :param gpu_ids: List of strings like: ['0', '1, 3']
      :param nb_workers:
      :return:
      """
      self.trials = trials
      self.trials = [(x, train_function) for x in self.trials]
  
      # build q of gpu ids so we can use them in each process
      # this is thread safe so each process can pull out a gpu id, run its task and put it back when done
      if self.pool is None:
          gpu_q = Queue()
          for gpu_id in gpu_ids:
              gpu_q.put(gpu_id)
  
          # called by the Pool when a process starts
          def init(local_gpu_q):
              global g_gpu_id_q
              g_gpu_id_q = local_gpu_q
  
          # init a pool with the nb of worker threads we want
          self.pool = Pool(
              processes=nb_workers, initializer=init, initargs=(gpu_q,)
          )
  
      # apply parallelization
      results = self.pool.map(
          optimize_parallel_gpu_private, self.trials
      )
      return results
  
imports: import argparse
  import json
  import math
  import os
  import random
  import re
  import traceback
  from argparse import ArgumentParser
  from copy import deepcopy
  from gettext import gettext
  from multiprocessing import Pool, Queue
  from time import sleep
  import numpy
  from .hyper_opt_utils import strategies
label_desc: Use image node_id 16 for calling the HyperOptArgumentParser obj's underlying member method code with example usage: obj.optimize_trials_parallel_gpu(train_function, nb_trials, trials, gpu_ids, nb_workers) and returns: results