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 receiver.
  
  This method tries to receive numpy-array from target process.
  The target process is expected to invoke ``send()``.
  This method relies on mpi4py fast communication optimized for
  numpy arrays, which discards any information attached to
  chainer.Variable objects. Please be sure.
  
  If the corresponding ``send()`` is invoked with 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:
      source (int): Target process specifier.
      tag (int): Message ID (MPI feature).
  
  Returns:
      data (tuple of numpy/cupy array or numpy/cupy array):
          Received data. If ``send()`` is invoked with tuple data,
          it is also tuple. Otherwise, it is a vanilla numpy/cupy array.
docstr_tok: ["A","primitive","of","inter-process","receiver",".","This","method","tries","to","receive","numpy-array","from","target","process",".","The","target","process","is","expected","to","invoke","``","send","(",")","``",".","This","method","relies","on","mpi4py","fast","communication","optimized","for","numpy","arrays",",","which","discards","any","information","attached","to","chainer.Variable","objects",".","Please","be","sure",".","If","the","corresponding","``","send","(",")","``","is","invoked","with","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",":","source","(","int",")",":","Target","process","specifier",".","tag","(","int",")",":","Message","ID","(","MPI","feature",")",".","Returns",":","data","(","tuple","of","numpy\/cupy","array","or","numpy\/cupy","array",")",":","Received","data",".","If","``","send","(",")","``","is","invoked","with","tuple","data",",","it","is","also","tuple",".","Otherwise",",","it","is","a","vanilla","numpy\/cupy","array","."]
code: def recv(self, source, tag):
      """A primitive of inter-process receiver.
  
      This method tries to receive numpy-array from target process.
      The target process is expected to invoke ``send()``.
      This method relies on mpi4py fast communication optimized for
      numpy arrays, which discards any information attached to
      chainer.Variable objects. Please be sure.
  
      If the corresponding ``send()`` is invoked with 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:
          source (int): Target process specifier.
          tag (int): Message ID (MPI feature).
  
      Returns:
          data (tuple of numpy/cupy array or numpy/cupy array):
              Received data. If ``send()`` is invoked with tuple data,
              it is also tuple. Otherwise, it is a vanilla numpy/cupy array.
      """
  
      chainer.utils.experimental(
          "chainermn.communicators.MpiCommunicatorBase.recv"
      )
  
      msgtype = self.mpi_comm.recv(source=source, tag=tag)
      xp = msgtype.get_array_module()
      if numpy.float16 == msgtype.dtype:
          comm_dtype = numpy.float32
      else:
          comm_dtype = msgtype.dtype
  
      if msgtype.is_tuple:
          msg = []
          for shape in msgtype.shapes:
              buf = xp.empty(
                  [chainer.utils.size_of_shape(shape)], dtype=comm_dtype
              )
              rtype = _get_mpi_type(msgtype)
              self.mpi_comm.Recv(
                  _memory_utility.array_to_buffer_object(buf, rtype),
                  source=source,
                  tag=tag,
              )
  
              if numpy.float16 == msgtype.dtype:
                  buf = buf.astype(numpy.float16)
              msg.append(buf.reshape(shape))
          return tuple(msg)
  
      else:
          assert len(msgtype.shapes) == 1
          shape = msgtype.shapes[0]
          buf = xp.empty(
              [chainer.utils.size_of_shape(shape)], dtype=comm_dtype
          )
          rtype = _get_mpi_type(msgtype)
          self.mpi_comm.Recv(
              _memory_utility.array_to_buffer_object(buf, rtype),
              source=source,
              tag=tag,
          )
  
          if numpy.float16 == msgtype.dtype:
              buf = buf.astype(numpy.float16)
          return buf.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 13 for calling the MpiCommunicatorBase obj's underlying member method code with example usage: obj.recv(source, tag) and returns: tuple, buf