mpi_datatype_primitive.hpp 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. // (C) Copyright 2005 Matthias Troyer
  2. // Use, modification and distribution is subject to the Boost Software
  3. // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  4. // http://www.boost.org/LICENSE_1_0.txt)
  5. // Authors: Matthias Troyer
  6. #ifndef BOOST_MPI_DETAIL_MPI_DATATYPE_OPRIMITIVE_HPP
  7. #define BOOST_MPI_DETAIL_MPI_DATATYPE_OPRIMITIVE_HPP
  8. #include <boost/mpi/config.hpp>
  9. #include <cstddef> // size_t
  10. #include <boost/config.hpp>
  11. #if defined(BOOST_NO_STDC_NAMESPACE)
  12. namespace std{
  13. using ::size_t;
  14. } // namespace std
  15. #endif
  16. #include <boost/mpi/datatype_fwd.hpp>
  17. #include <boost/mpi/exception.hpp>
  18. #include <boost/mpi/detail/antiques.hpp>
  19. #include <boost/throw_exception.hpp>
  20. #include <boost/assert.hpp>
  21. #include <boost/mpl/placeholders.hpp>
  22. #include <boost/serialization/array.hpp>
  23. #include <stdexcept>
  24. #include <iostream>
  25. #include <vector>
  26. #include <boost/mpi/detail/antiques.hpp>
  27. namespace boost { namespace mpi { namespace detail {
  28. /////////////////////////////////////////////////////////////////////////
  29. // class mpi_data_type_oprimitive - creation of custom MPI data types
  30. class mpi_datatype_primitive
  31. {
  32. public:
  33. // trivial default constructor
  34. mpi_datatype_primitive()
  35. : is_committed(false),
  36. origin(0)
  37. {}
  38. mpi_datatype_primitive(void const* orig)
  39. : is_committed(false),
  40. origin()
  41. {
  42. #if BOOST_MPI_VERSION >= 2
  43. BOOST_MPI_CHECK_RESULT(MPI_Get_address,(const_cast<void*>(orig), &origin));
  44. #else
  45. BOOST_MPI_CHECK_RESULT(MPI_Address,(const_cast<void*>(orig), &origin));
  46. #endif
  47. }
  48. void save_binary(void const *address, std::size_t count)
  49. {
  50. save_impl(address,MPI_BYTE,count);
  51. }
  52. // fast saving of arrays of MPI types
  53. template<class T>
  54. void save_array(serialization::array_wrapper<T> const& x, unsigned int /* version */)
  55. {
  56. if (x.count())
  57. save_impl(x.address(), boost::mpi::get_mpi_datatype(*x.address()), x.count());
  58. }
  59. typedef is_mpi_datatype<mpl::_1> use_array_optimization;
  60. // create and return the custom MPI data type
  61. MPI_Datatype get_mpi_datatype()
  62. {
  63. if (!is_committed)
  64. {
  65. #if BOOST_MPI_VERSION >= 2
  66. BOOST_MPI_CHECK_RESULT(MPI_Type_create_struct,
  67. (
  68. addresses.size(),
  69. c_data(lengths),
  70. c_data(addresses),
  71. c_data(types),
  72. &datatype_
  73. ));
  74. #else
  75. BOOST_MPI_CHECK_RESULT(MPI_Type_struct,
  76. (
  77. addresses.size(),
  78. c_data(lengths),
  79. c_data(addresses),
  80. c_data(types),
  81. &datatype_
  82. ));
  83. #endif
  84. BOOST_MPI_CHECK_RESULT(MPI_Type_commit,(&datatype_));
  85. is_committed = true;
  86. }
  87. return datatype_;
  88. }
  89. // default saving of primitives.
  90. template<class T>
  91. void save(const T & t)
  92. {
  93. save_impl(&t, boost::mpi::get_mpi_datatype(t), 1);
  94. }
  95. private:
  96. void save_impl(void const * p, MPI_Datatype t, int l)
  97. {
  98. BOOST_ASSERT ( !is_committed );
  99. // store address, type and length
  100. MPI_Aint a;
  101. #if BOOST_MPI_VERSION >= 2
  102. BOOST_MPI_CHECK_RESULT(MPI_Get_address,(const_cast<void*>(p), &a));
  103. #else
  104. BOOST_MPI_CHECK_RESULT(MPI_Address,(const_cast<void*>(p), &a));
  105. #endif
  106. addresses.push_back(a-origin);
  107. types.push_back(t);
  108. lengths.push_back(l);
  109. }
  110. template <class T>
  111. static T* get_data(std::vector<T>& v)
  112. {
  113. return v.empty() ? 0 : &(v[0]);
  114. }
  115. std::vector<MPI_Aint> addresses;
  116. std::vector<MPI_Datatype> types;
  117. std::vector<int> lengths;
  118. bool is_committed;
  119. MPI_Datatype datatype_;
  120. MPI_Aint origin;
  121. };
  122. } } } // end namespace boost::mpi::detail
  123. #endif // BOOST_MPI_DETAIL_MPI_DATATYPE_OPRIMITIVE_HPP