class_docstr: Class for clusters following a master-worker architecture.
  
  Usually you want to inherit from this class and do not want to use it directly. It is recommended to treat this
  class as an abstract class or an interface.
  
  Examples:
      Create a cluster with all `Runtimes` detected by the `RuntimeManager`.
  
      ```python
      from lazycluster import RuntimeManager
      cluster = MyMasterWorkerClusterImpl(RuntimeManager().create_group())
      cluster.start()
      ```
  
      Use different strategies for launching the master and the worker instance as the default ones by providing
      custom implementation of `MasterLauncher` and `WorkerLauncher`.
  
      ```python
      cluster = MyMasterWorkerClusterImpl(RuntimeManager().create_group(),
                                          MyMasterLauncherImpl(),
                                          MyWorkerLauncherImpl()
      cluster.start()
      ```
class_docstr_tok: ["Class","for","clusters","following","a","master-worker","architecture",".","Usually","you","want","to","inherit","from","this","class","and","do","not","want","to","use","it","directly",".","It","is","recommended","to","treat","this","class","as","an","abstract","class","or","an","interface",".","Examples",":","Create","a","cluster","with","all","`","Runtimes","`","detected","by","the","`","RuntimeManager","`",".","``","`","python","from","lazycluster","import","RuntimeManager","cluster","=","MyMasterWorkerClusterImpl","(","RuntimeManager","(",")",".create_group","(",")",")","cluster.start","(",")","``","`","Use","different","strategies","for","launching","the","master","and","the","worker","instance","as","the","default","ones","by","providing","custom","implementation","of","`","MasterLauncher","`","and","`","WorkerLauncher","`",".","``","`","python","cluster","=","MyMasterWorkerClusterImpl","(","RuntimeManager","(",")",".create_group","(",")",",","MyMasterLauncherImpl","(",")",",","MyWorkerLauncherImpl","(",")","cluster.start","(",")","``","`"]
docstr: Start the worker instances.
  
  Note:
      How workers are actually started is determined by the the actual `WorkerLauncher` implementation. Another
      implementation adhering to the `WorkerLauncher` interface can be provided in the constructor of the cluster
      class.
  
  Args:
      count: The number of worker instances to be started in the cluster. Defaults to the number of runtimes in
             the cluster.
      debug: If `True`, stdout/stderr from the runtime will be printed to stdout of localhost. If, `False` then
             the stdout/stderr will be added to python logger with level debug after each `RuntimeTask` step. Defaults to
             `False`.
  
  Raises:
      NoPortsLeftError: If there are no free ports left in the port list for instantiating new worker entities.
docstr_tok: ["Start","the","worker","instances",".","Note",":","How","workers","are","actually","started","is","determined","by","the","the","actual","`","WorkerLauncher","`","implementation",".","Another","implementation","adhering","to","the","`","WorkerLauncher","`","interface","can","be","provided","in","the","constructor","of","the","cluster","class",".","Args",":","count",":","The","number","of","worker","instances","to","be","started","in","the","cluster",".","Defaults","to","the","number","of","runtimes","in","the","cluster",".","debug",":","If","`","True","`",",","stdout\/stderr","from","the","runtime","will","be","printed","to","stdout","of","localhost",".","If",",","`","False","`","then","the","stdout\/stderr","will","be","added","to","python","logger","with","level","debug","after","each","`","RuntimeTask","`","step",".","Defaults","to","`","False","`",".","Raises",":","NoPortsLeftError",":","If","there","are","no","free","ports","left","in","the","port","list","for","instantiating","new","worker","entities","."]
code: def start_workers(
      self, count: Optional[int] = None, debug: bool = False
  ) -> None:
      """Start the worker instances.
  
      Note:
          How workers are actually started is determined by the the actual `WorkerLauncher` implementation. Another
          implementation adhering to the `WorkerLauncher` interface can be provided in the constructor of the cluster
          class.
  
      Args:
          count: The number of worker instances to be started in the cluster. Defaults to the number of runtimes in
                 the cluster.
          debug: If `True`, stdout/stderr from the runtime will be printed to stdout of localhost. If, `False` then
                 the stdout/stderr will be added to python logger with level debug after each `RuntimeTask` step. Defaults to
                 `False`.
  
      Raises:
          NoPortsLeftError: If there are no free ports left in the port list for instantiating new worker entities.
      """
  
      if not self._worker_launcher:
          raise LazyclusterError("Worker launcher does not exist")
  
      if not count:
          count = self._group.runtime_count
  
      assert self.master_port
  
      self._ports = self._worker_launcher.start(
          count, self.master_port, self._ports, debug
      )
  
      # Some attributes must be set in the given MasterLauncher implementation after
      # starting the master to ensure correct behavior of MasterWorkerCluster
      # => indicates a wrong implementation of the given launcher class
      # e.g. for DASK -> assert self._worker_launcher.ports_per_host
  
      self.log.info("Worker instances started.")
  
imports: import atexit
  import logging
  from subprocess import Popen
  from typing import Dict, List, Optional, Union
  from lazycluster.exceptions import LazyclusterError
  from lazycluster.runtime_mgmt import RuntimeGroup
label_desc: Use image node_id 7 for calling the MasterWorkerCluster obj's underlying member method code with example usage: obj.start_workers(count, debug) without return types