opm-simulators
mpibuffer.hh
Go to the documentation of this file.
1 // -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 // vi: set et ts=4 sw=4 sts=4:
3 /*
4  This file is part of the Open Porous Media project (OPM).
5 
6  OPM is free software: you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 2 of the License, or
9  (at your option) any later version.
10 
11  OPM is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with OPM. If not, see <http://www.gnu.org/licenses/>.
18 
19  Consult the COPYING file in the top-level source directory of this
20  module for the precise wording of the license and the list of
21  copyright holders.
22 */
27 #ifndef EWOMS_MPI_BUFFER_HH
28 #define EWOMS_MPI_BUFFER_HH
29 
30 #if HAVE_MPI
31 #include <mpi.h>
32 #include <type_traits>
33 #endif
34 
35 #include <cassert>
36 #include <cstddef>
37 #include <vector>
38 
39 namespace Opm {
40 
44 template <class DataType>
45 class MpiBuffer
46 {
47 public:
48  MpiBuffer()
49  {
50  setMpiDataType_();
51  updateMpiDataSize_();
52  }
53 
54  explicit MpiBuffer(std::size_t size)
55  {
56  data_.resize(size);
57 
58  setMpiDataType_();
59  updateMpiDataSize_();
60  }
61 
65  void resize(std::size_t newSize)
66  {
67  data_.resize(newSize);
68  updateMpiDataSize_();
69  }
70 
74  void send([[maybe_unused]] unsigned peerRank)
75  {
76 #if HAVE_MPI
77  MPI_Isend(data_.data(),
78  static_cast<int>(mpiDataSize_),
79  mpiDataType_,
80  static_cast<int>(peerRank),
81  0, // tag
82  MPI_COMM_WORLD,
83  &mpiRequest_);
84 #endif
85  }
86 
90  void wait()
91  {
92 #if HAVE_MPI
93  MPI_Wait(&mpiRequest_, &mpiStatus_);
94 #endif // HAVE_MPI
95  }
96 
100  void receive([[maybe_unused]] unsigned peerRank)
101  {
102 #if HAVE_MPI
103  MPI_Recv(data_.data(),
104  static_cast<int>(mpiDataSize_),
105  mpiDataType_,
106  static_cast<int>(peerRank),
107  0, // tag
108  MPI_COMM_WORLD,
109  MPI_STATUS_IGNORE);
110 #endif // HAVE_MPI
111  }
112 
113 #if HAVE_MPI
114 
119  MPI_Request& request()
120  { return mpiRequest_; }
121 
127  const MPI_Request& request() const
128  { return mpiRequest_; }
129 
135  MPI_Status& status()
136  { return mpiStatus_; }
137 
143  const MPI_Status& status() const
144  { return mpiStatus_; }
145 #endif // HAVE_MPI
146 
150  std::size_t size() const
151  { return data_.size(); }
152 
156  DataType& operator[](std::size_t i)
157  {
158  assert(i < data_.size());
159  return data_[i];
160  }
161 
165  const DataType& operator[](std::size_t i) const
166  {
167  assert(i < data_.size());
168  return data_[i];
169  }
170 
171 private:
172  void setMpiDataType_()
173  {
174 #if HAVE_MPI
175  // set the MPI data type
176  if constexpr (std::is_same_v<DataType, char>) {
177  mpiDataType_ = MPI_CHAR;
178  }
179  else if constexpr (std::is_same_v<DataType, unsigned char>) {
180  mpiDataType_ = MPI_UNSIGNED_CHAR;
181  }
182  else if constexpr (std::is_same_v<DataType, short>) {
183  mpiDataType_ = MPI_SHORT;
184  }
185  else if constexpr (std::is_same_v<DataType, unsigned short>) {
186  mpiDataType_ = MPI_UNSIGNED_SHORT;
187  }
188  else if constexpr (std::is_same_v<DataType, int>) {
189  mpiDataType_ = MPI_INT;
190  }
191  else if constexpr (std::is_same_v<DataType, unsigned>) {
192  mpiDataType_ = MPI_UNSIGNED;
193  }
194  else if constexpr (std::is_same_v<DataType, long>) {
195  mpiDataType_ = MPI_LONG;
196  }
197  else if constexpr (std::is_same_v<DataType, unsigned long>) {
198  mpiDataType_ = MPI_UNSIGNED_LONG;
199  }
200  else if constexpr (std::is_same_v<DataType, long long>) {
201  mpiDataType_ = MPI_LONG_LONG;
202  }
203  else if constexpr (std::is_same_v<DataType, unsigned long long>) {
204  mpiDataType_ = MPI_UNSIGNED_LONG_LONG;
205  }
206  else if constexpr (std::is_same_v<DataType, float>) {
207  mpiDataType_ = MPI_FLOAT;
208  }
209  else if constexpr (std::is_same_v<DataType, double>) {
210  mpiDataType_ = MPI_DOUBLE;
211  }
212  else if constexpr (std::is_same_v<DataType, long double>) {
213  mpiDataType_ = MPI_LONG_DOUBLE;
214  }
215  else {
216  mpiDataType_ = MPI_BYTE;
217  }
218 #endif // HAVE_MPI
219  }
220 
221  void updateMpiDataSize_()
222  {
223 #if HAVE_MPI
224  mpiDataSize_ = data_.size();
225  if (mpiDataType_ == MPI_BYTE) {
226  mpiDataSize_ *= sizeof(DataType);
227  }
228 #endif // HAVE_MPI
229  }
230 
231  std::vector<DataType> data_;
232 
233 #if HAVE_MPI
234  std::size_t mpiDataSize_;
235  MPI_Datatype mpiDataType_;
236  MPI_Request mpiRequest_;
237  MPI_Status mpiStatus_;
238 #endif // HAVE_MPI
239 };
240 
241 } // namespace Opm
242 
243 #endif
DataType & operator[](std::size_t i)
Provide access to the buffer data.
Definition: mpibuffer.hh:156
void resize(std::size_t newSize)
Set the size of the buffer.
Definition: mpibuffer.hh:65
Simplifies handling of buffers to be used in conjunction with MPI.
Definition: mpibuffer.hh:45
const DataType & operator[](std::size_t i) const
Provide access to the buffer data.
Definition: mpibuffer.hh:165
void wait()
Wait until the buffer was send to the peer completely.
Definition: mpibuffer.hh:90
void receive([[maybe_unused]] unsigned peerRank)
Receive the buffer syncronously from a peer rank.
Definition: mpibuffer.hh:100
This file contains a set of helper functions used by VFPProd / VFPInj.
Definition: blackoilbioeffectsmodules.hh:45
void send([[maybe_unused]] unsigned peerRank)
Send the buffer asyncronously to a peer process.
Definition: mpibuffer.hh:74
std::size_t size() const
Returns the number of data objects in the buffer.
Definition: mpibuffer.hh:150