Dune Core Modules (unstable)

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 © 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#if HAVE_MPI
24
25#include <type_traits>
26#include <vector>
27
28#include <mpi.h>
29
32
33
34namespace Dune {
35
36 class MPIPack {
37 std::vector<char> _buffer;
38 int _position;
39 MPI_Comm _comm;
40
41 friend struct MPIData<MPIPack>;
42 friend struct MPIData<const MPIPack>;
43 public:
44 MPIPack(Communication<MPI_Comm> comm, std::size_t size = 0)
45 : _buffer(size)
46 , _position(0)
47 , _comm(comm)
48 {}
49
50 // Its not valid to copy a MPIPack but you can move it
51 MPIPack(const MPIPack&) = delete;
52 MPIPack& operator = (const MPIPack& other) = delete;
53 MPIPack(MPIPack&&) = default;
54 MPIPack& operator = (MPIPack&& other) = default;
55
61 template<class T>
62 void pack(const T& data){
63 auto mpidata = getMPIData(data);
64 int size = getPackSize(mpidata.size(), _comm, mpidata.type());
65 constexpr bool has_static_size = decltype(getMPIData(std::declval<T&>()))::static_size;
66 if(!has_static_size)
67 size += getPackSize(1, _comm, MPI_INT);
68 if (_position + size > 0 && size_t(_position + size) > _buffer.size()) // resize buffer if necessary
69 _buffer.resize(_position + size);
70 if(!has_static_size){
71 int size = mpidata.size();
72 MPI_Pack(&size, 1, MPI_INT, _buffer.data(), _buffer.size(),
73 &_position, _comm);
74 }
75 MPI_Pack(mpidata.ptr(), mpidata.size(),
76 mpidata.type(), _buffer.data(), _buffer.size(),
77 &_position, _comm);
78 }
79
84 template<class T>
85 auto /*void*/ unpack(T& data)
86 -> std::enable_if_t<decltype(getMPIData(data))::static_size, void>
87 {
88 auto mpidata = getMPIData(data);
89 MPI_Unpack(_buffer.data(), _buffer.size(), &_position,
90 mpidata.ptr(), mpidata.size(),
91 mpidata.type(), _comm);
92 }
93
98 template<class T>
99 auto /*void*/ unpack(T& data)
100 -> std::enable_if_t<!decltype(getMPIData(data))::static_size, void>
101 {
102 auto mpidata = getMPIData(data);
103 int size = 0;
104 MPI_Unpack(_buffer.data(), _buffer.size(), &_position,
105 &size, 1,
106 MPI_INT, _comm);
107 mpidata.resize(size);
108 MPI_Unpack(_buffer.data(), _buffer.size(), &_position,
109 mpidata.ptr(), mpidata.size(),
110 mpidata.type(), _comm);
111 }
112
113
115 template<typename T>
116 friend MPIPack& operator << (MPIPack& p, const T& t){
117 p.pack(t);
118 return p;
119 }
120
122 template<typename T>
123 friend MPIPack& operator >> (MPIPack& p, T& t){
124 p.unpack(t);
125 return p;
126 }
127
129 template<typename T>
130 MPIPack& read(T& t){
131 unpack(t);
132 return *this;
133 }
134
136 template<typename T>
137 MPIPack& write(const T& t){
138 pack(t);
139 return *this;
140 }
141
145 void resize(size_t size){
146 _buffer.resize(size);
147 }
148
151 void enlarge(int s) {
152 _buffer.resize(_buffer.size() + s);
153 }
154
157 size_t size() const {
158 return _buffer.size();
159 }
160
164 void seek(int p){
165 _position = p;
166 }
167
171 int tell() const{
172 return _position;
173 }
174
177 bool eof() const{
178 return std::size_t(_position)==_buffer.size();
179 }
180
184 static int getPackSize(int len, const MPI_Comm& comm, const MPI_Datatype& dt){
185 int size;
186 MPI_Pack_size(len, dt, comm, &size);
187 return size;
188 }
189
190 friend bool operator==(const MPIPack& a, const MPIPack& b) {
191 return a._buffer == b._buffer && a._comm == b._comm;
192 }
193 friend bool operator!=(const MPIPack& a, const MPIPack& b) {
194 return !(a==b);
195 }
196
197 };
198
199 template<class P>
200 struct MPIData<P, std::enable_if_t<std::is_same<std::remove_const_t<P>, MPIPack>::value>> {
201 protected:
202 friend auto getMPIData<P>(P& t);
203 MPIData(P& t) :
204 data_(t)
205 {}
206 public:
207 static constexpr bool static_size = std::is_const<P>::value;
208
209 void* ptr() {
210 return (void*) data_._buffer.data();
211 }
212
213 int size() {
214 return data_.size();
215 }
216
217 MPI_Datatype type() const{
218 return MPI_PACKED;
219 }
220
221 void resize(int size){
222 data_.resize(size);
223 }
224 protected:
225 P& data_;
226 };
227
228} // end namespace Dune
229
230#endif // HAVE_MPI
231#endif // DUNE_COMMON_PARALLEL_MPIPACK_HH
std::istream & operator>>(std::istream &stream, std::tuple< Ts... > &t)
Read a std::tuple.
Definition: streamoperators.hh:43
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:238
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:260
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:13
constexpr std::integral_constant< std::size_t, sizeof...(II)> size(std::integer_sequence< T, II... >)
Return the size of the sequence.
Definition: integersequence.hh:75
STL namespace.
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Dec 21, 23:30, 2024)