Dune Core Modules (2.9.0)

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:
221 P& data_;
222 };
223
224} // end namespace Dune
225
226#endif
227#endif
Stream & operator>>(Stream &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:237
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:259
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
STL namespace.
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Dec 21, 23:30, 2024)