DUNE PDELab (2.8)

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:
18#ifndef DUNE_COMMON_PARALLEL_MPIPACK_HH
19#define DUNE_COMMON_PARALLEL_MPIPACK_HH
20
21#include <vector>
22#if HAVE_MPI
23#include <mpi.h>
26
27
28namespace Dune {
29
30 class MPIPack {
31 std::vector<char> _buffer;
32 int _position;
33 MPI_Comm _comm;
34
35 friend struct MPIData<MPIPack>;
36 friend struct MPIData<const MPIPack>;
37 public:
38 MPIPack(Communication<MPI_Comm> comm, std::size_t size = 0)
39 : _buffer(size)
40 , _position(0)
41 , _comm(comm)
42 {}
43
44 // Its not valid to copy a MPIPack but you can move it
45 MPIPack(const MPIPack&) = delete;
46 MPIPack& operator = (const MPIPack& other) = delete;
47 MPIPack(MPIPack&&) = default;
48 MPIPack& operator = (MPIPack&& other) = default;
49
55 template<class T>
56 void pack(const T& data){
57 auto mpidata = getMPIData(data);
58 int size = getPackSize(mpidata.size(), _comm, mpidata.type());
59 constexpr bool has_static_size = decltype(getMPIData(std::declval<T&>()))::static_size;
60 if(!has_static_size)
61 size += getPackSize(1, _comm, MPI_INT);
62 if (_position + size > 0 && size_t(_position + size) > _buffer.size()) // resize buffer if necessary
63 _buffer.resize(_position + size);
64 if(!has_static_size){
65 int size = mpidata.size();
66 MPI_Pack(&size, 1, MPI_INT, _buffer.data(), _buffer.size(),
67 &_position, _comm);
68 }
69 MPI_Pack(mpidata.ptr(), mpidata.size(),
70 mpidata.type(), _buffer.data(), _buffer.size(),
71 &_position, _comm);
72 }
73
78 template<class T>
79 auto /*void*/ unpack(T& data)
80 -> std::enable_if_t<decltype(getMPIData(data))::static_size, void>
81 {
82 auto mpidata = getMPIData(data);
83 MPI_Unpack(_buffer.data(), _buffer.size(), &_position,
84 mpidata.ptr(), mpidata.size(),
85 mpidata.type(), _comm);
86 }
87
92 template<class T>
93 auto /*void*/ unpack(T& data)
94 -> std::enable_if_t<!decltype(getMPIData(data))::static_size, void>
95 {
96 auto mpidata = getMPIData(data);
97 int size = 0;
98 MPI_Unpack(_buffer.data(), _buffer.size(), &_position,
99 &size, 1,
100 MPI_INT, _comm);
101 mpidata.resize(size);
102 MPI_Unpack(_buffer.data(), _buffer.size(), &_position,
103 mpidata.ptr(), mpidata.size(),
104 mpidata.type(), _comm);
105 }
106
107
109 template<typename T>
110 friend MPIPack& operator << (MPIPack& p, const T& t){
111 p.pack(t);
112 return p;
113 }
114
116 template<typename T>
117 friend MPIPack& operator >> (MPIPack& p, T& t){
118 p.unpack(t);
119 return p;
120 }
121
123 template<typename T>
124 MPIPack& read(T& t){
125 unpack(t);
126 return *this;
127 }
128
130 template<typename T>
131 MPIPack& write(const T& t){
132 pack(t);
133 return *this;
134 }
135
139 void resize(size_t size){
140 _buffer.resize(size);
141 }
142
145 void enlarge(int s) {
146 _buffer.resize(_buffer.size() + s);
147 }
148
151 size_t size() const {
152 return _buffer.size();
153 }
154
158 void seek(int p){
159 _position = p;
160 }
161
165 int tell() const{
166 return _position;
167 }
168
171 bool eof() const{
172 return std::size_t(_position)==_buffer.size();
173 }
174
178 static int getPackSize(int len, const MPI_Comm& comm, const MPI_Datatype& dt){
179 int size;
180 MPI_Pack_size(len, dt, comm, &size);
181 return size;
182 }
183
184 friend bool operator==(const MPIPack& a, const MPIPack& b) {
185 return a._buffer == b._buffer && a._comm == b._comm;
186 }
187 friend bool operator!=(const MPIPack& a, const MPIPack& b) {
188 return !(a==b);
189 }
190
191 };
192
193 template<class P>
194 struct MPIData<P, std::enable_if_t<std::is_same<std::remove_const_t<P>, MPIPack>::value>> {
195 protected:
196 friend auto getMPIData<P>(P& t);
197 MPIData(P& t) :
198 data_(t)
199 {}
200 public:
201 static constexpr bool static_size = std::is_const<P>::value;
202
203 void* ptr() {
204 return (void*) data_._buffer.data();
205 }
206
207 int size() {
208 return data_.size();
209 }
210
211 MPI_Datatype type() const{
212 return MPI_PACKED;
213 }
214
215 void resize(int size){
216 data_.resize(size);
217 }
218 protected:
219 P& data_;
220 };
221
222} // end namespace Dune
223
224#endif
225#endif
Stream & operator>>(Stream &stream, std::tuple< Ts... > &t)
Read a std::tuple.
Definition: streamoperators.hh:41
EnableIfInterOperable< T1, T2, bool >::type operator==(const ForwardIteratorFacade< T1, V1, R1, D > &lhs, const ForwardIteratorFacade< T2, V2, R2, D > &rhs)
Checks for equality.
Definition: iteratorfacades.hh:235
EnableIfInterOperable< T1, T2, bool >::type operator!=(const ForwardIteratorFacade< T1, V1, R1, D > &lhs, const ForwardIteratorFacade< T2, V2, R2, D > &rhs)
Checks for inequality.
Definition: iteratorfacades.hh:257
Implements an utility class that provides MPI's collective communication methods.
Interface class to translate objects to a MPI_Datatype, void* and size used for MPI calls.
Dune namespace.
Definition: alignedallocator.hh:11
STL namespace.
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Dec 21, 23:30, 2024)