diff options
Diffstat (limited to 'libs/mpi/src/broadcast.cpp')
-rw-r--r-- | libs/mpi/src/broadcast.cpp | 151 |
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 |