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