mirror of
https://github.com/OPM/opm-simulators.git
synced 2026-08-27 13:57:35 -05:00
Merge pull request #4107 from akva2/mpipacker_refactor
Refactor MPIPacker
This commit is contained in:
@@ -74,7 +74,6 @@ list (APPEND MAIN_SOURCE_FILES
|
||||
opm/simulators/timestepping/gatherConvergenceReport.cpp
|
||||
opm/simulators/utils/DeferredLogger.cpp
|
||||
opm/simulators/utils/gatherDeferredLogger.cpp
|
||||
opm/simulators/utils/MPIPacker.cpp
|
||||
opm/simulators/utils/ParallelFileMerger.cpp
|
||||
opm/simulators/utils/ParallelRestart.cpp
|
||||
opm/simulators/wells/ALQState.cpp
|
||||
@@ -146,7 +145,8 @@ if(HAVE_AMGCL)
|
||||
endif()
|
||||
if(MPI_FOUND)
|
||||
list(APPEND MAIN_SOURCE_FILES opm/simulators/utils/ParallelEclipseState.cpp
|
||||
opm/simulators/utils/ParallelSerialization.cpp)
|
||||
opm/simulators/utils/ParallelSerialization.cpp
|
||||
opm/simulators/utils/MPIPacker.cpp)
|
||||
endif()
|
||||
|
||||
# originally generated with the command:
|
||||
|
||||
+46
-32
@@ -107,11 +107,11 @@ public:
|
||||
const_cast<T&>(data).serializeOp(*this);
|
||||
} else {
|
||||
if (m_op == Operation::PACKSIZE)
|
||||
m_packSize += Mpi::packSize(data, m_comm);
|
||||
m_packSize += Mpi::Packer::packSize(data, m_comm);
|
||||
else if (m_op == Operation::PACK)
|
||||
Mpi::pack(data, m_buffer, m_position, m_comm);
|
||||
Mpi::Packer::pack(data, m_buffer, m_position, m_comm);
|
||||
else if (m_op == Operation::UNPACK)
|
||||
Mpi::unpack(const_cast<T&>(data), m_buffer, m_position, m_comm);
|
||||
Mpi::Packer::unpack(const_cast<T&>(data), m_buffer, m_position, m_comm);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,7 +121,7 @@ public:
|
||||
template <typename T>
|
||||
void vector(std::vector<T>& data)
|
||||
{
|
||||
auto handle = [&](auto& d)
|
||||
[[maybe_unused]] auto handle = [&](auto& d)
|
||||
{
|
||||
for (auto& it : d) {
|
||||
if constexpr (is_pair_or_tuple<T>::value)
|
||||
@@ -138,16 +138,25 @@ public:
|
||||
};
|
||||
|
||||
if (m_op == Operation::PACKSIZE) {
|
||||
m_packSize += Mpi::packSize(data.size(), m_comm);
|
||||
handle(data);
|
||||
m_packSize += Mpi::Packer::packSize(data.size(), m_comm);
|
||||
if constexpr (std::is_pod_v<T>)
|
||||
m_packSize += Mpi::Packer::packSize(data.data(), data.size(), m_comm);
|
||||
else
|
||||
handle(data);
|
||||
} else if (m_op == Operation::PACK) {
|
||||
Mpi::pack(data.size(), m_buffer, m_position, m_comm);
|
||||
handle(data);
|
||||
Mpi::Packer::pack(data.size(), m_buffer, m_position, m_comm);
|
||||
if constexpr (std::is_pod_v<T>)
|
||||
Mpi::Packer::pack(data.data(), data.size(), m_buffer, m_position, m_comm);
|
||||
else
|
||||
handle(data);
|
||||
} else if (m_op == Operation::UNPACK) {
|
||||
size_t size;
|
||||
Mpi::unpack(size, m_buffer, m_position, m_comm);
|
||||
Mpi::Packer::unpack(size, m_buffer, m_position, m_comm);
|
||||
data.resize(size);
|
||||
handle(data);
|
||||
if constexpr (std::is_pod_v<T>)
|
||||
Mpi::Packer::unpack(data.data(), size, m_buffer, m_position, m_comm);
|
||||
else
|
||||
handle(data);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,8 +165,8 @@ public:
|
||||
void vector(std::vector<bool>& data)
|
||||
{
|
||||
if (m_op == Operation::PACKSIZE) {
|
||||
m_packSize += Mpi::packSize(data.size(), m_comm);
|
||||
m_packSize += data.size()*Mpi::packSize(bool(), m_comm);
|
||||
m_packSize += Mpi::Packer::packSize(data.size(), m_comm);
|
||||
m_packSize += data.size()*Mpi::Packer::packSize(bool(), m_comm);
|
||||
} else if (m_op == Operation::PACK) {
|
||||
(*this)(data.size());
|
||||
for (const auto entry : data) { // Not a reference: vector<bool> range
|
||||
@@ -184,7 +193,7 @@ public:
|
||||
{
|
||||
using T = typename Array::value_type;
|
||||
|
||||
auto handle = [&](auto& d) {
|
||||
[[maybe_unused]] auto handle = [&](auto& d) {
|
||||
for (auto& it : d) {
|
||||
if constexpr (is_pair_or_tuple<T>::value)
|
||||
tuple(it);
|
||||
@@ -198,15 +207,20 @@ public:
|
||||
};
|
||||
|
||||
if (m_op == Operation::PACKSIZE) {
|
||||
m_packSize += Mpi::packSize(data.size(), m_comm);
|
||||
handle(data);
|
||||
if constexpr (std::is_pod_v<T>)
|
||||
m_packSize += Mpi::Packer::packSize(data.data(), data.size(), m_comm);
|
||||
else
|
||||
handle(data);
|
||||
} else if (m_op == Operation::PACK) {
|
||||
Mpi::pack(data.size(), m_buffer, m_position, m_comm);
|
||||
handle(data);
|
||||
if constexpr (std::is_pod_v<T>)
|
||||
Mpi::Packer::pack(data.data(), data.size(), m_buffer, m_position, m_comm);
|
||||
else
|
||||
handle(data);
|
||||
} else if (m_op == Operation::UNPACK) {
|
||||
size_t size;
|
||||
Mpi::unpack(size, m_buffer, m_position, m_comm);
|
||||
handle(data);
|
||||
if constexpr (std::is_pod_v<T>)
|
||||
Mpi::Packer::unpack(data.data(), data.size(), m_buffer, m_position, m_comm);
|
||||
else
|
||||
handle(data);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -223,14 +237,14 @@ public:
|
||||
(*this)(d);
|
||||
};
|
||||
if (m_op == Operation::PACKSIZE) {
|
||||
m_packSize += Mpi::packSize(data.index(), m_comm);
|
||||
m_packSize += Mpi::Packer::packSize(data.index(), m_comm);
|
||||
std::visit(visitor, data);
|
||||
} else if (m_op == Operation::PACK) {
|
||||
Mpi::pack(data.index(), m_buffer, m_position, m_comm);
|
||||
Mpi::Packer::pack(data.index(), m_buffer, m_position, m_comm);
|
||||
std::visit(visitor, data);
|
||||
} else if (m_op == Operation::UNPACK) {
|
||||
size_t index;
|
||||
Mpi::unpack(index, m_buffer, m_position, m_comm);
|
||||
Mpi::Packer::unpack(index, m_buffer, m_position, m_comm);
|
||||
auto& data_mut = const_cast<std::variant<Args...>&>(data);
|
||||
data_mut = detail::make_variant<Args...>(index);
|
||||
std::visit(visitor, data_mut);
|
||||
@@ -244,18 +258,18 @@ public:
|
||||
void optional(const std::optional<T>& data)
|
||||
{
|
||||
if (m_op == Operation::PACKSIZE) {
|
||||
m_packSize += Mpi::packSize(data.has_value(), m_comm);
|
||||
m_packSize += Mpi::Packer::packSize(data.has_value(), m_comm);
|
||||
if (data.has_value()) {
|
||||
(*this)(*data);
|
||||
}
|
||||
} else if (m_op == Operation::PACK) {
|
||||
Mpi::pack(data.has_value(), m_buffer, m_position, m_comm);
|
||||
Mpi::Packer::pack(data.has_value(), m_buffer, m_position, m_comm);
|
||||
if (data.has_value()) {
|
||||
(*this)(*data);
|
||||
}
|
||||
} else if (m_op == Operation::UNPACK) {
|
||||
bool has;
|
||||
Mpi::unpack(has, m_buffer, m_position, m_comm);
|
||||
Mpi::Packer::unpack(has, m_buffer, m_position, m_comm);
|
||||
if (has) {
|
||||
T res;
|
||||
(*this)(res);
|
||||
@@ -306,20 +320,20 @@ public:
|
||||
};
|
||||
|
||||
if (m_op == Operation::PACKSIZE) {
|
||||
m_packSize += Mpi::packSize(data.size(), m_comm);
|
||||
m_packSize += Mpi::Packer::packSize(data.size(), m_comm);
|
||||
for (auto& it : data) {
|
||||
keyHandle(it.first);
|
||||
handle(it.second);
|
||||
}
|
||||
} else if (m_op == Operation::PACK) {
|
||||
Mpi::pack(data.size(), m_buffer, m_position, m_comm);
|
||||
Mpi::Packer::pack(data.size(), m_buffer, m_position, m_comm);
|
||||
for (auto& it : data) {
|
||||
keyHandle(it.first);
|
||||
handle(it.second);
|
||||
}
|
||||
} else if (m_op == Operation::UNPACK) {
|
||||
size_t size;
|
||||
Mpi::unpack(size, m_buffer, m_position, m_comm);
|
||||
Mpi::Packer::unpack(size, m_buffer, m_position, m_comm);
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
Key key;
|
||||
keyHandle(key);
|
||||
@@ -351,18 +365,18 @@ public:
|
||||
};
|
||||
|
||||
if (m_op == Operation::PACKSIZE) {
|
||||
m_packSize += Mpi::packSize(data.size(), m_comm);
|
||||
m_packSize += Mpi::Packer::packSize(data.size(), m_comm);
|
||||
for (auto& it : data) {
|
||||
handle(it);
|
||||
}
|
||||
} else if (m_op == Operation::PACK) {
|
||||
Mpi::pack(data.size(), m_buffer, m_position, m_comm);
|
||||
Mpi::Packer::pack(data.size(), m_buffer, m_position, m_comm);
|
||||
for (auto& it : data) {
|
||||
handle(it);
|
||||
}
|
||||
} else if (m_op == Operation::UNPACK) {
|
||||
size_t size;
|
||||
Mpi::unpack(size, m_buffer, m_position, m_comm);
|
||||
Mpi::Packer::unpack(size, m_buffer, m_position, m_comm);
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
Data entry;
|
||||
handle(entry);
|
||||
|
||||
@@ -19,277 +19,118 @@
|
||||
#include <config.h>
|
||||
#include "MPIPacker.hpp"
|
||||
|
||||
#include <bitset>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <ctime>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
#include <dune/common/parallel/mpitraits.hh>
|
||||
#if HAVE_MPI
|
||||
#include <ebos/eclmpiserializer.hh>
|
||||
#endif
|
||||
#include <opm/common/utility/TimeService.hpp>
|
||||
|
||||
namespace Opm
|
||||
namespace Opm {
|
||||
namespace Mpi {
|
||||
namespace detail {
|
||||
|
||||
template<std::size_t Size>
|
||||
std::size_t Packing<false,std::bitset<Size>>::
|
||||
packSize(const std::bitset<Size>& data,
|
||||
Parallel::MPIComm comm)
|
||||
{
|
||||
namespace Mpi
|
||||
{
|
||||
template<class T>
|
||||
std::size_t packSize(const T*, std::size_t, Opm::Parallel::MPIComm,
|
||||
std::integral_constant<bool, false>)
|
||||
{
|
||||
OPM_THROW(std::logic_error, "Packing not (yet) supported for this non-pod type.");
|
||||
return Packing<true,unsigned long long>::packSize(data.to_ullong(), comm);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
std::size_t packSize(const T*, std::size_t l, Opm::Parallel::MPIComm comm,
|
||||
std::integral_constant<bool, true>)
|
||||
template<std::size_t Size>
|
||||
void Packing<false,std::bitset<Size>>::
|
||||
pack(const std::bitset<Size>& data,
|
||||
std::vector<char>& buffer,
|
||||
int& position,
|
||||
Parallel::MPIComm comm)
|
||||
{
|
||||
#if HAVE_MPI
|
||||
int size;
|
||||
MPI_Pack_size(1, Dune::MPITraits<std::size_t>::getType(), comm, &size);
|
||||
std::size_t totalSize = size;
|
||||
MPI_Pack_size(l, Dune::MPITraits<T>::getType(), comm, &size);
|
||||
return totalSize + size;
|
||||
#else
|
||||
(void) comm;
|
||||
return l-l;
|
||||
#endif
|
||||
Packing<true,unsigned long long>::pack(data.to_ullong(), buffer, position, comm);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
std::size_t packSize(const T* data, std::size_t l, Opm::Parallel::MPIComm comm)
|
||||
template<std::size_t Size>
|
||||
void Packing<false,std::bitset<Size>>::
|
||||
unpack(std::bitset<Size>& data,
|
||||
std::vector<char>& buffer,
|
||||
int& position,
|
||||
Parallel::MPIComm comm)
|
||||
{
|
||||
return packSize(data, l, comm, typename std::is_pod<T>::type());
|
||||
unsigned long long d;
|
||||
Packing<true,unsigned long long>::unpack(d, buffer, position, comm);
|
||||
data = std::bitset<Size>(d);
|
||||
}
|
||||
|
||||
std::size_t packSize(const char* str, Opm::Parallel::MPIComm comm)
|
||||
std::size_t Packing<false,std::string>::
|
||||
packSize(const std::string& data, Parallel::MPIComm comm)
|
||||
{
|
||||
#if HAVE_MPI
|
||||
int size;
|
||||
MPI_Pack_size(1, Dune::MPITraits<std::size_t>::getType(), comm, &size);
|
||||
int totalSize = size;
|
||||
MPI_Pack_size(strlen(str)+1, MPI_CHAR, comm, &size);
|
||||
MPI_Pack_size(strlen(data.c_str()), MPI_CHAR, comm, &size);
|
||||
return totalSize + size;
|
||||
#else
|
||||
(void) str;
|
||||
(void) comm;
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
std::size_t packSize(const std::string& str, Opm::Parallel::MPIComm comm)
|
||||
void Packing<false,std::string>::
|
||||
pack(const std::string& data,
|
||||
std::vector<char>& buffer,
|
||||
int& position,
|
||||
Parallel::MPIComm comm)
|
||||
{
|
||||
return packSize(str.c_str(), comm);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
struct Packing
|
||||
{
|
||||
};
|
||||
|
||||
template <std::size_t Size>
|
||||
struct Packing<std::bitset<Size>>
|
||||
{
|
||||
static std::size_t packSize(const std::bitset<Size>& data, Opm::Parallel::MPIComm comm)
|
||||
{
|
||||
return Mpi::packSize(data.to_ullong(), comm);
|
||||
}
|
||||
|
||||
static void pack(const std::bitset<Size>& data, std::vector<char>& buffer, int& position, Opm::Parallel::MPIComm comm)
|
||||
{
|
||||
Mpi::pack(data.to_ullong(), buffer, position, comm);
|
||||
}
|
||||
|
||||
static void unpack(std::bitset<Size>& data, std::vector<char>& buffer, int& position, Opm::Parallel::MPIComm comm)
|
||||
{
|
||||
unsigned long long d;
|
||||
Mpi::unpack(d, buffer, position, comm);
|
||||
data = std::bitset<Size>(d);
|
||||
}
|
||||
};
|
||||
|
||||
template<std::size_t Size>
|
||||
std::size_t packSize(const std::bitset<Size>& data, Opm::Parallel::MPIComm comm)
|
||||
{
|
||||
return Packing<std::bitset<Size>>::packSize(data, comm);
|
||||
}
|
||||
|
||||
std::size_t packSize(const Opm::time_point&, Opm::Parallel::MPIComm comm)
|
||||
{
|
||||
std::time_t tp = 0;
|
||||
return packSize(tp, comm);
|
||||
}
|
||||
|
||||
|
||||
////// pack routines
|
||||
|
||||
template<class T>
|
||||
void pack(const T*, std::size_t, std::vector<char>&, int&,
|
||||
Opm::Parallel::MPIComm, std::integral_constant<bool, false>)
|
||||
{
|
||||
OPM_THROW(std::logic_error, "Packing not (yet) supported for this non-pod type.");
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void pack(const T* data, std::size_t l, std::vector<char>& buffer, int& position,
|
||||
Opm::Parallel::MPIComm comm,
|
||||
std::integral_constant<bool, true>)
|
||||
{
|
||||
#if HAVE_MPI
|
||||
MPI_Pack(&l, 1, Dune::MPITraits<std::size_t>::getType(), buffer.data(),
|
||||
buffer.size(), &position, comm);
|
||||
MPI_Pack(data, l, Dune::MPITraits<T>::getType(), buffer.data(),
|
||||
buffer.size(), &position, comm);
|
||||
#else
|
||||
(void) data;
|
||||
(void) comm;
|
||||
(void) l;
|
||||
(void) buffer;
|
||||
(void) position;
|
||||
#endif
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void pack(const T* data, std::size_t l, std::vector<char>& buffer, int& position,
|
||||
Opm::Parallel::MPIComm comm)
|
||||
{
|
||||
pack(data, l, buffer, position, comm, typename std::is_pod<T>::type());
|
||||
}
|
||||
|
||||
void pack(const char* str, std::vector<char>& buffer, int& position,
|
||||
Opm::Parallel::MPIComm comm)
|
||||
{
|
||||
#if HAVE_MPI
|
||||
std::size_t length = strlen(str)+1;
|
||||
std::size_t length = strlen(data.c_str());
|
||||
MPI_Pack(&length, 1, Dune::MPITraits<std::size_t>::getType(), buffer.data(),
|
||||
buffer.size(), &position, comm);
|
||||
MPI_Pack(str, strlen(str)+1, MPI_CHAR, buffer.data(), buffer.size(),
|
||||
&position, comm);
|
||||
#else
|
||||
(void) str;
|
||||
(void) comm;
|
||||
(void) buffer;
|
||||
(void) position;
|
||||
#endif
|
||||
buffer.size(), &position, comm);
|
||||
MPI_Pack(data.c_str(), length, MPI_CHAR, buffer.data(), buffer.size(),
|
||||
&position, comm);
|
||||
}
|
||||
|
||||
void pack(const std::string& str, std::vector<char>& buffer, int& position,
|
||||
Opm::Parallel::MPIComm comm)
|
||||
void Packing<false,std::string>::
|
||||
unpack(std::string& data,
|
||||
std::vector<char>& buffer,
|
||||
int& position,
|
||||
Opm::Parallel::MPIComm comm)
|
||||
{
|
||||
pack(str.c_str(), buffer, position, comm);
|
||||
std::size_t length = 0;
|
||||
MPI_Unpack(buffer.data(), buffer.size(), &position, &length, 1,
|
||||
Dune::MPITraits<std::size_t>::getType(), comm);
|
||||
std::vector<char> cStr(length+1, '\0');
|
||||
MPI_Unpack(buffer.data(), buffer.size(), &position, cStr.data(), length,
|
||||
MPI_CHAR, comm);
|
||||
data.clear();
|
||||
data.append(cStr.data());
|
||||
}
|
||||
|
||||
template<std::size_t Size>
|
||||
void pack(const std::bitset<Size>& data, std::vector<char>& buffer,
|
||||
int& position, Opm::Parallel::MPIComm comm)
|
||||
std::size_t Packing<false,time_point>::
|
||||
packSize(const time_point&, Opm::Parallel::MPIComm comm)
|
||||
{
|
||||
Packing<std::bitset<Size>>::pack(data, buffer, position, comm);
|
||||
return Packing<true,std::time_t>::packSize(std::time_t(), comm);
|
||||
}
|
||||
|
||||
void pack(const Opm::time_point& data, std::vector<char>& buffer, int& position,
|
||||
Opm::Parallel::MPIComm comm)
|
||||
void Packing<false,time_point>::
|
||||
pack(const time_point& data,
|
||||
std::vector<char>& buffer,
|
||||
int& position,
|
||||
Parallel::MPIComm comm)
|
||||
{
|
||||
pack(Opm::TimeService::to_time_t(data), buffer, position, comm);
|
||||
Packing<true,std::time_t>::pack(TimeService::to_time_t(data),
|
||||
buffer, position, comm);
|
||||
}
|
||||
|
||||
|
||||
/// Mpi::unpack routines
|
||||
|
||||
template<class T>
|
||||
void unpack(T*, const std::size_t&, std::vector<char>&, int&,
|
||||
Opm::Parallel::MPIComm, std::integral_constant<bool, false>)
|
||||
void Packing<false,time_point>::
|
||||
unpack(time_point& data,
|
||||
std::vector<char>& buffer,
|
||||
int& position,
|
||||
Parallel::MPIComm comm)
|
||||
{
|
||||
OPM_THROW(std::logic_error, "Packing not (yet) supported for this non-pod type.");
|
||||
std::time_t res;
|
||||
Packing<true,std::time_t>::unpack(res, buffer, position, comm);
|
||||
data = TimeService::from_time_t(res);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void unpack(T* data, const std::size_t& l, std::vector<char>& buffer, int& position,
|
||||
Opm::Parallel::MPIComm comm,
|
||||
std::integral_constant<bool, true>)
|
||||
{
|
||||
#if HAVE_MPI
|
||||
MPI_Unpack(buffer.data(), buffer.size(), &position, data, l,
|
||||
Dune::MPITraits<T>::getType(), comm);
|
||||
#else
|
||||
(void) data;
|
||||
(void) comm;
|
||||
(void) l;
|
||||
(void) buffer;
|
||||
(void) position;
|
||||
#endif
|
||||
template struct Packing<false,std::bitset<4>>;
|
||||
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void unpack(T* data, const std::size_t& l, std::vector<char>& buffer, int& position,
|
||||
Opm::Parallel::MPIComm comm)
|
||||
{
|
||||
unpack(data, l, buffer, position, comm, typename std::is_pod<T>::type());
|
||||
}
|
||||
|
||||
void unpack(char* str, std::size_t length, std::vector<char>& buffer, int& position,
|
||||
Opm::Parallel::MPIComm comm)
|
||||
{
|
||||
#if HAVE_MPI
|
||||
MPI_Unpack(buffer.data(), buffer.size(), &position, const_cast<char*>(str), length, MPI_CHAR, comm);
|
||||
#else
|
||||
(void) str;
|
||||
(void) comm;
|
||||
(void) length;
|
||||
(void) buffer;
|
||||
(void) position;
|
||||
#endif
|
||||
}
|
||||
|
||||
void unpack(std::string& str, std::vector<char>& buffer, int& position,
|
||||
Opm::Parallel::MPIComm comm)
|
||||
{
|
||||
std::size_t length=0;
|
||||
unpack(length, buffer, position, comm);
|
||||
std::vector<char> cStr(length, '\0');
|
||||
unpack(cStr.data(), length, buffer, position, comm);
|
||||
str.clear();
|
||||
str.append(cStr.data());
|
||||
}
|
||||
|
||||
template<std::size_t Size>
|
||||
void unpack(std::bitset<Size>& data, std::vector<char>& buffer, int& position,
|
||||
Opm::Parallel::MPIComm comm)
|
||||
{
|
||||
Packing<std::bitset<Size>>::unpack(data, buffer, position, comm);
|
||||
}
|
||||
|
||||
void unpack([[maybe_unused]] Opm::time_point& data, std::vector<char>& buffer, int& position,
|
||||
Opm::Parallel::MPIComm comm)
|
||||
{
|
||||
std::time_t tp;
|
||||
unpack(tp, buffer, position, comm);
|
||||
#if HAVE_MPI
|
||||
data = Opm::TimeService::from_time_t(tp);
|
||||
#endif
|
||||
}
|
||||
|
||||
#define INSTANTIATE_PACK(...) \
|
||||
template std::size_t packSize(const __VA_ARGS__& data, \
|
||||
Opm::Parallel::MPIComm comm); \
|
||||
template void pack(const __VA_ARGS__& data, \
|
||||
std::vector<char>& buffer, int& position, \
|
||||
Opm::Parallel::MPIComm comm); \
|
||||
template void unpack(__VA_ARGS__& data, \
|
||||
std::vector<char>& buffer, int& position, \
|
||||
Opm::Parallel::MPIComm comm);
|
||||
|
||||
INSTANTIATE_PACK(float)
|
||||
INSTANTIATE_PACK(double)
|
||||
INSTANTIATE_PACK(bool)
|
||||
INSTANTIATE_PACK(int)
|
||||
INSTANTIATE_PACK(unsigned char)
|
||||
INSTANTIATE_PACK(unsigned int)
|
||||
INSTANTIATE_PACK(unsigned long int)
|
||||
INSTANTIATE_PACK(unsigned long long int)
|
||||
INSTANTIATE_PACK(std::bitset<4>)
|
||||
|
||||
|
||||
#undef INSTANTIATE_PACK
|
||||
|
||||
} // end namespace Mpi
|
||||
|
||||
} // end namespace Opm
|
||||
|
||||
+219
-150
@@ -19,179 +19,248 @@
|
||||
#ifndef MPI_SERIALIZER_HPP
|
||||
#define MPI_SERIALIZER_HPP
|
||||
|
||||
#include <opm/common/ErrorMacros.hpp>
|
||||
#include <opm/common/utility/TimeService.hpp>
|
||||
|
||||
#include <opm/simulators/utils/ParallelCommunication.hpp>
|
||||
|
||||
#include <dune/common/parallel/mpitraits.hh>
|
||||
|
||||
#include <bitset>
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
#include <typeinfo>
|
||||
|
||||
namespace Opm
|
||||
namespace Opm {
|
||||
namespace Mpi {
|
||||
namespace detail {
|
||||
|
||||
//! \brief Abstract struct for packing which is (partially) specialized for specific types.
|
||||
template <bool pod, class T>
|
||||
struct Packing
|
||||
{
|
||||
static std::size_t packSize(const T&, Parallel::MPIComm);
|
||||
static void pack(const T&, std::vector<char>&, int&, Parallel::MPIComm);
|
||||
static void unpack(T&, std::vector<char>&, int&, Parallel::MPIComm);
|
||||
};
|
||||
|
||||
namespace Mpi
|
||||
//! \brief Packaging for pod data.
|
||||
template<class T>
|
||||
struct Packing<true,T>
|
||||
{
|
||||
template<class T>
|
||||
std::size_t packSize(const T*, std::size_t, Opm::Parallel::MPIComm,
|
||||
std::integral_constant<bool, false>);
|
||||
//! \brief Calculates the pack size for a POD.
|
||||
//! \param data The data to pack
|
||||
//! \param comm The communicator to use
|
||||
static std::size_t packSize(const T& data, Parallel::MPIComm comm)
|
||||
{
|
||||
return packSize(&data, 1, comm);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
std::size_t packSize(const T*, std::size_t l, Opm::Parallel::MPIComm comm,
|
||||
std::integral_constant<bool, true>);
|
||||
//! \brief Calculates the pack size for an array of POD.
|
||||
//! \param data The array to pack
|
||||
//! \param n Length of array
|
||||
//! \param comm The communicator to use
|
||||
static std::size_t packSize(const T*, std::size_t n, Parallel::MPIComm comm)
|
||||
{
|
||||
int size = 0;
|
||||
MPI_Pack_size(n, Dune::MPITraits<T>::getType(), comm, &size);
|
||||
return size;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
std::size_t packSize(const T* data, std::size_t l, Opm::Parallel::MPIComm comm);
|
||||
//! \brief Pack a POD.
|
||||
//! \param data The variable to pack
|
||||
//! \param buffer Buffer to pack into
|
||||
//! \param position Position in buffer to use
|
||||
//! \param comm The communicator to use
|
||||
static void pack(const T& data,
|
||||
std::vector<char>& buffer,
|
||||
int& position,
|
||||
Parallel::MPIComm comm)
|
||||
{
|
||||
pack(&data, 1, buffer, position, comm);
|
||||
}
|
||||
|
||||
//! \brief Pack an array of POD.
|
||||
//! \param data The array to pack
|
||||
//! \param n Length of array
|
||||
//! \param buffer Buffer to pack into
|
||||
//! \param position Position in buffer to use
|
||||
//! \param comm The communicator to use
|
||||
static void pack(const T* data,
|
||||
std::size_t n,
|
||||
std::vector<char>& buffer,
|
||||
int& position,
|
||||
Parallel::MPIComm comm)
|
||||
{
|
||||
MPI_Pack(data, n, Dune::MPITraits<T>::getType(), buffer.data(),
|
||||
buffer.size(), &position, comm);
|
||||
}
|
||||
|
||||
//! \brief Unpack a POD.
|
||||
//! \param data The variable to unpack
|
||||
//! \param buffer Buffer to unpack from
|
||||
//! \param position Position in buffer to use
|
||||
//! \param comm The communicator to use
|
||||
static void unpack(T& data,
|
||||
std::vector<char>& buffer,
|
||||
int& position,
|
||||
Parallel::MPIComm comm)
|
||||
{
|
||||
unpack(&data, 1, buffer, position, comm);
|
||||
}
|
||||
|
||||
//! \brief Unpack an array of POD.
|
||||
//! \param data The array to unpack
|
||||
//! \param n Length of array
|
||||
//! \param buffer Buffer to unpack from
|
||||
//! \param position Position in buffer to use
|
||||
//! \param comm The communicator to use
|
||||
static void unpack(T* data,
|
||||
std::size_t n,
|
||||
std::vector<char>& buffer,
|
||||
int& position,
|
||||
Parallel::MPIComm comm)
|
||||
{
|
||||
MPI_Unpack(buffer.data(), buffer.size(), &position, data, n,
|
||||
Dune::MPITraits<T>::getType(), comm);
|
||||
}
|
||||
};
|
||||
|
||||
//! \brief Default handling for unsupported types.
|
||||
template<class T>
|
||||
std::size_t packSize(const T&, Opm::Parallel::MPIComm,
|
||||
std::integral_constant<bool, false>)
|
||||
struct Packing<false,T>
|
||||
{
|
||||
std::string msg = std::string{"Packing not (yet) supported for non-pod type: "} + typeid(T).name();
|
||||
OPM_THROW(std::logic_error, msg);
|
||||
static std::size_t packSize(const T&, Parallel::MPIComm)
|
||||
{
|
||||
static_assert(!std::is_same_v<T,T>, "Packing not supported for type");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pack(const T&, std::vector<char>&, int&,
|
||||
Parallel::MPIComm)
|
||||
{
|
||||
static_assert(!std::is_same_v<T,T>, "Packing not supported for type");
|
||||
}
|
||||
|
||||
static void unpack(T&, std::vector<char>&, int&,
|
||||
Parallel::MPIComm)
|
||||
{
|
||||
static_assert(!std::is_same_v<T,T>, "Packing not supported for type");
|
||||
}
|
||||
};
|
||||
|
||||
//! \brief Specialization for std::bitset
|
||||
template <std::size_t Size>
|
||||
struct Packing<false,std::bitset<Size>>
|
||||
{
|
||||
static std::size_t packSize(const std::bitset<Size>&, Opm::Parallel::MPIComm);
|
||||
static void pack(const std::bitset<Size>&, std::vector<char>&, int&, Opm::Parallel::MPIComm);
|
||||
static void unpack(std::bitset<Size>&, std::vector<char>&, int&, Opm::Parallel::MPIComm);
|
||||
};
|
||||
|
||||
#define ADD_PACK_SPECIALIZATION(T) \
|
||||
template<> \
|
||||
struct Packing<false,T> \
|
||||
{ \
|
||||
static std::size_t packSize(const T&, Parallel::MPIComm); \
|
||||
static void pack(const T&, std::vector<char>&, int&, Parallel::MPIComm); \
|
||||
static void unpack(T&, std::vector<char>&, int&, Parallel::MPIComm); \
|
||||
};
|
||||
|
||||
ADD_PACK_SPECIALIZATION(std::string)
|
||||
ADD_PACK_SPECIALIZATION(time_point)
|
||||
|
||||
}
|
||||
|
||||
template<class T>
|
||||
std::size_t packSize(const T&, Opm::Parallel::MPIComm comm,
|
||||
std::integral_constant<bool, true>)
|
||||
{
|
||||
#if HAVE_MPI
|
||||
int size{};
|
||||
MPI_Pack_size(1, Dune::MPITraits<T>::getType(), comm, &size);
|
||||
return size;
|
||||
#else
|
||||
(void) comm;
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
//! \brief Struct handling packing of serialization for MPI communication.
|
||||
struct Packer {
|
||||
//! \brief Calculates the pack size for a variable.
|
||||
//! \tparam T The type of the data to be packed
|
||||
//! \param data The data to pack
|
||||
//! \param comm The communicator to use
|
||||
template<class T>
|
||||
static std::size_t packSize(const T& data, Parallel::MPIComm comm)
|
||||
{
|
||||
return detail::Packing<std::is_pod_v<T>,T>::packSize(data,comm);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
std::size_t packSize(const T& data, Opm::Parallel::MPIComm comm)
|
||||
{
|
||||
return packSize(data, comm, typename std::is_pod<T>::type());
|
||||
}
|
||||
//! \brief Calculates the pack size for an array.
|
||||
//! \tparam T The type of the data to be packed
|
||||
//! \param data The array to pack
|
||||
//! \param n Length of array
|
||||
//! \param comm The communicator to use
|
||||
template<class T>
|
||||
static std::size_t packSize(const T* data, std::size_t n, Parallel::MPIComm comm)
|
||||
{
|
||||
static_assert(std::is_pod_v<T>, "Array packing not supported for non-pod data");
|
||||
return detail::Packing<true,T>::packSize(data,n,comm);
|
||||
}
|
||||
|
||||
std::size_t packSize(const char* str, Opm::Parallel::MPIComm comm);
|
||||
//! \brief Pack a variable.
|
||||
//! \tparam T The type of the data to be packed
|
||||
//! \param data The variable to pack
|
||||
//! \param buffer Buffer to pack into
|
||||
//! \param position Position in buffer to use
|
||||
//! \param comm The communicator to use
|
||||
template<class T>
|
||||
static void pack(const T& data,
|
||||
std::vector<char>& buffer,
|
||||
int& position,
|
||||
Parallel::MPIComm comm)
|
||||
{
|
||||
detail::Packing<std::is_pod_v<T>,T>::pack(data, buffer, position, comm);
|
||||
}
|
||||
|
||||
template<std::size_t Size>
|
||||
std::size_t packSize(const std::bitset<Size>& data, Opm::Parallel::MPIComm comm);
|
||||
//! \brief Pack an array.
|
||||
//! \tparam T The type of the data to be packed
|
||||
//! \param data The array to pack
|
||||
//! \param n Length of array
|
||||
//! \param buffer Buffer to pack into
|
||||
//! \param position Position in buffer to use
|
||||
//! \param comm The communicator to use
|
||||
template<class T>
|
||||
static void pack(const T* data,
|
||||
std::size_t n,
|
||||
std::vector<char>& buffer,
|
||||
int& position,
|
||||
Parallel::MPIComm comm)
|
||||
{
|
||||
static_assert(std::is_pod_v<T>, "Array packing not supported for non-pod data");
|
||||
detail::Packing<true,T>::pack(data, n, buffer, position, comm);
|
||||
}
|
||||
|
||||
////// pack routines
|
||||
//! \brief Unpack a variable.
|
||||
//! \tparam T The type of the data to be unpacked
|
||||
//! \param data The variable to unpack
|
||||
//! \param buffer Buffer to unpack from
|
||||
//! \param position Position in buffer to use
|
||||
//! \param comm The communicator to use
|
||||
template<class T>
|
||||
static void unpack(T& data,
|
||||
std::vector<char>& buffer,
|
||||
int& position,
|
||||
Parallel::MPIComm comm)
|
||||
{
|
||||
detail::Packing<std::is_pod_v<T>,T>::unpack(data, buffer, position, comm);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void pack(const T*, std::size_t, std::vector<char>&, int&,
|
||||
Opm::Parallel::MPIComm, std::integral_constant<bool, false>);
|
||||
|
||||
template<class T>
|
||||
void pack(const T* data, std::size_t l, std::vector<char>& buffer, int& position,
|
||||
Opm::Parallel::MPIComm comm, std::integral_constant<bool, true>);
|
||||
|
||||
template<class T>
|
||||
void pack(const T* data, std::size_t l, std::vector<char>& buffer, int& position,
|
||||
Opm::Parallel::MPIComm comm);
|
||||
|
||||
template<class T>
|
||||
void pack(const T&, std::vector<char>&, int&,
|
||||
Opm::Parallel::MPIComm, std::integral_constant<bool, false>)
|
||||
{
|
||||
OPM_THROW(std::logic_error, "Packing not (yet) supported for this non-pod type.");
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void pack(const T& data, std::vector<char>& buffer, int& position,
|
||||
Opm::Parallel::MPIComm comm, std::integral_constant<bool, true>)
|
||||
{
|
||||
#if HAVE_MPI
|
||||
MPI_Pack(&data, 1, Dune::MPITraits<T>::getType(), buffer.data(),
|
||||
buffer.size(), &position, comm);
|
||||
#else
|
||||
(void) data;
|
||||
(void) comm;
|
||||
(void) buffer;
|
||||
(void) position;
|
||||
#endif
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void pack(const T& data, std::vector<char>& buffer, int& position,
|
||||
Opm::Parallel::MPIComm comm)
|
||||
{
|
||||
pack(data, buffer, position, comm, typename std::is_pod<T>::type());
|
||||
}
|
||||
|
||||
void pack(const char* str, std::vector<char>& buffer, int& position,
|
||||
Opm::Parallel::MPIComm comm);
|
||||
|
||||
template<std::size_t Size>
|
||||
void pack(const std::bitset<Size>& data, std::vector<char>& buffer, int& position,
|
||||
Opm::Parallel::MPIComm comm);
|
||||
|
||||
/// unpack routines
|
||||
|
||||
template<class T>
|
||||
void unpack(T*, const std::size_t&, std::vector<char>&, int&,
|
||||
Opm::Parallel::MPIComm, std::integral_constant<bool, false>);
|
||||
|
||||
template<class T>
|
||||
void unpack(T* data, const std::size_t& l, std::vector<char>& buffer, int& position,
|
||||
Opm::Parallel::MPIComm comm,
|
||||
std::integral_constant<bool, true>);
|
||||
|
||||
template<class T>
|
||||
void unpack(T* data, const std::size_t& l, std::vector<char>& buffer, int& position,
|
||||
Opm::Parallel::MPIComm comm);
|
||||
|
||||
template<class T>
|
||||
void unpack(T&, std::vector<char>&, int&,
|
||||
Opm::Parallel::MPIComm, std::integral_constant<bool, false>)
|
||||
{
|
||||
OPM_THROW(std::logic_error, "Packing not (yet) supported for this non-pod type.");
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void unpack(T& data, std::vector<char>& buffer, int& position,
|
||||
Opm::Parallel::MPIComm comm, std::integral_constant<bool, true>)
|
||||
{
|
||||
#if HAVE_MPI
|
||||
MPI_Unpack(buffer.data(), buffer.size(), &position, &data, 1,
|
||||
Dune::MPITraits<T>::getType(), comm);
|
||||
#else
|
||||
(void) data;
|
||||
(void) comm;
|
||||
(void) buffer;
|
||||
(void) position;
|
||||
#endif
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void unpack(T& data, std::vector<char>& buffer, int& position,
|
||||
Opm::Parallel::MPIComm comm)
|
||||
{
|
||||
unpack(data, buffer, position, comm, typename std::is_pod<T>::type());
|
||||
}
|
||||
|
||||
void unpack(char* str, std::size_t length, std::vector<char>& buffer, int& position,
|
||||
Opm::Parallel::MPIComm comm);
|
||||
|
||||
template<std::size_t Size>
|
||||
void unpack(std::bitset<Size>& data, std::vector<char>& buffer, int& position,
|
||||
Opm::Parallel::MPIComm comm);
|
||||
|
||||
/// prototypes for complex types
|
||||
|
||||
#define ADD_PACK_PROTOTYPES(T) \
|
||||
std::size_t packSize(const T& data, Opm::Parallel::MPIComm comm); \
|
||||
void pack(const T& data, std::vector<char>& buffer, int& position, \
|
||||
Opm::Parallel::MPIComm comm); \
|
||||
void unpack(T& data, std::vector<char>& buffer, int& position, \
|
||||
Opm::Parallel::MPIComm comm);
|
||||
|
||||
ADD_PACK_PROTOTYPES(std::string)
|
||||
ADD_PACK_PROTOTYPES(time_point)
|
||||
//! \brief Unpack an array.
|
||||
//! \tparam T The type of the data to be unpacked
|
||||
//! \param data The array to unpack
|
||||
//! \param n Length of array
|
||||
//! \param buffer Buffer to unpack from
|
||||
//! \param position Position in buffer to use
|
||||
//! \param comm The communicator to use
|
||||
template<class T>
|
||||
static void unpack(T* data,
|
||||
std::size_t n,
|
||||
std::vector<char>& buffer,
|
||||
int& position,
|
||||
Parallel::MPIComm comm)
|
||||
{
|
||||
static_assert(std::is_pod_v<T>, "Array packing not supported for non-pod data");
|
||||
detail::Packing<true,T>::unpack(data, n, buffer, position, comm);
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace Mpi
|
||||
|
||||
} // end namespace Opm
|
||||
|
||||
#endif // MPI_SERIALIZER_HPP
|
||||
|
||||
Reference in New Issue
Block a user