]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 | |
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 | |
92f5a8d4 TL |
34 | std::vector<request> requests(size-1); |
35 | std::vector<request>::iterator it = requests.begin(); | |
7c673cae FG |
36 | for (int dest = 0; dest < size; ++dest) { |
37 | if (dest != root) { | |
92f5a8d4 | 38 | *it++ = detail::packed_archive_isend(comm, dest, tag, oa); |
7c673cae FG |
39 | } |
40 | } | |
92f5a8d4 | 41 | wait_all(requests.begin(), requests.end()); |
7c673cae FG |
42 | } |
43 | ||
44 | template<> | |
45 | void | |
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 | |
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 | |
92f5a8d4 TL |
69 | std::vector<request> requests(size-1); |
70 | std::vector<request>::iterator it = requests.begin(); | |
7c673cae FG |
71 | for (int dest = 0; dest < size; ++dest) { |
72 | if (dest != root) { | |
92f5a8d4 | 73 | *it++ = detail::packed_archive_isend(comm, dest, tag, ia); |
7c673cae FG |
74 | } |
75 | } | |
92f5a8d4 | 76 | wait_all(requests.begin(), requests.end()); |
7c673cae FG |
77 | } |
78 | } | |
79 | ||
80 | template<> | |
81 | void | |
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 | |
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 | |
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<> | |
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<> | |
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 |