class_docstr: A wrapper object that turns a `DistributedExplainer` into a remote actor. This allows running multiple distributed
  explainers in parallel.
class_docstr_tok: ["A","wrapper","object","that","turns","a","`","DistributedExplainer","`","into","a","remote","actor",".","This","allows","running","multiple","distributed","explainers","in","parallel","."]
docstr: Initialises a list of *distinct* distributed explainers which can explain the same batch in parallel. It
  generalizes the `DistributedExplainer`, which contains replicas of one explainer object, speeding up the task
  of explaining batches of instances.
  
  Parameters
  ----------
  distributed_opts , explainer_type, explainer_init_args, explainer_init_kwargs
      See :py:meth:`alibi.utils.distributed.DistributedExplainer` constructor documentation for explanations. 
      Each entry in the list is a different explainer configuration (e.g., CEM in PN vs PP mode, different 
      background dataset sizes for SHAP, etc).
  **kwargs
      Any other kwargs, passed to the `DistributedExplainer` objects.
  
  Raises
  ------
  ResourceError
      If the number of CPUs specified by the user is smaller than the number of distributed explainers.
  ValueError
      If the number of entries in the explainers args/kwargs list differ.
code: def __init__(
      self,
      distributed_opts: Dict[str, Any],
      explainer_type: Any,
      explainer_init_args: List[Tuple],
      explainer_init_kwargs: List[Dict],
      **kwargs,
  ):
      """
      Initialises a list of *distinct* distributed explainers which can explain the same batch in parallel. It
      generalizes the `DistributedExplainer`, which contains replicas of one explainer object, speeding up the task
      of explaining batches of instances.
  
      Parameters
      ----------
      distributed_opts , explainer_type, explainer_init_args, explainer_init_kwargs
          See :py:meth:`alibi.utils.distributed.DistributedExplainer` constructor documentation for explanations.
          Each entry in the list is a different explainer configuration (e.g., CEM in PN vs PP mode, different
          background dataset sizes for SHAP, etc).
      **kwargs
          Any other kwargs, passed to the `DistributedExplainer` objects.
  
      Raises
      ------
      ResourceError
          If the number of CPUs specified by the user is smaller than the number of distributed explainers.
      ValueError
          If the number of entries in the explainers args/kwargs list differ.
      """  # noqa W605
  
      available_cpus = distributed_opts["n_cpus"]
      if len(explainer_init_args) != len(explainer_init_kwargs):
          raise ValueError(
              "To run multiple explainers over distinct parallel pools of replicas, the lists of args and kwargs"
              "should be of equal length."
          )
      cpus_per_pool = available_cpus // len(explainer_init_args)
      if cpus_per_pool < 1:
          raise ResourceError(
              f"Running {explainer_type.__name__} requires {len(explainer_init_args)} CPU but only {available_cpus} "
              f"were specified. Please allocate more cpus to run this explainer in distributed mode"
          )
      # we can allow users to experiment with CPU fractions if only 1 CPU available per pool
      actor_cpu_fraction = distributed_opts.get(
          "actor_cpu_fraction", 1.0
      )
      if cpus_per_pool == 1:
          if actor_cpu_fraction is not None:
              cpus_per_pool /= actor_cpu_fraction
  
      if not ray.is_initialized():
          logger.info(
              f"Initialising ray on {distributed_opts['n_cpus']} CPUs"
          )
          ray.init(num_cpus=distributed_opts["n_cpus"])
  
      opts = copy.deepcopy(distributed_opts)
      opts.update(n_cpus=int(cpus_per_pool))
      self.distributed_explainers = self.create_explainer_handles(
          opts,
          explainer_type,
          explainer_init_args,
          explainer_init_kwargs,
          **kwargs,
      )
  
      self._remote_explainer_index = 0
  
imports: import copy
  import logging
  from functools import partial
  from typing import Any, Callable, Dict, Generator, List, Optional, Tuple, Union
  import numpy
  from scipy import sparse
  import ray
label_desc: Use image node_id 1 to create a new PoolCollection object  with example: obj = PoolCollection(distributed_opts, explainer_type, explainer_init_args, explainer_init_kwargs)