summaryrefslogtreecommitdiff
path: root/libs/mpi/src/broadcast.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libs/mpi/src/broadcast.cpp')
-rw-r--r--libs/mpi/src/broadcast.cpp151
1 files changed, 151 insertions, 0 deletions
diff --git a/libs/mpi/src/broadcast.cpp b/libs/mpi/src/broadcast.cpp
new file mode 100644
index 000000000..2b807774d
--- /dev/null
+++ b/libs/mpi/src/broadcast.cpp
@@ -0,0 +1,151 @@
+// Copyright 2005 Douglas Gregor.
+
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// Message Passing Interface 1.1 -- Section 4.4. Broadcast
+
+#include <boost/mpi/collectives/broadcast.hpp>
+#include <boost/mpi/skeleton_and_content.hpp>
+#include <boost/mpi/detail/point_to_point.hpp>
+#include <boost/mpi/environment.hpp>
+
+namespace boost { namespace mpi {
+
+template<>
+void
+broadcast<const packed_oarchive>(const communicator& comm,
+ const packed_oarchive& oa,
+ int root)
+{
+ // Only the root can broadcast the packed_oarchive
+ assert(comm.rank() == root);
+
+ int size = comm.size();
+ if (size < 2) return;
+
+ // Determine maximum tag value
+ int tag = environment::collectives_tag();
+
+ // Broadcast data to all nodes
+ std::vector<MPI_Request> requests(size * 2);
+ int num_requests = 0;
+ for (int dest = 0; dest < size; ++dest) {
+ if (dest != root) {
+ // Build up send requests for each child send.
+ num_requests += detail::packed_archive_isend(comm, dest, tag, oa,
+ &requests[num_requests], 2);
+ }
+ }
+
+ // Complete all of the sends
+ BOOST_MPI_CHECK_RESULT(MPI_Waitall,
+ (num_requests, &requests[0], MPI_STATUSES_IGNORE));
+}
+
+template<>
+void
+broadcast<packed_oarchive>(const communicator& comm, packed_oarchive& oa,
+ int root)
+{
+ broadcast(comm, const_cast<const packed_oarchive&>(oa), root);
+}
+
+template<>
+void
+broadcast<packed_iarchive>(const communicator& comm, packed_iarchive& ia,
+ int root)
+{
+ int size = comm.size();
+ if (size < 2) return;
+
+ // Determine maximum tag value
+ int tag = environment::collectives_tag();
+
+ // Receive data from the root.
+ if (comm.rank() != root) {
+ MPI_Status status;
+ detail::packed_archive_recv(comm, root, tag, ia, status);
+ } else {
+ // Broadcast data to all nodes
+ std::vector<MPI_Request> requests(size * 2);
+ int num_requests = 0;
+ for (int dest = 0; dest < size; ++dest) {
+ if (dest != root) {
+ // Build up send requests for each child send.
+ num_requests += detail::packed_archive_isend(comm, dest, tag, ia,
+ &requests[num_requests],
+ 2);
+ }
+ }
+
+ // Complete all of the sends
+ BOOST_MPI_CHECK_RESULT(MPI_Waitall,
+ (num_requests, &requests[0], MPI_STATUSES_IGNORE));
+ }
+}
+
+template<>
+void
+broadcast<const packed_skeleton_oarchive>(const communicator& comm,
+ const packed_skeleton_oarchive& oa,
+ int root)
+{
+ broadcast(comm, oa.get_skeleton(), root);
+}
+
+template<>
+void
+broadcast<packed_skeleton_oarchive>(const communicator& comm,
+ packed_skeleton_oarchive& oa, int root)
+{
+ broadcast(comm, oa.get_skeleton(), root);
+}
+
+template<>
+void
+broadcast<packed_skeleton_iarchive>(const communicator& comm,
+ packed_skeleton_iarchive& ia, int root)
+{
+ broadcast(comm, ia.get_skeleton(), root);
+}
+
+template<>
+void broadcast<content>(const communicator& comm, content& c, int root)
+{
+ broadcast(comm, const_cast<const content&>(c), root);
+}
+
+template<>
+void broadcast<const content>(const communicator& comm, const content& c,
+ int root)
+{
+#ifdef LAM_MPI
+ if (comm.size() < 2)
+ return;
+
+ // Some versions of LAM/MPI behave badly when broadcasting using
+ // MPI_BOTTOM, so we'll instead use manual send/recv operations.
+ if (comm.rank() == root) {
+ for (int p = 0; p < comm.size(); ++p) {
+ if (p != root) {
+ BOOST_MPI_CHECK_RESULT(MPI_Send,
+ (MPI_BOTTOM, 1, c.get_mpi_datatype(),
+ p, environment::collectives_tag(), comm));
+ }
+ }
+ } else {
+ BOOST_MPI_CHECK_RESULT(MPI_Recv,
+ (MPI_BOTTOM, 1, c.get_mpi_datatype(),
+ root, environment::collectives_tag(),
+ comm, MPI_STATUS_IGNORE));
+ }
+#else
+ BOOST_MPI_CHECK_RESULT(MPI_Bcast,
+ (MPI_BOTTOM, 1, c.get_mpi_datatype(),
+ root, comm));
+#endif
+}
+
+} } // end namespace boost::mpi