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 #endif
33 
34 #include <stddef.h>
35 
36 #include <type_traits>
37 #include <cassert>
38 
39 namespace Ewoms {
40 
44 template <class DataType>
45 class MpiBuffer
46 {
47 public:
48  MpiBuffer()
49  {
50  data_ = NULL;
51  dataSize_ = 0;
52 
53  setMpiDataType_();
54  updateMpiDataSize_();
55  }
56 
57  MpiBuffer(size_t size)
58  {
59  data_ = new DataType[size];
60  dataSize_ = size;
61 
62  setMpiDataType_();
63  updateMpiDataSize_();
64  }
65 
66  MpiBuffer(const MpiBuffer&) = default;
67 
68  ~MpiBuffer()
69  { delete[] data_; }
70 
74  void resize(size_t newSize)
75  {
76  delete[] data_;
77  data_ = new DataType[newSize];
78  dataSize_ = newSize;
79  updateMpiDataSize_();
80  }
81 
85  void send(unsigned peerRank)
86  {
87 #if HAVE_MPI
88  MPI_Isend(data_,
89  static_cast<int>(mpiDataSize_),
90  mpiDataType_,
91  static_cast<int>(peerRank),
92  0, // tag
93  MPI_COMM_WORLD,
94  &mpiRequest_);
95 #endif
96  }
97 
101  void wait()
102  {
103 #if HAVE_MPI
104  MPI_Wait(&mpiRequest_, &mpiStatus_);
105 #endif // HAVE_MPI
106  }
107 
111  void receive(unsigned peerRank)
112  {
113 #if HAVE_MPI
114  MPI_Recv(data_,
115  static_cast<int>(mpiDataSize_),
116  mpiDataType_,
117  static_cast<int>(peerRank),
118  0, // tag
119  MPI_COMM_WORLD,
120  &mpiStatus_);
121  assert(!mpiStatus_.MPI_ERROR);
122 #endif // HAVE_MPI
123  }
124 
125 #if HAVE_MPI
126 
131  MPI_Request& request()
132  { return mpiRequest_; }
138  const MPI_Request& request() const
139  { return mpiRequest_; }
140 
146  MPI_Status& status()
147  { return mpiStatus_; }
153  const MPI_Status& status() const
154  { return mpiStatus_; }
155 #endif // HAVE_MPI
156 
160  size_t size() const
161  { return dataSize_; }
162 
166  DataType& operator[](size_t i)
167  {
168  assert(0 <= i && i < dataSize_);
169  return data_[i];
170  }
171 
175  const DataType& operator[](size_t i) const
176  {
177  assert(0 <= i && i < dataSize_);
178  return data_[i];
179  }
180 
181 private:
182  void setMpiDataType_()
183  {
184 #if HAVE_MPI
185  // set the MPI data type
186  if (std::is_same<DataType, char>::value)
187  mpiDataType_ = MPI_CHAR;
188  else if (std::is_same<DataType, unsigned char>::value)
189  mpiDataType_ = MPI_UNSIGNED_CHAR;
190  else if (std::is_same<DataType, short>::value)
191  mpiDataType_ = MPI_SHORT;
192  else if (std::is_same<DataType, unsigned short>::value)
193  mpiDataType_ = MPI_UNSIGNED_SHORT;
194  else if (std::is_same<DataType, int>::value)
195  mpiDataType_ = MPI_INT;
196  else if (std::is_same<DataType, unsigned>::value)
197  mpiDataType_ = MPI_UNSIGNED;
198  else if (std::is_same<DataType, long>::value)
199  mpiDataType_ = MPI_LONG;
200  else if (std::is_same<DataType, unsigned long>::value)
201  mpiDataType_ = MPI_UNSIGNED_LONG;
202  else if (std::is_same<DataType, long long>::value)
203  mpiDataType_ = MPI_LONG_LONG;
204  else if (std::is_same<DataType, unsigned long long>::value)
205  mpiDataType_ = MPI_UNSIGNED_LONG_LONG;
206  else if (std::is_same<DataType, float>::value)
207  mpiDataType_ = MPI_FLOAT;
208  else if (std::is_same<DataType, double>::value)
209  mpiDataType_ = MPI_DOUBLE;
210  else if (std::is_same<DataType, long double>::value)
211  mpiDataType_ = MPI_LONG_DOUBLE;
212  else {
213  mpiDataType_ = MPI_BYTE;
214  }
215 #endif // HAVE_MPI
216  }
217 
218  void updateMpiDataSize_()
219  {
220 #if HAVE_MPI
221  mpiDataSize_ = dataSize_;
222  if (mpiDataType_ == MPI_BYTE)
223  mpiDataSize_ *= sizeof(DataType);
224 #endif // HAVE_MPI
225  }
226 
227  DataType *data_;
228  size_t dataSize_;
229 #if HAVE_MPI
230  size_t mpiDataSize_;
231  MPI_Datatype mpiDataType_;
232  MPI_Request mpiRequest_;
233  MPI_Status mpiStatus_;
234 #endif // HAVE_MPI
235 };
236 
237 } // namespace Ewoms
238 
239 #endif
Simplifies handling of buffers to be used in conjunction with MPI.
Definition: mpibuffer.hh:45
const DataType & operator[](size_t i) const
Provide access to the buffer data.
Definition: mpibuffer.hh:175
Definition: baseauxiliarymodule.hh:37
void send(unsigned peerRank)
Send the buffer asyncronously to a peer process.
Definition: mpibuffer.hh:85
void receive(unsigned peerRank)
Receive the buffer syncronously from a peer rank.
Definition: mpibuffer.hh:111
void resize(size_t newSize)
Set the size of the buffer.
Definition: mpibuffer.hh:74
size_t size() const
Returns the number of data objects in the buffer.
Definition: mpibuffer.hh:160
void wait()
Wait until the buffer was send to the peer completely.
Definition: mpibuffer.hh:101
DataType & operator[](size_t i)
Provide access to the buffer data.
Definition: mpibuffer.hh:166