• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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