class_docstr: Generic gossip averaging object for multi-peer communication
  
  Args:
      msg (torch.Tensor): message used to initialize recv buffer
      graph (GraphManager): Subclass of GraphManager
      device: (torch.Device) device on which to initialize recv buffer
      mixing (MixingManager): Subclass of MixingManager
      logger (logging.Logger): Module used to log results
      rank (int): Rank of the current process
      world_size (int): World size of the current process
class_docstr_tok: ["Generic","gossip","averaging","object","for","multi-peer","communication","Args",":","msg","(","torch.Tensor",")",":","message","used","to","initialize","recv","buffer","graph","(","GraphManager",")",":","Subclass","of","GraphManager","device",":","(","torch.Device",")","device","on","which","to","initialize","recv","buffer","mixing","(","MixingManager",")",":","Subclass","of","MixingManager","logger","(","logging.Logger",")",":","Module","used","to","log","results","rank","(","int",")",":","Rank","of","the","current","process","world_size","(","int",")",":","World","size","of","the","current","process"]
docstr: Initialize generic averaging class designed for multi-peer comms
docstr_tok: ["Initialize","generic","averaging","class","designed","for","multi-peer","comms"]
code: def __init__(
      self,
      msg: torch.Tensor,
      graph: GraphManager,
      device: Optional[torch.device] = None,
      mixing: MixingManager = None,
      logger: logging.Logger = None,
      rank: Optional[int] = None,
      world_size: Optional[int] = None,
  ) -> None:
      """
      Initialize generic averaging class designed for multi-peer comms
      """
  
      self.logger = logger
      if rank is None or world_size is None:
          assert dist.is_initialized()
          # for now p2p communication only supported with tcp and mpi
          assert dist.get_backend() != dist_backend.GLOO
          assert dist.get_backend() != dist_backend.NCCL
          rank = dist.get_rank()
          world_size = dist.get_world_size()
  
      # graph topology properties
      self.rank = rank
      self.world_size = world_size
      assert isinstance(graph, GraphManager)
      self._graph_manager = graph
      self.peers_per_itr_device = torch.tensor(
          [self._graph_manager.peers_per_itr],
          device=device,
          dtype=msg.dtype,
      )
      # This might need to be made float16 later on
      self.passive = self._graph_manager.is_passive()
      self.refresh_peers_(
          rotate=False
      )  # sets in- and out-peers attributes
  
      # mixing matrix
      if mixing is None:
          mixing = UniformMixing(self._graph_manager, device)
      assert isinstance(mixing, MixingManager)
      self._mixing_manager = mixing
      self.refresh_mixing_weights_()  # sets mixing-weights attribute
  
      # regular ==> we don't need to keep track of ps-weight explicitly
      self.regular = self._mixing_manager.is_regular()
  
      # msg buffers used during send/recv
      self.device = device if device is not None else msg.device
      self.out_msg_buffer: List[Tuple[dist.Work, torch.Tensor]] = []
      self.in_msg_buffer = msg.clone().detach_().to(self.device)
      self._ps_weight: torch.Tensor = (
          torch.ones(1, dtype=msg.dtype).detach_().to(self.device)
      )
      # not using regular comms ==> need to communicate ps-weight
      if not self.regular:
          self.in_msg_buffer = torch.cat(
              [self.in_msg_buffer, self.ps_weight]
          )
      if self.device.type == "cpu":
          try:
              self.in_msg_buffer = self.in_msg_buffer.pin_memory()
          except Exception as e:
              if self.logger is not None:
                  self.logger.error(e)
              else:
                  raise
  
      self.placeholder = self.in_msg_buffer.clone()
  
imports: from enum import Enum
  import logging
  from typing import Iterator, List, Optional, Tuple, cast
  import torch
  import torch.distributed
  from .graph_manager import GraphManager
  from .mixing_manager import MixingManager, UniformMixing
label_desc: Use image node_id 1 to create a new Gossiper object from inherited base classes: object with example: obj = Gossiper(msg, graph, device, mixing, logger, rank, world_size)