146 lines
4.1 KiB
Plaintext
146 lines
4.1 KiB
Plaintext
// (C) Copyright 2005 Matthias Troyer
|
|
|
|
// Use, modification and distribution is subject to the Boost Software
|
|
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
|
// http://www.boost.org/LICENSE_1_0.txt)
|
|
|
|
// Authors: Matthias Troyer
|
|
|
|
#ifndef BOOST_MPI_DETAIL_MPI_DATATYPE_OPRIMITIVE_HPP
|
|
#define BOOST_MPI_DETAIL_MPI_DATATYPE_OPRIMITIVE_HPP
|
|
|
|
#include <boost/mpi/config.hpp>
|
|
#include <cstddef> // size_t
|
|
|
|
#include <boost/config.hpp>
|
|
#if defined(BOOST_NO_STDC_NAMESPACE)
|
|
namespace std{
|
|
using ::size_t;
|
|
} // namespace std
|
|
#endif
|
|
|
|
#include <boost/mpi/datatype_fwd.hpp>
|
|
#include <boost/mpi/exception.hpp>
|
|
#include <boost/throw_exception.hpp>
|
|
#include <boost/assert.hpp>
|
|
#include <boost/mpl/placeholders.hpp>
|
|
#include <boost/serialization/array.hpp>
|
|
#include <boost/serialization/detail/get_data.hpp>
|
|
#include <stdexcept>
|
|
#include <iostream>
|
|
#include <vector>
|
|
|
|
namespace boost { namespace mpi { namespace detail {
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
// class mpi_data_type_oprimitive - creation of custom MPI data types
|
|
|
|
class mpi_datatype_primitive
|
|
{
|
|
public:
|
|
|
|
// trivial default constructor
|
|
mpi_datatype_primitive()
|
|
: is_committed(false),
|
|
origin(0)
|
|
{}
|
|
|
|
mpi_datatype_primitive(void const* orig)
|
|
: is_committed(false),
|
|
origin()
|
|
{
|
|
#if defined(MPI_VERSION) && MPI_VERSION >= 2
|
|
BOOST_MPI_CHECK_RESULT(MPI_Get_address,(const_cast<void*>(orig), &origin));
|
|
#else
|
|
BOOST_MPI_CHECK_RESULT(MPI_Address,(const_cast<void*>(orig), &origin));
|
|
#endif
|
|
}
|
|
|
|
void save_binary(void const *address, std::size_t count)
|
|
{
|
|
save_impl(address,MPI_BYTE,count);
|
|
}
|
|
|
|
// fast saving of arrays of MPI types
|
|
template<class T>
|
|
void save_array(serialization::array_wrapper<T> const& x, unsigned int /* version */)
|
|
{
|
|
if (x.count())
|
|
save_impl(x.address(), boost::mpi::get_mpi_datatype(*x.address()), x.count());
|
|
}
|
|
|
|
typedef is_mpi_datatype<mpl::_1> use_array_optimization;
|
|
|
|
// create and return the custom MPI data type
|
|
MPI_Datatype get_mpi_datatype()
|
|
{
|
|
if (!is_committed)
|
|
{
|
|
#if defined(MPI_VERSION) && MPI_VERSION >= 2
|
|
BOOST_MPI_CHECK_RESULT(MPI_Type_create_struct,
|
|
(
|
|
addresses.size(),
|
|
boost::serialization::detail::get_data(lengths),
|
|
boost::serialization::detail::get_data(addresses),
|
|
boost::serialization::detail::get_data(types),
|
|
&datatype_
|
|
));
|
|
#else
|
|
BOOST_MPI_CHECK_RESULT(MPI_Type_struct,
|
|
(
|
|
addresses.size(),
|
|
boost::serialization::detail::get_data(lengths),
|
|
boost::serialization::detail::get_data(addresses),
|
|
boost::serialization::detail::get_data(types),
|
|
&datatype_
|
|
));
|
|
#endif
|
|
BOOST_MPI_CHECK_RESULT(MPI_Type_commit,(&datatype_));
|
|
|
|
is_committed = true;
|
|
}
|
|
|
|
return datatype_;
|
|
}
|
|
|
|
// default saving of primitives.
|
|
template<class T>
|
|
void save(const T & t)
|
|
{
|
|
save_impl(&t, boost::mpi::get_mpi_datatype(t), 1);
|
|
}
|
|
|
|
private:
|
|
|
|
void save_impl(void const * p, MPI_Datatype t, int l)
|
|
{
|
|
BOOST_ASSERT ( !is_committed );
|
|
|
|
// store address, type and length
|
|
|
|
MPI_Aint a;
|
|
#if defined(MPI_VERSION) && MPI_VERSION >= 2
|
|
BOOST_MPI_CHECK_RESULT(MPI_Get_address,(const_cast<void*>(p), &a));
|
|
#else
|
|
BOOST_MPI_CHECK_RESULT(MPI_Address,(const_cast<void*>(p), &a));
|
|
#endif
|
|
addresses.push_back(a-origin);
|
|
types.push_back(t);
|
|
lengths.push_back(l);
|
|
}
|
|
|
|
std::vector<MPI_Aint> addresses;
|
|
std::vector<MPI_Datatype> types;
|
|
std::vector<int> lengths;
|
|
|
|
bool is_committed;
|
|
MPI_Datatype datatype_;
|
|
MPI_Aint origin;
|
|
};
|
|
|
|
|
|
} } } // end namespace boost::mpi::detail
|
|
|
|
|
|
#endif // BOOST_MPI_DETAIL_MPI_DATATYPE_OPRIMITIVE_HPP
|