class_docstr: MpiCommunicatorBase
  
  Implementation of communicator interface defined by
  :class:`CommunicatorBase`. This communicator assumes MPI4py and
  all ChainerMN processes are invoked by ``mpirun`` (``mpiexec``)
  command. Although this lacks several important methods such as
  ``multi_node_mean_grad`` to be impelmented with speficic algorithm. See
  hierarchical communicator or pure_nccl communicator for example.
docstr: A primitive of inter-process gather communication.
  
  This method tries to invoke gather communication within the
  communicator. All processes in the communicator are expected to
  invoke ``gather()``. This method relies on mpi4py fast communication
  optimized for numpy arrays, as well as ``send()`` and ``recv()``.
  
  If ``x`` is numpy array, the received data will also be allocated
  as numpy array. Additionally, when ``x`` is cupy array, the returned
  array will be placed at current device
  (``https://docs-cupy.chainer.org/en/stable/tutorial/basic.html#current-device``)
  regardless of which device the argument is placed at remote nodes.
  
  Args:
      x (numpy/cupy array): Array to be gathered.
      root (int): Rank of root process.
  
  Returns:
      ys (tuple of numpy/cupy array):
          Received arrays. ``None`` for non-root processes.
docstr_tok: ["A","primitive","of","inter-process","gather","communication",".","This","method","tries","to","invoke","gather","communication","within","the","communicator",".","All","processes","in","the","communicator","are","expected","to","invoke","``","gather","(",")","``",".","This","method","relies","on","mpi4py","fast","communication","optimized","for","numpy","arrays",",","as","well","as","``","send","(",")","``","and","``","recv","(",")","``",".","If","``","x","``","is","numpy","array",",","the","received","data","will","also","be","allocated","as","numpy","array",".","Additionally",",","when","``","x","``","is","cupy","array",",","the","returned","array","will","be","placed","at","current","device","(","``","https",":","\/\/docs-cupy.chainer.org\/en\/stable\/tutorial\/basic.html","#","current-device","``",")","regardless","of","which","device","the","argument","is","placed","at","remote","nodes",".","Args",":","x","(","numpy\/cupy","array",")",":","Array","to","be","gathered",".","root","(","int",")",":","Rank","of","root","process",".","Returns",":","ys","(","tuple","of","numpy\/cupy","array",")",":","Received","arrays",".","``","None","``","for","non-root","processes","."]
code: def gather(self, x, root=0):
      """A primitive of inter-process gather communication.
  
      This method tries to invoke gather communication within the
      communicator. All processes in the communicator are expected to
      invoke ``gather()``. This method relies on mpi4py fast communication
      optimized for numpy arrays, as well as ``send()`` and ``recv()``.
  
      If ``x`` is numpy array, the received data will also be allocated
      as numpy array. Additionally, when ``x`` is cupy array, the returned
      array will be placed at current device
      (``https://docs-cupy.chainer.org/en/stable/tutorial/basic.html#current-device``)
      regardless of which device the argument is placed at remote nodes.
  
      Args:
          x (numpy/cupy array): Array to be gathered.
          root (int): Rank of root process.
  
      Returns:
          ys (tuple of numpy/cupy array):
              Received arrays. ``None`` for non-root processes.
      """
      chainer.utils.experimental(
          "chainermn.communicators.MpiCommunicatorBase.gather"
      )
  
      is_master = self.mpi_comm.rank == root
  
      msgtype = _MessageType(x)
      _check_dtype("gather", msgtype)
  
      msgtypes = self.mpi_comm.gather(msgtype, root)
  
      if is_master:
          _check_dtypes_are_same(msgtypes)
  
          for msgtype in msgtypes:
              if msgtype.is_tuple:
                  raise TypeError("gather cannot handle tuple data")
  
              assert len(msgtype.shapes) == 1
  
          xp = chainer.backend.get_array_module(x)
          sbuf = _memory_utility.array_to_buffer_object(
              x, _get_mpi_type(msgtype)
          )
          shapes = [mty.shapes[0] for mty in msgtypes]
          rlens = [chainer.utils.size_of_shape(s) for s in shapes]
          rbuf = xp.empty([sum(rlens)], dtype=msgtype.dtype)
  
          if xp is not numpy:
              chainer.cuda.Stream.null.synchronize()
  
          self.mpi_comm.Gatherv(
              sbuf,
              [
                  _memory_utility.get_device_memory_pointer(rbuf),
                  (rlens, _cnt_to_dsp(rlens)),
                  _get_mpi_type(msgtype),
              ],
              root,
          )
  
          ys = [
              rbuf[i : i + l].reshape(s)
              for i, l, s in zip(_cnt_to_dsp(rlens), rlens, shapes)
          ]
          return tuple(ys)
  
      else:
          sbuf = _memory_utility.array_to_buffer_object(
              x, _get_mpi_type(msgtype)
          )
          self.mpi_comm.Gatherv(sbuf, None, root)
          return None
  
imports: import mpi4py
  import numpy
  import chainer
  import chainer.backends
  import chainer.utils
  from chainer.utils import collections_abc
  from chainermn.communicators import _communication_utility
  from chainermn.communicators._communication_utility import chunked_bcast_obj
  from chainermn.communicators import _memory_utility
  from chainermn.communicators import communicator_base
  import chainerx
label_desc: Use image node_id 15 for calling the MpiCommunicatorBase obj's underlying member method code with example usage: obj.gather(x, root) and returns: tuple, None