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 scatter communication.
  
  This method tries to invoke scatter communication within the
  communicator. All processes in the communicator are expected to
  invoke ``scatter()``. This method relies on mpi4py fast communication
  optimized for numpy arrays, as well as ``send()`` and ``recv()``.
  
  If ``xs`` is tuple, each element is send to different processes.
  The length of the tuple must be the same as the communicator size.
  If ``xs`` is ``numpy.ndarrray``, it is splitted with the first
  axis and sent to different processes. For slave processes, ``xs``
  is allowed to be any value (will be ignored).
  
  If ``scatter()`` is invoked with cupy array in the root process,
  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:
      xs (tuple of numpy/cupy array): Arrays to be scattered.
      root (int): Rank of root process.
  
  Returns:
      ys (numpy/cupy array): Received arrays.
docstr_tok: ["A","primitive","of","inter-process","scatter","communication",".","This","method","tries","to","invoke","scatter","communication","within","the","communicator",".","All","processes","in","the","communicator","are","expected","to","invoke","``","scatter","(",")","``",".","This","method","relies","on","mpi4py","fast","communication","optimized","for","numpy","arrays",",","as","well","as","``","send","(",")","``","and","``","recv","(",")","``",".","If","``","xs","``","is","tuple",",","each","element","is","send","to","different","processes",".","The","length","of","the","tuple","must","be","the","same","as","the","communicator","size",".","If","``","xs","``","is","``","numpy.ndarrray","``",",","it","is","splitted","with","the","first","axis","and","sent","to","different","processes",".","For","slave","processes",",","``","xs","``","is","allowed","to","be","any","value","(","will","be","ignored",")",".","If","``","scatter","(",")","``","is","invoked","with","cupy","array","in","the","root","process",",","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",":","xs","(","tuple","of","numpy\/cupy","array",")",":","Arrays","to","be","scattered",".","root","(","int",")",":","Rank","of","root","process",".","Returns",":","ys","(","numpy\/cupy","array",")",":","Received","arrays","."]
code: def scatter(self, xs, root=0):
      """A primitive of inter-process scatter communication.
  
      This method tries to invoke scatter communication within the
      communicator. All processes in the communicator are expected to
      invoke ``scatter()``. This method relies on mpi4py fast communication
      optimized for numpy arrays, as well as ``send()`` and ``recv()``.
  
      If ``xs`` is tuple, each element is send to different processes.
      The length of the tuple must be the same as the communicator size.
      If ``xs`` is ``numpy.ndarrray``, it is splitted with the first
      axis and sent to different processes. For slave processes, ``xs``
      is allowed to be any value (will be ignored).
  
      If ``scatter()`` is invoked with cupy array in the root process,
      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:
          xs (tuple of numpy/cupy array): Arrays to be scattered.
          root (int): Rank of root process.
  
      Returns:
          ys (numpy/cupy array): Received arrays.
      """
      chainer.utils.experimental(
          "chainermn.communicators.CommunicatorBase.scatter"
      )
  
      is_master = self.mpi_comm.rank == root
  
      if is_master:
          # Type check.
          msgtype = _MessageType(xs)
          _check_dtype("scatter", msgtype)
  
          if msgtype.is_tuple:
              if len(msgtype.shapes) != self.size:
                  raise ValueError(
                      "the length of xs must be consistent "
                      "with communicator size"
                  )
  
              xp = chainer.backend.get_array_module(*xs)
              msgtype = tuple([_MessageType(x) for x in xs])
              shapes = [mty.shapes[0] for mty in msgtype]
              # concatenate([x.reshape(-1) ... ], axis=0) will fail
              xs = xp.concatenate(
                  [x.reshape(1, -1) for x in xs], axis=1
              )
  
          else:
              assert len(msgtype.shapes) == 1
  
              if msgtype.shapes[0][0] != self.mpi_comm.size:
                  raise ValueError(
                      "scatter received inconsistent number of inputs "
                      "with communicator size"
                  )
  
              xp = chainer.backend.get_array_module(xs)
              msgtype = tuple(
                  [_MessageType(xs[0]) for _ in range(self.size)]
              )
              shapes = [xs.shape[1:] for _ in range(self.size)]
  
          msgtype = self.mpi_comm.scatter(msgtype, root)
          shape = msgtype.shapes[0]
  
          # Collective communication.
          slens = [chainer.utils.size_of_shape(s) for s in shapes]
          sbuf = _memory_utility.get_device_memory_pointer(xs)
          rbuf = xp.empty(
              [chainer.utils.size_of_shape(shape)], dtype=msgtype.dtype
          )
          rtype = _get_mpi_type(msgtype)
          if xp is not numpy:
              chainer.cuda.Stream.null.synchronize()
  
          self.mpi_comm.Scatterv(
              [
                  sbuf,
                  (slens, _cnt_to_dsp(slens)),
                  _get_mpi_type(msgtype),
              ],
              _memory_utility.array_to_buffer_object(rbuf, rtype),
              root,
          )
  
          return rbuf.reshape(shape)
  
      else:  # slave processes
          msgtypes = self.mpi_comm.scatter(None, root)
          xp = msgtypes.get_array_module()
          shape = msgtypes.shapes[0]
          rbuf = xp.empty(
              [chainer.utils.size_of_shape(shape)], dtype=msgtypes.dtype
          )
          rtype = _get_mpi_type(msgtypes)
          self.mpi_comm.Scatterv(
              None,
              _memory_utility.array_to_buffer_object(rbuf, rtype),
              root,
          )
          return rbuf.reshape(shape)
  
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 18 for calling the MpiCommunicatorBase obj's underlying member method code with example usage: obj.scatter(xs, root) and returns: rbuf, rbuf