Communicator.inc.hpp 4.34 KB
Newer Older
Praetorius, Simon's avatar
Praetorius, Simon committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
#pragma once

#if HAVE_MPI

namespace AMDiS { namespace Mpi {

// send mpi datatype
template <class Data>
void Communicator::send(Data const& data, int to, int tag) const
{
  MPI_Send(to_void_ptr(&data), 1, type_to_mpi<Data>(), to, tag, comm_);
}


// send array of mpi datatypes
template <class Data>
void Communicator::send(Data const* data, std::size_t size, int to, int tag) const
{
  MPI_Send(to_void_ptr(data), int(size), type_to_mpi<Data>(), to, tag, comm_);
}


template <class T>
void Communicator::send(std::vector<T> const& vec, int to, int tag) const
{
  MPI_Send(to_void_ptr(vec.data()), int(vec.size()), type_to_mpi<T>(), to, tag, comm_);
}


// -------------------------------------------------------------------------------------


// send mpi datatype (non-blocking)
template <class Data>
Request Communicator::isend(Data const& data, int to, int tag) const
{
  MPI_Request request;
  MPI_Isend(to_void_ptr(&data), 1, type_to_mpi<Data>(), to, tag, comm_, &request);
  return {request};
}


// send mpi datatype (non-blocking, buffered)
template <class Data>
Request Communicator::ibsend(Data const& data, int to, int tag) const
{
  MPI_Request request;
  MPI_Ibsend(to_void_ptr(&data), 1, type_to_mpi<Data>(), to, tag, comm_, &request);
  return {request};
}


// send array of mpi datatypes (non-blocking)
template <class Data>
Request Communicator::isend(Data const* data, std::size_t size, int to, int tag) const
{
  MPI_Request request;
  MPI_Isend(to_void_ptr(data), size, type_to_mpi<Data>(), to, tag, comm_, &request);
  return {request};
}


// send array of mpi datatypes (non-blocking, buffered)
template <class Data>
Request Communicator::ibsend(Data const* data, std::size_t size, int to, int tag) const
{
  MPI_Request request;
  MPI_Ibsend(to_void_ptr(data), size, type_to_mpi<Data>(), to, tag, comm_, &request);
  return {request};
}


template <class T>
Request Communicator::isend(std::vector<T> const& vec, int to, int tag) const
{
  MPI_Request request;
  MPI_Isend(to_void_ptr(vec.data()), int(vec.size()), type_to_mpi<T>(), to, tag, comm_, &request);
  return {request};
}

// -------------------------------------------------------------------------------------

// receive mpi datatype
template <class Data>
MPI_Status Communicator::recv(Data& data, int from, int tag) const
{
  MPI_Status status;
  MPI_Recv(&data, 1, type_to_mpi<Data>(), from, tag, comm_, &status);
  return status;
}


// receive array of mpi datatypes
template <class Data>
MPI_Status Communicator::recv(Data* data, std::size_t size, int from, int tag) const
{
  MPI_Status status;
  MPI_Recv(data, size, type_to_mpi<Data>(), from, tag, comm_, &status);
  return status;
}


// receive array of mpi datatypes
template <class T>
MPI_Status Communicator::recv(std::vector<T>& vec, int from, int tag) const
{
  MPI_Status status;
  MPI_Probe(from, tag, comm_, &status);

  int size = 0;
  MPI_Get_count(&status, type_to_mpi<T>(), &size);
  int min_size = std::max(size,1);

  vec.resize(min_size);
  MPI_Recv(vec.data(), min_size, type_to_mpi<T>(), from, tag, comm_, MPI_STATUS_IGNORE);
  if (size != min_size)
    vec.resize(size);
  return status;
}


// -------------------------------------------------------------------------------------

// receive mpi datatype
template <class Data>
Request Communicator::irecv(Data& data, int from, int tag) const
{
  MPI_Request request;
  MPI_Irecv(&data, 1, type_to_mpi<Data>(), from, tag, comm_, &request);
  return {request};
}


// receive array of mpi datatypes
template <class Data>
Request Communicator::irecv(Data* data, std::size_t size, int from, int tag) const
{
  MPI_Request request;
  MPI_Irecv(data, size, type_to_mpi<Data>(), from, tag, comm_, &request);
  return {request};
}


template <class T>
Request Communicator::irecv(std::vector<T>& vec, int from, int tag) const
{
  return Request{ RecvDynamicSize(from,tag,comm_,
    [comm=comm_,&vec](MPI_Status status) -> MPI_Request
    {
      int size = 0;
      MPI_Get_count(&status, type_to_mpi<T>(), &size);
      int min_size = std::max(size,1);

      vec.resize(min_size);
      MPI_Request req;
      MPI_Irecv(vec.data(), min_size, type_to_mpi<T>(), status.MPI_SOURCE, status.MPI_TAG, comm, &req);
      return req;
    },
    [&vec](MPI_Status status)
    {
      int size = 0;
      MPI_Get_count(&status, type_to_mpi<T>(), &size);
      vec.resize(size);
    }) };
}

}} // end namespace AMDiS::Mpi

#endif // HAVE_MPI