docstr: Start the Optimizer controller function loop()
  If the calling process is stopped, the controller will stop as well.
  
  .. important::
      This function returns only after optimization is completed or :meth:`stop` was called.
docstr_tok: ["Start","the","Optimizer","controller","function","loop","(",")","If","the","calling","process","is","stopped",",","the","controller","will","stop","as","well",".","..","important",":",":","This","function","returns","only","after","optimization","is","completed","or",":","meth",":","`","stop","`","was","called","."]
code: def start(self):
      # type: () -> ()
      """
      Start the Optimizer controller function loop()
      If the calling process is stopped, the controller will stop as well.
  
      .. important::
          This function returns only after optimization is completed or :meth:`stop` was called.
  
      """
      # Step 1: Start a NameServer
      fake_run_id = "OptimizerBOHB_{}".format(time())
      # default port is 9090, we must have one, this is how BOHB workers communicate (even locally)
      self._namespace = hpns.NameServer(
          run_id=fake_run_id,
          host="127.0.0.1",
          port=self._nameserver_port,
      )
      self._namespace.start()
  
      # we have to scale the budget to the iterations per job, otherwise numbers might be too high
      budget_iteration_scale = self._max_iteration_per_job
  
      # Step 2: Start the workers
      workers = []
      for i in range(self._num_concurrent_workers):
          w = _TrainsBandsterWorker(
              optimizer=self,
              sleep_interval=int(self.pool_period_minutes * 60),
              budget_iteration_scale=budget_iteration_scale,
              base_task_id=self._base_task_id,
              objective=self._objective_metric.objectives[0],
              queue_name=self._execution_queue,
              nameserver="127.0.0.1",
              nameserver_port=self._nameserver_port,
              run_id=fake_run_id,
              id=i,
          )
          w.run(background=True)
          workers.append(w)
  
      # Step 3: Run an optimizer
      self._bohb = BOHB(
          configspace=self._convert_hyper_parameters_to_cs(),
          run_id=fake_run_id,
          # num_samples=self.total_max_jobs, # will be set by self._bohb_kwargs
          min_budget=float(self._min_iteration_per_job)
          / float(self._max_iteration_per_job),
          **self._bohb_kwargs,
      )
      # scale the budget according to the successive halving iterations
      if self.budget.jobs.limit:
          self.budget.jobs.limit *= len(self._bohb.budgets)
      if self.budget.iterations.limit:
          self.budget.iterations.limit *= len(self._bohb.budgets)
      # start optimization
      self._res = self._bohb.run(
          n_iterations=self.total_max_jobs,
          min_n_workers=self._num_concurrent_workers,
      )
  
      # Step 4: if we get here, Shutdown
      self.stop()
  
file_path: clearml/clearml/automation/hpbandster/bandster.py
imports: from time import sleep, time
  from typing import Any, Optional, Sequence
  from ..optimization import Objective, SearchStrategy
  from ..parameters import DiscreteParameterRange, UniformParameterRange, RandomSeed, UniformIntegerParameterRange, Parameter
  from ...task import Task
label_desc: Use image node_id 3 for calling the OptimizerBOHB obj's underlying member method code with example usage: obj.start() without return types