dune-common  2.11
mpipack.hh
Go to the documentation of this file.
1 // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 // vi: set et ts=4 sw=2 sts=2:
3 // SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root
4 // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception
20 #ifndef DUNE_COMMON_PARALLEL_MPIPACK_HH
21 #define DUNE_COMMON_PARALLEL_MPIPACK_HH
22 
23 #if HAVE_MPI
24 
25 #include <type_traits>
26 #include <vector>
27 
28 #include <mpi.h>
29 
32 
33 
34 namespace Dune {
35 
36  class MPIPack {
37  std::vector<char> _buffer;
38  int _position;
39  MPI_Comm _comm;
40 
41  friend struct MPIData<MPIPack>;
42  friend struct MPIData<const MPIPack>;
43  public:
44  MPIPack(Communication<MPI_Comm> comm, std::size_t size = 0)
45  : _buffer(size)
46  , _position(0)
47  , _comm(comm)
48  {}
49 
50  // Its not valid to copy a MPIPack but you can move it
51  MPIPack(const MPIPack&) = delete;
52  MPIPack& operator = (const MPIPack& other) = delete;
53  MPIPack(MPIPack&&) = default;
54  MPIPack& operator = (MPIPack&& other) = default;
55 
61  template<class T>
62  void pack(const T& data){
63  auto mpidata = getMPIData(data);
64  int size = getPackSize(mpidata.size(), _comm, mpidata.type());
65  constexpr bool has_static_size = decltype(getMPIData(std::declval<T&>()))::static_size;
66  if(!has_static_size)
67  size += getPackSize(1, _comm, MPI_INT);
68  if (_position + size > 0 && size_t(_position + size) > _buffer.size()) // resize buffer if necessary
69  _buffer.resize(_position + size);
70  if(!has_static_size){
71  int size = mpidata.size();
72  MPI_Pack(&size, 1, MPI_INT, _buffer.data(), _buffer.size(),
73  &_position, _comm);
74  }
75  MPI_Pack(mpidata.ptr(), mpidata.size(),
76  mpidata.type(), _buffer.data(), _buffer.size(),
77  &_position, _comm);
78  }
79 
84  template<class T>
85  auto /*void*/ unpack(T& data)
86  -> std::enable_if_t<decltype(getMPIData(data))::static_size, void>
87  {
88  auto mpidata = getMPIData(data);
89  MPI_Unpack(_buffer.data(), _buffer.size(), &_position,
90  mpidata.ptr(), mpidata.size(),
91  mpidata.type(), _comm);
92  }
93 
98  template<class T>
99  auto /*void*/ unpack(T& data)
100  -> std::enable_if_t<!decltype(getMPIData(data))::static_size, void>
101  {
102  auto mpidata = getMPIData(data);
103  int size = 0;
104  MPI_Unpack(_buffer.data(), _buffer.size(), &_position,
105  &size, 1,
106  MPI_INT, _comm);
107  mpidata.resize(size);
108  MPI_Unpack(_buffer.data(), _buffer.size(), &_position,
109  mpidata.ptr(), mpidata.size(),
110  mpidata.type(), _comm);
111  }
112 
113 
115  template<typename T>
116  friend MPIPack& operator << (MPIPack& p, const T& t){
117  p.pack(t);
118  return p;
119  }
120 
122  template<typename T>
123  friend MPIPack& operator >> (MPIPack& p, T& t){
124  p.unpack(t);
125  return p;
126  }
127 
129  template<typename T>
130  MPIPack& read(T& t){
131  unpack(t);
132  return *this;
133  }
134 
136  template<typename T>
137  MPIPack& write(const T& t){
138  pack(t);
139  return *this;
140  }
141 
145  void resize(size_t size){
146  _buffer.resize(size);
147  }
148 
151  void enlarge(int s) {
152  _buffer.resize(_buffer.size() + s);
153  }
154 
157  size_t size() const {
158  return _buffer.size();
159  }
160 
164  void seek(int p){
165  _position = p;
166  }
167 
171  int tell() const{
172  return _position;
173  }
174 
177  bool eof() const{
178  return std::size_t(_position)==_buffer.size();
179  }
180 
184  static int getPackSize(int len, const MPI_Comm& comm, const MPI_Datatype& dt){
185  int size;
186  MPI_Pack_size(len, dt, comm, &size);
187  return size;
188  }
189 
190  friend bool operator==(const MPIPack& a, const MPIPack& b) {
191  return a._buffer == b._buffer && a._comm == b._comm;
192  }
193  friend bool operator!=(const MPIPack& a, const MPIPack& b) {
194  return !(a==b);
195  }
196 
197  };
198 
199  template<class P>
200  struct MPIData<P, std::enable_if_t<std::is_same<std::remove_const_t<P>, MPIPack>::value>> {
201  protected:
202  friend auto getMPIData<P>(P& t);
203  MPIData(P& t) :
204  data_(t)
205  {}
206  public:
207  static constexpr bool static_size = std::is_const<P>::value;
208 
209  void* ptr() {
210  return (void*) data_._buffer.data();
211  }
212 
213  int size() {
214  return data_.size();
215  }
216 
217  MPI_Datatype type() const{
218  return MPI_PACKED;
219  }
220 
221  void resize(int size){
222  data_.resize(size);
223  }
224  protected:
225  P& data_;
226  };
227 
228 } // end namespace Dune
229 
230 #endif // HAVE_MPI
231 #endif // DUNE_COMMON_PARALLEL_MPIPACK_HH
friend bool operator==(const MPIPack &a, const MPIPack &b)
Definition: mpipack.hh:190
auto getMPIData(T &t)
Definition: mpidata.hh:44
Implements an utility class that provides MPI&#39;s collective communication methods. ...
int tell() const
Gets the position in the buffer where the next pack/unpack operation should take place.
Definition: mpipack.hh:171
T & data_
Definition: mpidata.hh:54
MPIPack(Communication< MPI_Comm > comm, std::size_t size=0)
Definition: mpipack.hh:44
void pack(const T &data)
Packs the data into the object. Enlarges the internal buffer if necessary.
Definition: mpipack.hh:62
Interface class to translate objects to a MPI_Datatype, void* and size used for MPI calls...
Definition: mpidata.hh:41
friend bool operator!=(const MPIPack &a, const MPIPack &b)
Definition: mpipack.hh:193
static constexpr bool static_size
Definition: mpidata.hh:66
MPIPack & read(T &t)
Unpacks data from the object.
Definition: mpipack.hh:130
Dune namespace
Definition: alignedallocator.hh:12
size_t size() const
Returns the size of the internal buffer.
Definition: mpipack.hh:157
auto unpack(T &data) -> std::enable_if_t< decltype(getMPIData(data))::static_size, void >
Unpacks data from the object.
Definition: mpipack.hh:85
void seek(int p)
Sets the position in the buffer where the next pack/unpack operation should take place.
Definition: mpipack.hh:164
int size() const
Definition: mpidata.hh:68
Specialization of Communication for MPI.
Definition: mpicommunication.hh:107
void enlarge(int s)
Enlarges the internal buffer.
Definition: mpipack.hh:151
friend MPIPack & operator>>(MPIPack &p, T &t)
Unpacks data from the object.
Definition: mpipack.hh:123
MPIPack & operator=(const MPIPack &other)=delete
auto unpack(T &data) -> std::enable_if_t<!decltype(getMPIData(data))::static_size, void >
Unpacks data from the object.
Definition: mpipack.hh:99
bool eof() const
Checks whether the end of the buffer is reached.
Definition: mpipack.hh:177
friend MPIPack & operator<<(MPIPack &p, const T &t)
Packs the data into the object. Enlarges the internal buffer if necessary.
Definition: mpipack.hh:116
static int getPackSize(int len, const MPI_Comm &comm, const MPI_Datatype &dt)
Returns the size of the data needed to store the data in an MPIPack. See MPI_Pack_size.
Definition: mpipack.hh:184
STL namespace.
MPIPack & write(const T &t)
Packs the data into the object. Enlarges the internal buffer if necessary.
Definition: mpipack.hh:137
void resize(size_t size)
Resizes the internal buffer.
Definition: mpipack.hh:145
Definition: mpipack.hh:36