Loading...
Searching...
No Matches
mpipack.hh
Go to the documentation of this file.
// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
// vi: set et ts=4 sw=2 sts=2:
// SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root
// SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception
#ifndef DUNE_COMMON_PARALLEL_MPIPACK_HH
#define DUNE_COMMON_PARALLEL_MPIPACK_HH
#if HAVE_MPI
#include <type_traits>
#include <vector>
#include <mpi.h>
#include <dune/common/parallel/mpicommunication.hh>
#include <dune/common/parallel/mpidata.hh>
namespace Dune {
class MPIPack {
std::vector<char> _buffer;
int _position;
MPI_Comm _comm;
friend struct MPIData<MPIPack>;
friend struct MPIData<const MPIPack>;
public:
MPIPack(Communication<MPI_Comm> comm, std::size_t size = 0)
: _buffer(size)
, _position(0)
, _comm(comm)
{}
// Its not valid to copy a MPIPack but you can move it
MPIPack(const MPIPack&) = delete;
MPIPack& operator = (const MPIPack& other) = delete;
MPIPack(MPIPack&&) = default;
MPIPack& operator = (MPIPack&& other) = default;
template<class T>
void pack(const T& data){
auto mpidata = getMPIData(data);
int size = getPackSize(mpidata.size(), _comm, mpidata.type());
constexpr bool has_static_size = decltype(getMPIData(std::declval<T&>()))::static_size;
if(!has_static_size)
size += getPackSize(1, _comm, MPI_INT);
if (_position + size > 0 && size_t(_position + size) > _buffer.size()) // resize buffer if necessary
_buffer.resize(_position + size);
if(!has_static_size){
int size = mpidata.size();
MPI_Pack(&size, 1, MPI_INT, _buffer.data(), _buffer.size(),
&_position, _comm);
}
MPI_Pack(mpidata.ptr(), mpidata.size(),
mpidata.type(), _buffer.data(), _buffer.size(),
&_position, _comm);
}
template<class T>
auto /*void*/ unpack(T& data)
-> std::enable_if_t<decltype(getMPIData(data))::static_size, void>
{
auto mpidata = getMPIData(data);
MPI_Unpack(_buffer.data(), _buffer.size(), &_position,
mpidata.ptr(), mpidata.size(),
mpidata.type(), _comm);
}
template<class T>
auto /*void*/ unpack(T& data)
-> std::enable_if_t<!decltype(getMPIData(data))::static_size, void>
{
auto mpidata = getMPIData(data);
int size = 0;
MPI_Unpack(_buffer.data(), _buffer.size(), &_position,
&size, 1,
MPI_INT, _comm);
mpidata.resize(size);
MPI_Unpack(_buffer.data(), _buffer.size(), &_position,
mpidata.ptr(), mpidata.size(),
mpidata.type(), _comm);
}
template<typename T>
friend MPIPack& operator << (MPIPack& p, const T& t){
p.pack(t);
return p;
}
template<typename T>
friend MPIPack& operator >> (MPIPack& p, T& t){
p.unpack(t);
return p;
}
template<typename T>
MPIPack& read(T& t){
unpack(t);
return *this;
}
template<typename T>
MPIPack& write(const T& t){
pack(t);
return *this;
}
void resize(size_t size){
_buffer.resize(size);
}
void enlarge(int s) {
_buffer.resize(_buffer.size() + s);
}
size_t size() const {
return _buffer.size();
}
void seek(int p){
_position = p;
}
int tell() const{
return _position;
}
bool eof() const{
return std::size_t(_position)==_buffer.size();
}
static int getPackSize(int len, const MPI_Comm& comm, const MPI_Datatype& dt){
int size;
MPI_Pack_size(len, dt, comm, &size);
return size;
}
friend bool operator==(const MPIPack& a, const MPIPack& b) {
return a._buffer == b._buffer && a._comm == b._comm;
}
friend bool operator!=(const MPIPack& a, const MPIPack& b) {
return !(a==b);
}
};
template<class P>
struct MPIData<P, std::enable_if_t<std::is_same<std::remove_const_t<P>, MPIPack>::value>> {
protected:
friend auto getMPIData<P>(P& t);
MPIData(P& t) :
data_(t)
{}
public:
static constexpr bool static_size = std::is_const<P>::value;
void* ptr() {
return (void*) data_._buffer.data();
}
int size() {
return data_.size();
}
MPI_Datatype type() const{
return MPI_PACKED;
}
void resize(int size){
data_.resize(size);
}
protected:
P& data_;
};
} // end namespace Dune
#endif // HAVE_MPI
#endif // DUNE_COMMON_PARALLEL_MPIPACK_HH
mpicommunication.hh
Implements an utility class that provides MPI's collective communication methods.
mpidata.hh
Interface class to translate objects to a MPI_Datatype, void* and size used for MPI calls.
std
STL namespace.
Dune
Dune namespace
Definition alignedallocator.hh:13
Dune::getMPIData
auto getMPIData(T &t)
Definition mpidata.hh:44
Dune::Communication
Collective communication interface and sequential default implementation.
Definition communication.hh:100
Dune::MPIData
Definition mpidata.hh:51
Dune::MPIData::getMPIData
friend auto getMPIData(T &)
Definition mpidata.hh:44
Dune::MPIPack::enlarge
void enlarge(int s)
Enlarges the internal buffer.
Definition mpipack.hh:151
Dune::MPIPack::operator>>
friend MPIPack & operator>>(MPIPack &p, T &t)
Unpacks data from the object.
Definition mpipack.hh:123
Dune::MPIPack::operator<<
friend MPIPack & operator<<(MPIPack &p, const T &t)
Packs the data into the object. Enlarges the internal buffer if necessary.
Definition mpipack.hh:116
Dune::MPIPack::operator!=
friend bool operator!=(const MPIPack &a, const MPIPack &b)
Definition mpipack.hh:193
Dune::MPIPack::size
size_t size() const
Returns the size of the internal buffer.
Definition mpipack.hh:157
Dune::MPIPack::operator=
MPIPack & operator=(const MPIPack &other)=delete
Dune::MPIPack::MPIPack
MPIPack(Communication< MPI_Comm > comm, std::size_t size=0)
Definition mpipack.hh:44
Dune::MPIPack::pack
void pack(const T &data)
Packs the data into the object. Enlarges the internal buffer if necessary.
Definition mpipack.hh:62
Dune::MPIPack::unpack
auto unpack(T &data) -> std::enable_if_t<!decltype(getMPIData(data))::static_size, void >
Unpacks data from the object.
Definition mpipack.hh:99
Dune::MPIPack::unpack
auto unpack(T &data) -> std::enable_if_t< decltype(getMPIData(data))::static_size, void >
Unpacks data from the object.
Definition mpipack.hh:85
Dune::MPIPack::operator==
friend bool operator==(const MPIPack &a, const MPIPack &b)
Definition mpipack.hh:190
Dune::MPIPack::MPIPack
MPIPack(const MPIPack &)=delete
Dune::MPIPack::seek
void seek(int p)
Sets the position in the buffer where the next pack/unpack operation should take place.
Definition mpipack.hh:164
Dune::MPIPack::eof
bool eof() const
Checks whether the end of the buffer is reached.
Definition mpipack.hh:177
Dune::MPIPack::resize
void resize(size_t size)
Resizes the internal buffer.
Definition mpipack.hh:145
Dune::MPIPack::tell
int tell() const
Gets the position in the buffer where the next pack/unpack operation should take place.
Definition mpipack.hh:171
Dune::MPIPack::MPIPack
MPIPack(MPIPack &&)=default
Dune::MPIPack::read
MPIPack & read(T &t)
Unpacks data from the object.
Definition mpipack.hh:130
Dune::MPIPack::getPackSize
static int getPackSize(int len, const MPI_Comm &comm, const MPI_Datatype &dt)
Returns the size of the data needed to store the data in an MPIPack. See MPI_Pack_size.
Definition mpipack.hh:184
Dune::MPIPack::write
MPIPack & write(const T &t)
Packs the data into the object. Enlarges the internal buffer if necessary.
Definition mpipack.hh:137
Dune::MPIData< P, std::enable_if_t< std::is_same< std::remove_const_t< P >, MPIPack >::value > >::type
MPI_Datatype type() const
Definition mpipack.hh:217
Dune::MPIData< P, std::enable_if_t< std::is_same< std::remove_const_t< P >, MPIPack >::value > >::MPIData
MPIData(P &t)
Definition mpipack.hh:203
Dune::MPIData< P, std::enable_if_t< std::is_same< std::remove_const_t< P >, MPIPack >::value > >::static_size
static constexpr bool static_size
Definition mpipack.hh:207
Dune::MPIData< P, std::enable_if_t< std::is_same< std::remove_const_t< P >, MPIPack >::value > >::size
int size()
Definition mpipack.hh:213
Dune::MPIData< P, std::enable_if_t< std::is_same< std::remove_const_t< P >, MPIPack >::value > >::ptr
void * ptr()
Definition mpipack.hh:209
Dune::MPIData< P, std::enable_if_t< std::is_same< std::remove_const_t< P >, MPIPack >::value > >::data_
P & data_
Definition mpipack.hh:225
Dune::MPIData< P, std::enable_if_t< std::is_same< std::remove_const_t< P >, MPIPack >::value > >::resize
void resize(int size)
Definition mpipack.hh:221