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  Copyright (C) 2011-2013 by Andreas Lauser
5 
6  This file is part of the Open Porous Media project (OPM).
7 
8  OPM is free software: you can redistribute it and/or modify
9  it under the terms of the GNU General Public License as published by
10  the Free Software Foundation, either version 2 of the License, or
11  (at your option) any later version.
12 
13  OPM is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  GNU General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with OPM. If not, see <http://www.gnu.org/licenses/>.
20 */
25 #ifndef EWOMS_MPI_BUFFER_HH
26 #define EWOMS_MPI_BUFFER_HH
27 
28 #if HAVE_MPI
29 #include <mpi.h>
30 #endif
31 #include <stddef.h>
32 
33 #include <type_traits>
34 #include <cassert>
35 
36 namespace Ewoms {
37 
41 template <class DataType>
42 class MpiBuffer
43 {
44 public:
46  {
47  data_ = NULL;
48  dataSize_ = 0;
49 
50  setMpiDataType_();
51  updateMpiDataSize_();
52  }
53 
55  {
56  data_ = new DataType[size];
57  dataSize_ = size;
58 
59  setMpiDataType_();
60  updateMpiDataSize_();
61  }
62 
64  { delete[] data_; }
65 
69  void resize(size_t newSize)
70  {
71  delete[] data_;
72  data_ = new DataType[newSize];
73  dataSize_ = newSize;
74  updateMpiDataSize_();
75  }
76 
80  void send(int peerRank, bool setNoAccess = true)
81  {
82 #if HAVE_MPI
83  MPI_Isend(data_, mpiDataSize_, mpiDataType_, peerRank, 0, // tag
84  MPI_COMM_WORLD, &mpiRequest_);
85 #endif
86  }
87 
91  void wait()
92  {
93 #if HAVE_MPI
94  MPI_Wait(&mpiRequest_, &mpiStatus_);
95 #endif // HAVE_MPI
96  }
97 
101  void receive(int peerRank)
102  {
103 #if HAVE_MPI
104  MPI_Recv(data_, mpiDataSize_, mpiDataType_, peerRank, 0, // tag
105  MPI_COMM_WORLD, &mpiStatus_);
106  assert(!mpiStatus_.MPI_ERROR);
107 #endif // HAVE_MPI
108  }
109 
110 #if HAVE_MPI
111 
116  MPI_Request &request()
117  { return mpiRequest_; }
123  const MPI_Request &request() const
124  { return mpiRequest_; }
125 
131  MPI_Status &status()
132  { return mpiStatus_; }
138  const MPI_Status &status() const
139  { return mpiStatus_; }
140 #endif // HAVE_MPI
141 
145  size_t size() const
146  { return dataSize_; }
147 
151  DataType &operator[](size_t i)
152  {
153  assert(0 <= i && i < dataSize_);
154  return data_[i];
155  }
156 
160  const DataType &operator[](size_t i) const
161  {
162  assert(0 <= i && i < dataSize_);
163  return data_[i];
164  }
165 
166 private:
167  void setMpiDataType_()
168  {
169 #if HAVE_MPI
170  // set the MPI data type
171  if (std::is_same<DataType, char>::value)
172  mpiDataType_ = MPI_CHAR;
173  else if (std::is_same<DataType, unsigned char>::value)
174  mpiDataType_ = MPI_UNSIGNED_CHAR;
175  else if (std::is_same<DataType, short>::value)
176  mpiDataType_ = MPI_SHORT;
177  else if (std::is_same<DataType, unsigned short>::value)
178  mpiDataType_ = MPI_UNSIGNED_SHORT;
179  else if (std::is_same<DataType, int>::value)
180  mpiDataType_ = MPI_INT;
181  else if (std::is_same<DataType, unsigned>::value)
182  mpiDataType_ = MPI_UNSIGNED;
183  else if (std::is_same<DataType, long>::value)
184  mpiDataType_ = MPI_LONG;
185  else if (std::is_same<DataType, unsigned long>::value)
186  mpiDataType_ = MPI_UNSIGNED_LONG;
187  else if (std::is_same<DataType, long long>::value)
188  mpiDataType_ = MPI_LONG_LONG;
189  else if (std::is_same<DataType, unsigned long long>::value)
190  mpiDataType_ = MPI_UNSIGNED_LONG_LONG;
191  else if (std::is_same<DataType, float>::value)
192  mpiDataType_ = MPI_FLOAT;
193  else if (std::is_same<DataType, double>::value)
194  mpiDataType_ = MPI_DOUBLE;
195  else if (std::is_same<DataType, long double>::value)
196  mpiDataType_ = MPI_LONG_DOUBLE;
197  else {
198  mpiDataType_ = MPI_BYTE;
199  }
200 #endif // HAVE_MPI
201  }
202 
203  void updateMpiDataSize_()
204  {
205 #if HAVE_MPI
206  mpiDataSize_ = dataSize_;
207  if (mpiDataType_ == MPI_BYTE)
208  mpiDataSize_ *= sizeof(DataType);
209 #endif // HAVE_MPI
210  }
211 
212  DataType *data_;
213  size_t dataSize_;
214 #if HAVE_MPI
215  size_t mpiDataSize_;
216  MPI_Datatype mpiDataType_;
217  MPI_Request mpiRequest_;
218  MPI_Status mpiStatus_;
219 #endif // HAVE_MPI
220 };
221 
222 } // namespace Ewoms
223 
224 #endif
const MPI_Status & status() const
Returns the current MPI_Status object.
Definition: mpibuffer.hh:138
void send(int peerRank, bool setNoAccess=true)
Send the buffer asyncronously to a peer process.
Definition: mpibuffer.hh:80
const DataType & operator[](size_t i) const
Provide access to the buffer data.
Definition: mpibuffer.hh:160
MPI_Request & request()
Returns the current MPI_Request object.
Definition: mpibuffer.hh:116
void receive(int peerRank)
Receive the buffer syncronously from a peer rank.
Definition: mpibuffer.hh:101
Definition: baseauxiliarymodule.hh:35
MPI_Status & status()
Returns the current MPI_Status object.
Definition: mpibuffer.hh:131
size_t size() const
Returns the number of data objects in the buffer.
Definition: mpibuffer.hh:145
~MpiBuffer()
Definition: mpibuffer.hh:63
MpiBuffer(int size)
Definition: mpibuffer.hh:54
void wait()
Wait until the buffer was send to the peer completely.
Definition: mpibuffer.hh:91
const MPI_Request & request() const
Returns the current MPI_Request object.
Definition: mpibuffer.hh:123
Simplifies handling of buffers to be used in conjunction with MPI.
Definition: mpibuffer.hh:42
MpiBuffer()
Definition: mpibuffer.hh:45
DataType & operator[](size_t i)
Provide access to the buffer data.
Definition: mpibuffer.hh:151
void resize(size_t newSize)
Set the size of the buffer.
Definition: mpibuffer.hh:69