class_docstr: History for use in training using multiple processes
  
  When using skorch with :class:`.AccelerateMixin` for multi GPU training, use
  this class instead of the default :class:`.History` class.
  
  When using PyTorch :class:`torch.nn.parallel.DistributedDataParallel`, the
  whole training process is forked and batches are processed in parallel. That
  means that the standard :class:`.History` does not see all the batches that
  are being processed, which results in the different processes having
  histories that are out of sync. This is bad because the history is used as a
  reference to influence the training, e.g. to control early stopping.
  
  This class solves the problem by using a distributed store from PyTorch,
  e.g. :class:`torch.distributed.TCPStore`, to synchronize the batch
  information across processes. This ensures that the information stored in
  the individual history copies is identical for ``history[:, 'batches']``.
  When it comes to the epoch-level information, it can still diverge between
  processes (e.g. the recorded duration of the epoch).
  
  To use this class, instantiate it and pass it as the ``history`` argument to
  the net.
  
  Click here for more information on `PyTorch distributed key-value stores
  <https://pytorch.org/docs/stable/distributed.html#distributed-key-value-store>`_.
  
  Notes
  -----
  If using this class results in the processes hanging or timing out, double
  check that the ``rank`` and ``world_size`` arguments are set correctly.
  Otherwise, the history instances will be waiting for records that are
  actually never written.
  
  If the speed of the processes is very uneven, there can also be timeouts. To
  increase the waiting time, pass a corresponding ``timeout`` argument to the
  ``store`` instance.
  
  Objects stored with this history make a json roundtrip. Therefore, if you
  store objects that don't survive a json roundtrip (say, numpy arrays), don't
  use this class.
  
  The PyTorch ``Store`` classes cannot be pickled. Therefore, if a net using
  this history class is pickled, the ``store`` attribute is discarded so that
  the pickling does not fail. This means, however, that an unpickled net
  cannot be used for further training without manually setting the ``store``
  attribute on the ``history``.
  
  Examples
  --------
  >>> # general
  >>> from skorch import NeuralNetClassifier
  >>> from torch.distributed import TCPStore
  >>> from torch.nn.parallel import DistributedDataParallel
  >>> def train(rank, world_size, is_master):
  ...     store = TCPStore(
  ...         "127.0.0.1", port=1234, world_size=world_size)
  ...     dist_history = DistributedHistory(
  ...         store=store, rank=rank, world_size=world_size)
  ...     net = NeuralNetClassifier(..., history=dist_history)
  ...     net.fit(X, y)
  >>> # with accelerate
  >>> from accelerate import Accelerator
  >>> from skorch.hf import AccelerateMixin
  >>> accelerator = Accelerator(...)
  >>> def train(accelerator):
  ...     is_master = accelerator.is_main_process
  ...     world_size = accelerator.num_processes
  ...     rank = accelerator.local_process_index
  ...     store = TCPStore(
  ...         "127.0.0.1", port=1234, world_size=world_size, is_master=is_master)
  ...     dist_history = DistributedHistory(
  ...         store=store, rank=rank, world_size=world_size)
  ...     net = AcceleratedNet(..., history=dist_history)
  ...     net.fit(X, y)
  
  Parameters
  ----------
  store : torch.distributed.Store
    The torch distributed ``Store`` instance,
    :class:`torch.distributed.TCPStore` has been tested to work.
  
  rank : int
    The rank of this particular process among all processes. Each process
    should have a unique rank between 0 and ``world_size`` - 1. If using
    ``accelerate``, the rank can be determined as
    ``accelerator.local_process_index``.
  
  world_size : int
    The number of processes in the training. When using ``accelerate``, the
    world size can be determined as ``accelerator.num_processes``.
  
  Attributes
  ----------
  history : skorch.history.History
    The actual skorch ``History`` object can be accessed using the
    :class:`.History` attribute. You should call ``net.history.sync()`` to
    ensure that all data is synced into the history before reading from it.
code: def new_epoch(self):
      self.sync()
      self._history.new_epoch()
      self._cur_batch = 0
  
imports: import json
  import pickle
  from skorch.utils import open_file_like
label_desc: Use image node_id 9 for calling the DistributedHistory obj's underlying member method code with example usage: obj.new_epoch() without return types