MPIPacker.hpp
Go to the documentation of this file.
1/*
2 Copyright 2019 Equinor AS.
3
4 This file is part of the Open Porous Media project (OPM).
5
6 OPM is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 OPM is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with OPM. If not, see <http://www.gnu.org/licenses/>.
18*/
19#ifndef MPI_PACKER_HPP
20#define MPI_PACKER_HPP
21
22#include <opm/common/utility/TimeService.hpp>
24
25#include <dune/common/parallel/mpitraits.hh>
26
27#include <bitset>
28#include <cstddef>
29#include <limits>
30#include <string>
31
32
33namespace Opm::Mpi {
34
35namespace detail {
36
37std::size_t mpi_buffer_size(const std::size_t bufsize, const std::size_t position);
38
40template <bool pod, class T>
41struct Packing
42{
43 static std::size_t packSize(const T&, Parallel::MPIComm);
44 static void pack(const T&, std::vector<char>&, std::size_t&, Parallel::MPIComm);
45 static void unpack(T&, const std::vector<char>&, std::size_t&, Parallel::MPIComm);
46};
47
49template<class T>
50struct Packing<true,T>
51{
55 static std::size_t packSize(const T& data, Parallel::MPIComm comm)
56 {
57 return packSize(&data, 1, comm);
58 }
59
64 static std::size_t packSize(const T*, std::size_t n, Parallel::MPIComm comm)
65 {
66 // For now we do not handle the situation where a a single call to packSize/pack/unpack
67 // is likely to require an MPI_Pack_size value larger than intmax
68 if (n*sizeof(T) > std::numeric_limits<int>::max())
69 throw std::invalid_argument("packSize will be larger than max integer - this is not supported.");
70 int size = 0;
71 MPI_Pack_size(n, Dune::MPITraits<T>::getType(), comm, &size);
72 return static_cast<std::size_t>(size);
73 }
74
80 static void pack(const T& data,
81 std::vector<char>& buffer,
82 std::size_t& position,
84 {
85 pack(&data, 1, buffer, position, comm);
86 }
87
94 static void pack(const T* data,
95 std::size_t n,
96 std::vector<char>& buffer,
97 std::size_t& position,
99 {
100 int int_position = 0;
101 MPI_Pack(data, n, Dune::MPITraits<T>::getType(), buffer.data()+position,
102 mpi_buffer_size(buffer.size(), position), &int_position, comm);
103 position += int_position;
104 }
105
111 static void unpack(T& data,
112 const std::vector<char>& buffer,
113 std::size_t& position,
115 {
116 unpack(&data, 1, buffer, position, comm);
117 }
118
125 static void unpack(T* data,
126 std::size_t n,
127 const std::vector<char>& buffer,
128 std::size_t& position,
130 {
131 int int_position = 0;
132 MPI_Unpack(buffer.data()+position, mpi_buffer_size(buffer.size(), position), &int_position, data, n,
134 position += int_position;
135 }
136};
137
139template<class T>
140struct Packing<false,T>
141{
142 static std::size_t packSize(const T&, Parallel::MPIComm)
143 {
144 static_assert(!std::is_same_v<T,T>, "Packing not supported for type");
145 return 0;
146 }
147
148 static void pack(const T&, std::vector<char>&, std::size_t&,
150 {
151 static_assert(!std::is_same_v<T,T>, "Packing not supported for type");
152 }
153
154 static void unpack(T&, const std::vector<char>&, std::size_t&,
156 {
157 static_assert(!std::is_same_v<T,T>, "Packing not supported for type");
158 }
159};
160
162template <std::size_t Size>
163struct Packing<false,std::bitset<Size>>
164{
165 static std::size_t packSize(const std::bitset<Size>&, Opm::Parallel::MPIComm);
166 static void pack(const std::bitset<Size>&, std::vector<char>&, std::size_t&, Opm::Parallel::MPIComm);
167 static void unpack(std::bitset<Size>&, const std::vector<char>&,
168 std::size_t&, Opm::Parallel::MPIComm);
169};
170
171#define ADD_PACK_SPECIALIZATION(T) \
172 template<> \
173 struct Packing<false,T> \
174 { \
175 static std::size_t packSize(const T&, Parallel::MPIComm); \
176 static void pack(const T&, std::vector<char>&, std::size_t&, Parallel::MPIComm); \
177 static void unpack(T&, const std::vector<char>&, std::size_t&, Parallel::MPIComm); \
178 };
179
180ADD_PACK_SPECIALIZATION(std::string)
181ADD_PACK_SPECIALIZATION(time_point)
182
183#undef ADD_PACK_SPECIALIZATION
184
185}
186
188struct Packer
189{
193 : m_comm(comm)
194 {}
195
199 template<class T>
200 std::size_t packSize(const T& data) const
201 {
202 return detail::Packing<std::is_pod_v<T>,T>::packSize(data, m_comm);
203 }
204
209 template<class T>
210 std::size_t packSize(const T* data, std::size_t n) const
211 {
212 static_assert(std::is_pod_v<T>, "Array packing not supported for non-pod data");
213 return detail::Packing<true,T>::packSize(data, n, m_comm);
214 }
215
221 template<class T>
222 void pack(const T& data,
223 std::vector<char>& buffer,
224 std::size_t& position) const
225 {
226 detail::Packing<std::is_pod_v<T>,T>::pack(data, buffer, position, m_comm);
227 }
228
235 template<class T>
236 void pack(const T* data,
237 std::size_t n,
238 std::vector<char>& buffer,
239 std::size_t& position) const
240 {
241 static_assert(std::is_pod_v<T>, "Array packing not supported for non-pod data");
242 detail::Packing<true,T>::pack(data, n, buffer, position, m_comm);
243 }
244
250 template<class T>
251 void unpack(T& data,
252 const std::vector<char>& buffer,
253 std::size_t& position) const
254 {
255 detail::Packing<std::is_pod_v<T>,T>::unpack(data, buffer, position, m_comm);
256 }
257
264 template<class T>
265 void unpack(T* data,
266 std::size_t n,
267 const std::vector<char>& buffer,
268 std::size_t& position) const
269 {
270 static_assert(std::is_pod_v<T>, "Array packing not supported for non-pod data");
271 detail::Packing<true,T>::unpack(data, n, buffer, position, m_comm);
272 }
273
274private:
276};
277
278} // end namespace Opm::Mpi
279
280#endif // MPI_PACKER_HPP
#define ADD_PACK_SPECIALIZATION(T)
Definition: MPIPacker.hpp:171
std::size_t mpi_buffer_size(const std::size_t bufsize, const std::size_t position)
Definition: MPIPacker.hpp:33
Dune::Communication< MPIComm > Communication
Definition: ParallelCommunication.hpp:30
typename Dune::MPIHelper::MPICommunicator MPIComm
Definition: ParallelCommunication.hpp:29
TYPE getType(const TABLE &table)
Struct handling packing of serialization for MPI communication.
Definition: MPIPacker.hpp:189
Packer(Parallel::Communication comm)
Constructor.
Definition: MPIPacker.hpp:192
void unpack(T &data, const std::vector< char > &buffer, std::size_t &position) const
Unpack a variable.
Definition: MPIPacker.hpp:251
void pack(const T *data, std::size_t n, std::vector< char > &buffer, std::size_t &position) const
Pack an array.
Definition: MPIPacker.hpp:236
void unpack(T *data, std::size_t n, const std::vector< char > &buffer, std::size_t &position) const
Unpack an array.
Definition: MPIPacker.hpp:265
std::size_t packSize(const T *data, std::size_t n) const
Calculates the pack size for an array.
Definition: MPIPacker.hpp:210
std::size_t packSize(const T &data) const
Calculates the pack size for a variable.
Definition: MPIPacker.hpp:200
void pack(const T &data, std::vector< char > &buffer, std::size_t &position) const
Pack a variable.
Definition: MPIPacker.hpp:222
static void pack(const T &, std::vector< char > &, std::size_t &, Parallel::MPIComm)
Definition: MPIPacker.hpp:148
static std::size_t packSize(const T &, Parallel::MPIComm)
Definition: MPIPacker.hpp:142
static void unpack(T &, const std::vector< char > &, std::size_t &, Parallel::MPIComm)
Definition: MPIPacker.hpp:154
static void unpack(std::bitset< Size > &, const std::vector< char > &, std::size_t &, Opm::Parallel::MPIComm)
static void pack(const std::bitset< Size > &, std::vector< char > &, std::size_t &, Opm::Parallel::MPIComm)
static std::size_t packSize(const std::bitset< Size > &, Opm::Parallel::MPIComm)
static void pack(const T *data, std::size_t n, std::vector< char > &buffer, std::size_t &position, Parallel::MPIComm comm)
Pack an array of POD.
Definition: MPIPacker.hpp:94
static void pack(const T &data, std::vector< char > &buffer, std::size_t &position, Parallel::MPIComm comm)
Pack a POD.
Definition: MPIPacker.hpp:80
static std::size_t packSize(const T *, std::size_t n, Parallel::MPIComm comm)
Calculates the pack size for an array of POD.
Definition: MPIPacker.hpp:64
static void unpack(T *data, std::size_t n, const std::vector< char > &buffer, std::size_t &position, Parallel::MPIComm comm)
Unpack an array of POD.
Definition: MPIPacker.hpp:125
static void unpack(T &data, const std::vector< char > &buffer, std::size_t &position, Parallel::MPIComm comm)
Unpack a POD.
Definition: MPIPacker.hpp:111
static std::size_t packSize(const T &data, Parallel::MPIComm comm)
Calculates the pack size for a POD.
Definition: MPIPacker.hpp:55
Abstract struct for packing which is (partially) specialized for specific types.
Definition: MPIPacker.hpp:42
static std::size_t packSize(const T &, Parallel::MPIComm)
static void pack(const T &, std::vector< char > &, std::size_t &, Parallel::MPIComm)
static void unpack(T &, const std::vector< char > &, std::size_t &, Parallel::MPIComm)