dune-common 2.9.0
Loading...
Searching...
No Matches
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 (C) 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#include <vector>
24#if HAVE_MPI
25#include <mpi.h>
28
29
30namespace Dune {
31
32 class MPIPack {
33 std::vector<char> _buffer;
34 int _position;
35 MPI_Comm _comm;
36
37 friend struct MPIData<MPIPack>;
38 friend struct MPIData<const MPIPack>;
39 public:
40 MPIPack(Communication<MPI_Comm> comm, std::size_t size = 0)
41 : _buffer(size)
42 , _position(0)
43 , _comm(comm)
44 {}
45
46 // Its not valid to copy a MPIPack but you can move it
47 MPIPack(const MPIPack&) = delete;
48 MPIPack& operator = (const MPIPack& other) = delete;
49 MPIPack(MPIPack&&) = default;
50 MPIPack& operator = (MPIPack&& other) = default;
51
57 template<class T>
58 void pack(const T& data){
59 auto mpidata = getMPIData(data);
60 int size = getPackSize(mpidata.size(), _comm, mpidata.type());
61 constexpr bool has_static_size = decltype(getMPIData(std::declval<T&>()))::static_size;
62 if(!has_static_size)
63 size += getPackSize(1, _comm, MPI_INT);
64 if (_position + size > 0 && size_t(_position + size) > _buffer.size()) // resize buffer if necessary
65 _buffer.resize(_position + size);
66 if(!has_static_size){
67 int size = mpidata.size();
68 MPI_Pack(&size, 1, MPI_INT, _buffer.data(), _buffer.size(),
69 &_position, _comm);
70 }
71 MPI_Pack(mpidata.ptr(), mpidata.size(),
72 mpidata.type(), _buffer.data(), _buffer.size(),
73 &_position, _comm);
74 }
75
80 template<class T>
81 auto /*void*/ unpack(T& data)
82 -> std::enable_if_t<decltype(getMPIData(data))::static_size, void>
83 {
84 auto mpidata = getMPIData(data);
85 MPI_Unpack(_buffer.data(), _buffer.size(), &_position,
86 mpidata.ptr(), mpidata.size(),
87 mpidata.type(), _comm);
88 }
89
94 template<class T>
95 auto /*void*/ unpack(T& data)
96 -> std::enable_if_t<!decltype(getMPIData(data))::static_size, void>
97 {
98 auto mpidata = getMPIData(data);
99 int size = 0;
100 MPI_Unpack(_buffer.data(), _buffer.size(), &_position,
101 &size, 1,
102 MPI_INT, _comm);
103 mpidata.resize(size);
104 MPI_Unpack(_buffer.data(), _buffer.size(), &_position,
105 mpidata.ptr(), mpidata.size(),
106 mpidata.type(), _comm);
107 }
108
109
111 template<typename T>
112 friend MPIPack& operator << (MPIPack& p, const T& t){
113 p.pack(t);
114 return p;
115 }
116
118 template<typename T>
119 friend MPIPack& operator >> (MPIPack& p, T& t){
120 p.unpack(t);
121 return p;
122 }
123
125 template<typename T>
126 MPIPack& read(T& t){
127 unpack(t);
128 return *this;
129 }
130
132 template<typename T>
133 MPIPack& write(const T& t){
134 pack(t);
135 return *this;
136 }
137
141 void resize(size_t size){
142 _buffer.resize(size);
143 }
144
147 void enlarge(int s) {
148 _buffer.resize(_buffer.size() + s);
149 }
150
153 size_t size() const {
154 return _buffer.size();
155 }
156
160 void seek(int p){
161 _position = p;
162 }
163
167 int tell() const{
168 return _position;
169 }
170
173 bool eof() const{
174 return std::size_t(_position)==_buffer.size();
175 }
176
180 static int getPackSize(int len, const MPI_Comm& comm, const MPI_Datatype& dt){
181 int size;
182 MPI_Pack_size(len, dt, comm, &size);
183 return size;
184 }
185
186 friend bool operator==(const MPIPack& a, const MPIPack& b) {
187 return a._buffer == b._buffer && a._comm == b._comm;
188 }
189 friend bool operator!=(const MPIPack& a, const MPIPack& b) {
190 return !(a==b);
191 }
192
193 };
194
195 template<class P>
196 struct MPIData<P, std::enable_if_t<std::is_same<std::remove_const_t<P>, MPIPack>::value>> {
197 protected:
198 friend auto getMPIData<P>(P& t);
199 MPIData(P& t) :
200 data_(t)
201 {}
202 public:
203 static constexpr bool static_size = std::is_const<P>::value;
204
205 void* ptr() {
206 return (void*) data_._buffer.data();
207 }
208
209 int size() {
210 return data_.size();
211 }
212
213 MPI_Datatype type() const{
214 return MPI_PACKED;
215 }
216
217 void resize(int size){
218 data_.resize(size);
219 }
220 protected:
222 };
223
224} // end namespace Dune
225
226#endif
227#endif
Interface class to translate objects to a MPI_Datatype, void* and size used for MPI calls.
Implements an utility class that provides MPI's collective communication methods.
STL namespace.
Dune namespace.
Definition alignedallocator.hh:13
auto getMPIData(T &t)
Definition mpidata.hh:43
Collective communication interface and sequential default implementation.
Definition communication.hh:100
Definition mpidata.hh:50
T & data_
Definition mpidata.hh:53
int size() const
Definition mpidata.hh:67
static constexpr bool static_size
Definition mpidata.hh:65
Definition mpipack.hh:32
void enlarge(int s)
Enlarges the internal buffer.
Definition mpipack.hh:147
friend MPIPack & operator>>(MPIPack &p, T &t)
Unpacks data from the object.
Definition mpipack.hh:119
friend MPIPack & operator<<(MPIPack &p, const T &t)
Packs the data into the object. Enlarges the internal buffer if necessary.
Definition mpipack.hh:112
friend bool operator!=(const MPIPack &a, const MPIPack &b)
Definition mpipack.hh:189
size_t size() const
Returns the size of the internal buffer.
Definition mpipack.hh:153
MPIPack & operator=(const MPIPack &other)=delete
MPIPack(Communication< MPI_Comm > comm, std::size_t size=0)
Definition mpipack.hh:40
void pack(const T &data)
Packs the data into the object. Enlarges the internal buffer if necessary.
Definition mpipack.hh:58
auto unpack(T &data) -> std::enable_if_t<!decltype(getMPIData(data))::static_size, void >
Unpacks data from the object.
Definition mpipack.hh:95
auto unpack(T &data) -> std::enable_if_t< decltype(getMPIData(data))::static_size, void >
Unpacks data from the object.
Definition mpipack.hh:81
friend bool operator==(const MPIPack &a, const MPIPack &b)
Definition mpipack.hh:186
MPIPack(const MPIPack &)=delete
void seek(int p)
Sets the position in the buffer where the next pack/unpack operation should take place.
Definition mpipack.hh:160
bool eof() const
Checks whether the end of the buffer is reached.
Definition mpipack.hh:173
void resize(size_t size)
Resizes the internal buffer.
Definition mpipack.hh:141
int tell() const
Gets the position in the buffer where the next pack/unpack operation should take place.
Definition mpipack.hh:167
MPIPack(MPIPack &&)=default
MPIPack & read(T &t)
Unpacks data from the object.
Definition mpipack.hh:126
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:180
MPIPack & write(const T &t)
Packs the data into the object. Enlarges the internal buffer if necessary.
Definition mpipack.hh:133