mirror of
https://github.com/saitohirga/WSJT-X.git
synced 2025-05-25 10:52:31 -04:00
154 lines
4.5 KiB
C++
154 lines
4.5 KiB
C++
// 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/config.hpp>
|
|
#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>
|
|
#include <cassert>
|
|
|
|
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)
|
|
{
|
|
#if defined(BOOST_MPI_BCAST_BOTTOM_WORKS_FINE)
|
|
BOOST_MPI_CHECK_RESULT(MPI_Bcast,
|
|
(MPI_BOTTOM, 1, c.get_mpi_datatype(),
|
|
root, comm));
|
|
#else
|
|
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));
|
|
}
|
|
#endif
|
|
}
|
|
|
|
} } // end namespace boost::mpi
|