class_docstr: Importing two different types of horovod in the same python process (horovod.tensorflow and
  horovod.pytorch, for instance) results in a segfault.
  
  _PolyHorovod is a wrapper around the horovod module to delay the actual importing of horovod
  until it is known which version is actually needed for the task. The result is that horovod
  importing across Determined becomes simple, easy, and robust.
  
  After require_horovod_type() is called once, horovod is imported, and _PolyHorovod passes all
  other calls to the real horovod module.
docstr: Declare the required type of horovod and give a unique reason as to why it is required.
  
  The reason makes for clear error reporting if require_horovod_type() is called a second
  time but with a different type.
docstr_tok: ["Declare","the","required","type","of","horovod","and","give","a","unique","reason","as","to","why","it","is","required",".","The","reason","makes","for","clear","error","reporting","if","require_horovod_type","(",")","is","called","a","second","time","but","with","a","different","type","."]
code: def require_horovod_type(
      self, horovod_type: str, reason: str
  ) -> None:
      """
      Declare the required type of horovod and give a unique reason as to why it is required.
  
      The reason makes for clear error reporting if require_horovod_type() is called a second
      time but with a different type.
      """
  
      known_types = {"tensorflow", "tensorflow.keras", "torch"}
      check.is_in(
          horovod_type, known_types, "Unknown horovod type requested."
      )
  
      if self._poly_hvd_type is not None:
          check.eq(
              horovod_type,
              self._poly_hvd_type,
              f"require_horovod_type() called with with type {horovod_type} after a previous "
              f"call with type {self._poly_hvd_type} in the same process. The reason for the "
              f"first call was '{self._poly_hvd_first_reason}'; the reason for this call is "
              f"'{reason}'.",
          )
      else:
          self._poly_hvd_type = horovod_type
          self._poly_hvd_first_reason = reason
          # If horovod has not been imported yet, do it now.
          try:
              self._poly_hvd_module = importlib.import_module(
                  f"horovod.{horovod_type}"
              )
          except ImportError:  # pragma: no cover
              pass
  
file_path: determined/harness/determined/horovod.py
imports: import importlib
  import os
  from typing import Any, Dict, List, Optional
  from determined import constants
  from determined.common import check
label_desc: Use image node_id 2 for calling the _PolyHorovod obj's underlying member method code with example usage: obj.require_horovod_type(horovod_type, reason) without return types