broadcast.hpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. // Copyright (C) 2005, 2006 Douglas Gregor <doug.gregor -at- gmail.com>.
  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. // Message Passing Interface 1.1 -- Section 4.4. Broadcast
  6. #ifndef BOOST_MPI_BROADCAST_HPP
  7. #define BOOST_MPI_BROADCAST_HPP
  8. #include <boost/mpi/collectives_fwd.hpp>
  9. #include <boost/mpi/exception.hpp>
  10. #include <boost/mpi/datatype.hpp>
  11. #include <boost/mpi/communicator.hpp>
  12. namespace boost { namespace mpi {
  13. /************************************************************************
  14. * Specializations *
  15. ************************************************************************/
  16. /**
  17. * INTERNAL ONLY
  18. */
  19. template<>
  20. BOOST_MPI_DECL void
  21. broadcast<const packed_oarchive>(const communicator& comm,
  22. const packed_oarchive& oa,
  23. int root);
  24. /**
  25. * INTERNAL ONLY
  26. */
  27. template<>
  28. BOOST_MPI_DECL void
  29. broadcast<packed_oarchive>(const communicator& comm, packed_oarchive& oa,
  30. int root);
  31. /**
  32. * INTERNAL ONLY
  33. */
  34. template<>
  35. BOOST_MPI_DECL void
  36. broadcast<packed_iarchive>(const communicator& comm, packed_iarchive& ia,
  37. int root);
  38. /**
  39. * INTERNAL ONLY
  40. */
  41. template<>
  42. BOOST_MPI_DECL void
  43. broadcast<const packed_skeleton_oarchive>(const communicator& comm,
  44. const packed_skeleton_oarchive& oa,
  45. int root);
  46. /**
  47. * INTERNAL ONLY
  48. */
  49. template<>
  50. void
  51. broadcast<packed_skeleton_oarchive>(const communicator& comm,
  52. packed_skeleton_oarchive& oa, int root);
  53. /**
  54. * INTERNAL ONLY
  55. */
  56. template<>
  57. void
  58. broadcast<packed_skeleton_iarchive>(const communicator& comm,
  59. packed_skeleton_iarchive& ia, int root);
  60. /**
  61. * INTERNAL ONLY
  62. */
  63. template<>
  64. void broadcast<content>(const communicator& comm, content& c, int root);
  65. /**
  66. * INTERNAL ONLY
  67. */
  68. template<>
  69. void broadcast<const content>(const communicator& comm, const content& c,
  70. int root);
  71. /************************************************************************
  72. * broadcast() implementation *
  73. ************************************************************************/
  74. namespace detail {
  75. // We're sending a type that has an associated MPI datatype, so
  76. // we'll use MPI_Bcast to do all of the work.
  77. template<typename T>
  78. void
  79. broadcast_impl(const communicator& comm, T* values, int n, int root,
  80. mpl::true_)
  81. {
  82. BOOST_MPI_CHECK_RESULT(MPI_Bcast,
  83. (values, n,
  84. boost::mpi::get_mpi_datatype<T>(*values),
  85. root, MPI_Comm(comm)));
  86. }
  87. // We're sending a type that does not have an associated MPI
  88. // datatype, so we'll need to serialize it.
  89. template<typename T>
  90. void
  91. broadcast_impl(const communicator& comm, T* values, int n, int root,
  92. mpl::false_ non_mpi_datatype)
  93. {
  94. // Implementation proposed by Lorenz Hübschle-Schneider
  95. if (comm.rank() == root) {
  96. packed_oarchive oa(comm);
  97. for (int i = 0; i < n; ++i) {
  98. oa << values[i];
  99. }
  100. std::size_t asize = oa.size();
  101. broadcast(comm, asize, root);
  102. void const* aptr = oa.address();
  103. BOOST_MPI_CHECK_RESULT(MPI_Bcast,
  104. (const_cast<void*>(aptr), asize,
  105. MPI_BYTE,
  106. root, MPI_Comm(comm)));
  107. } else {
  108. packed_iarchive ia(comm);
  109. std::size_t asize;
  110. broadcast(comm, asize, root);
  111. ia.resize(asize);
  112. void* aptr = ia.address();
  113. BOOST_MPI_CHECK_RESULT(MPI_Bcast,
  114. (aptr, asize,
  115. MPI_BYTE,
  116. root, MPI_Comm(comm)));
  117. for (int i = 0; i < n; ++i)
  118. ia >> values[i];
  119. }
  120. }
  121. } // end namespace detail
  122. template<typename T>
  123. void broadcast(const communicator& comm, T& value, int root)
  124. {
  125. detail::broadcast_impl(comm, &value, 1, root, is_mpi_datatype<T>());
  126. }
  127. template<typename T>
  128. void broadcast(const communicator& comm, T* values, int n, int root)
  129. {
  130. detail::broadcast_impl(comm, values, n, root, is_mpi_datatype<T>());
  131. }
  132. } } // end namespace boost::mpi
  133. // If the user has already included skeleton_and_content.hpp, include
  134. // the code to broadcast skeletons and content.
  135. #ifdef BOOST_MPI_SKELETON_AND_CONTENT_HPP
  136. # include <boost/mpi/detail/broadcast_sc.hpp>
  137. #endif
  138. #endif // BOOST_MPI_BROADCAST_HPP