1 // Copyright 2005 Douglas Gregor.
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
9 #include <boost/mpi/config.hpp>
10 #include <boost/mpi/collectives/broadcast.hpp>
11 #include <boost/mpi/skeleton_and_content.hpp>
12 #include <boost/mpi/detail/point_to_point.hpp>
13 #include <boost/mpi/environment.hpp>
14 #include <cassert>
15
16 namespace boost { namespace mpi {
17
18 template<>
19 void
broadcast(const communicator & comm,const packed_oarchive & oa,int root)20 broadcast<const packed_oarchive>(const communicator& comm,
21 const packed_oarchive& oa,
22 int root)
23 {
24 // Only the root can broadcast the packed_oarchive
25 assert(comm.rank() == root);
26
27 int size = comm.size();
28 if (size < 2) return;
29
30 // Determine maximum tag value
31 int tag = environment::collectives_tag();
32
33 // Broadcast data to all nodes
34 std::vector<request> requests(size-1);
35 std::vector<request>::iterator it = requests.begin();
36 for (int dest = 0; dest < size; ++dest) {
37 if (dest != root) {
38 *it++ = detail::packed_archive_isend(comm, dest, tag, oa);
39 }
40 }
41 wait_all(requests.begin(), requests.end());
42 }
43
44 template<>
45 void
broadcast(const communicator & comm,packed_oarchive & oa,int root)46 broadcast<packed_oarchive>(const communicator& comm, packed_oarchive& oa,
47 int root)
48 {
49 broadcast(comm, const_cast<const packed_oarchive&>(oa), root);
50 }
51
52 template<>
53 void
broadcast(const communicator & comm,packed_iarchive & ia,int root)54 broadcast<packed_iarchive>(const communicator& comm, packed_iarchive& ia,
55 int root)
56 {
57 int size = comm.size();
58 if (size < 2) return;
59
60 // Determine maximum tag value
61 int tag = environment::collectives_tag();
62
63 // Receive data from the root.
64 if (comm.rank() != root) {
65 MPI_Status status;
66 detail::packed_archive_recv(comm, root, tag, ia, status);
67 } else {
68 // Broadcast data to all nodes
69 std::vector<request> requests(size-1);
70 std::vector<request>::iterator it = requests.begin();
71 for (int dest = 0; dest < size; ++dest) {
72 if (dest != root) {
73 *it++ = detail::packed_archive_isend(comm, dest, tag, ia);
74 }
75 }
76 wait_all(requests.begin(), requests.end());
77 }
78 }
79
80 template<>
81 void
broadcast(const communicator & comm,const packed_skeleton_oarchive & oa,int root)82 broadcast<const packed_skeleton_oarchive>(const communicator& comm,
83 const packed_skeleton_oarchive& oa,
84 int root)
85 {
86 broadcast(comm, oa.get_skeleton(), root);
87 }
88
89 template<>
90 void
broadcast(const communicator & comm,packed_skeleton_oarchive & oa,int root)91 broadcast<packed_skeleton_oarchive>(const communicator& comm,
92 packed_skeleton_oarchive& oa, int root)
93 {
94 broadcast(comm, oa.get_skeleton(), root);
95 }
96
97 template<>
98 void
broadcast(const communicator & comm,packed_skeleton_iarchive & ia,int root)99 broadcast<packed_skeleton_iarchive>(const communicator& comm,
100 packed_skeleton_iarchive& ia, int root)
101 {
102 broadcast(comm, ia.get_skeleton(), root);
103 }
104
105 template<>
broadcast(const communicator & comm,content & c,int root)106 void broadcast<content>(const communicator& comm, content& c, int root)
107 {
108 broadcast(comm, const_cast<const content&>(c), root);
109 }
110
111 template<>
broadcast(const communicator & comm,const content & c,int root)112 void broadcast<const content>(const communicator& comm, const content& c,
113 int root)
114 {
115 #if defined(BOOST_MPI_BCAST_BOTTOM_WORKS_FINE)
116 BOOST_MPI_CHECK_RESULT(MPI_Bcast,
117 (MPI_BOTTOM, 1, c.get_mpi_datatype(),
118 root, comm));
119 #else
120 if (comm.size() < 2)
121 return;
122
123 // Some versions of LAM/MPI behave badly when broadcasting using
124 // MPI_BOTTOM, so we'll instead use manual send/recv operations.
125 if (comm.rank() == root) {
126 for (int p = 0; p < comm.size(); ++p) {
127 if (p != root) {
128 BOOST_MPI_CHECK_RESULT(MPI_Send,
129 (MPI_BOTTOM, 1, c.get_mpi_datatype(),
130 p, environment::collectives_tag(), comm));
131 }
132 }
133 } else {
134 BOOST_MPI_CHECK_RESULT(MPI_Recv,
135 (MPI_BOTTOM, 1, c.get_mpi_datatype(),
136 root, environment::collectives_tag(),
137 comm, MPI_STATUS_IGNORE));
138 }
139 #endif
140 }
141
142 } } // end namespace boost::mpi
143