annotate DEPENDENCIES/generic/include/boost/mpi/collectives/all_to_all.hpp @ 125:34e428693f5d vext

Vext -> Repoint
author Chris Cannam
date Thu, 14 Jun 2018 11:15:39 +0100
parents 2665513ce2d3
children
rev   line source
Chris@16 1 // Copyright (C) 2005, 2006 Douglas Gregor.
Chris@16 2
Chris@16 3 // Use, modification and distribution is subject to the Boost Software
Chris@16 4 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
Chris@16 5 // http://www.boost.org/LICENSE_1_0.txt)
Chris@16 6
Chris@16 7 // Message Passing Interface 1.1 -- Section 4.8. All-to-all
Chris@16 8 #ifndef BOOST_MPI_ALL_TO_ALL_HPP
Chris@16 9 #define BOOST_MPI_ALL_TO_ALL_HPP
Chris@16 10
Chris@16 11 #include <boost/mpi/exception.hpp>
Chris@16 12 #include <boost/mpi/datatype.hpp>
Chris@16 13 #include <vector>
Chris@16 14 #include <boost/mpi/packed_oarchive.hpp>
Chris@16 15 #include <boost/mpi/packed_iarchive.hpp>
Chris@16 16 #include <boost/mpi/communicator.hpp>
Chris@16 17 #include <boost/mpi/environment.hpp>
Chris@16 18 #include <boost/assert.hpp>
Chris@16 19 #include <boost/mpi/collectives_fwd.hpp>
Chris@16 20 #include <boost/mpi/allocator.hpp>
Chris@16 21
Chris@16 22 namespace boost { namespace mpi {
Chris@16 23
Chris@16 24 namespace detail {
Chris@16 25 // We're performaing an all-to-all with a type that has an
Chris@16 26 // associated MPI datatype, so we'll use MPI_Alltoall to do all of
Chris@16 27 // the work.
Chris@16 28 template<typename T>
Chris@16 29 void
Chris@16 30 all_to_all_impl(const communicator& comm, const T* in_values, int n,
Chris@16 31 T* out_values, mpl::true_)
Chris@16 32 {
Chris@16 33 MPI_Datatype type = get_mpi_datatype<T>(*in_values);
Chris@16 34 BOOST_MPI_CHECK_RESULT(MPI_Alltoall,
Chris@16 35 (const_cast<T*>(in_values), n, type,
Chris@16 36 out_values, n, type, comm));
Chris@16 37 }
Chris@16 38
Chris@16 39 // We're performing an all-to-all with a type that does not have an
Chris@16 40 // associated MPI datatype, so we'll need to serialize
Chris@16 41 // it. Unfortunately, this means that we cannot use MPI_Alltoall, so
Chris@16 42 // we'll just have to send individual messages to the other
Chris@16 43 // processes.
Chris@16 44 template<typename T>
Chris@16 45 void
Chris@16 46 all_to_all_impl(const communicator& comm, const T* in_values, int n,
Chris@16 47 T* out_values, mpl::false_)
Chris@16 48 {
Chris@16 49 int size = comm.size();
Chris@16 50 int rank = comm.rank();
Chris@16 51
Chris@16 52 // The amount of data to be sent to each process
Chris@16 53 std::vector<int> send_sizes(size);
Chris@16 54
Chris@16 55 // The displacements for each outgoing value.
Chris@16 56 std::vector<int> send_disps(size);
Chris@16 57
Chris@16 58 // The buffer that will store all of the outgoing values
Chris@16 59 std::vector<char, allocator<char> > outgoing;
Chris@16 60
Chris@16 61 // Pack the buffer with all of the outgoing values.
Chris@16 62 for (int dest = 0; dest < size; ++dest) {
Chris@16 63 // Keep track of the displacements
Chris@16 64 send_disps[dest] = outgoing.size();
Chris@16 65
Chris@16 66 // Our own value will never be transmitted, so don't pack it.
Chris@16 67 if (dest != rank) {
Chris@16 68 packed_oarchive oa(comm, outgoing);
Chris@16 69 for (int i = 0; i < n; ++i)
Chris@16 70 oa << in_values[dest * n + i];
Chris@16 71 }
Chris@16 72
Chris@16 73 // Keep track of the sizes
Chris@16 74 send_sizes[dest] = outgoing.size() - send_disps[dest];
Chris@16 75 }
Chris@16 76
Chris@16 77 // Determine how much data each process will receive.
Chris@16 78 std::vector<int> recv_sizes(size);
Chris@16 79 all_to_all(comm, send_sizes, recv_sizes);
Chris@16 80
Chris@16 81 // Prepare a buffer to receive the incoming data.
Chris@16 82 std::vector<int> recv_disps(size);
Chris@16 83 int sum = 0;
Chris@16 84 for (int src = 0; src < size; ++src) {
Chris@16 85 recv_disps[src] = sum;
Chris@16 86 sum += recv_sizes[src];
Chris@16 87 }
Chris@16 88 std::vector<char, allocator<char> > incoming(sum > 0? sum : 1);
Chris@16 89
Chris@16 90 // Make sure we don't try to reference an empty vector
Chris@16 91 if (outgoing.empty())
Chris@16 92 outgoing.push_back(0);
Chris@16 93
Chris@16 94 // Transmit the actual data
Chris@16 95 BOOST_MPI_CHECK_RESULT(MPI_Alltoallv,
Chris@16 96 (&outgoing[0], &send_sizes[0],
Chris@16 97 &send_disps[0], MPI_PACKED,
Chris@16 98 &incoming[0], &recv_sizes[0],
Chris@16 99 &recv_disps[0], MPI_PACKED,
Chris@16 100 comm));
Chris@16 101
Chris@16 102 // Deserialize data from the iarchive
Chris@16 103 for (int src = 0; src < size; ++src) {
Chris@16 104 if (src == rank)
Chris@16 105 std::copy(in_values + src * n, in_values + (src + 1) * n,
Chris@16 106 out_values + src * n);
Chris@16 107 else {
Chris@16 108 packed_iarchive ia(comm, incoming, boost::archive::no_header,
Chris@16 109 recv_disps[src]);
Chris@16 110 for (int i = 0; i < n; ++i)
Chris@16 111 ia >> out_values[src * n + i];
Chris@16 112 }
Chris@16 113 }
Chris@16 114 }
Chris@16 115 } // end namespace detail
Chris@16 116
Chris@16 117 template<typename T>
Chris@16 118 inline void
Chris@16 119 all_to_all(const communicator& comm, const T* in_values, T* out_values)
Chris@16 120 {
Chris@16 121 detail::all_to_all_impl(comm, in_values, 1, out_values, is_mpi_datatype<T>());
Chris@16 122 }
Chris@16 123
Chris@16 124 template<typename T>
Chris@16 125 void
Chris@16 126 all_to_all(const communicator& comm, const std::vector<T>& in_values,
Chris@16 127 std::vector<T>& out_values)
Chris@16 128 {
Chris@16 129 BOOST_ASSERT((int)in_values.size() == comm.size());
Chris@16 130 out_values.resize(comm.size());
Chris@16 131 ::boost::mpi::all_to_all(comm, &in_values[0], &out_values[0]);
Chris@16 132 }
Chris@16 133
Chris@16 134 template<typename T>
Chris@16 135 inline void
Chris@16 136 all_to_all(const communicator& comm, const T* in_values, int n, T* out_values)
Chris@16 137 {
Chris@16 138 detail::all_to_all_impl(comm, in_values, n, out_values, is_mpi_datatype<T>());
Chris@16 139 }
Chris@16 140
Chris@16 141 template<typename T>
Chris@16 142 void
Chris@16 143 all_to_all(const communicator& comm, const std::vector<T>& in_values, int n,
Chris@16 144 std::vector<T>& out_values)
Chris@16 145 {
Chris@16 146 BOOST_ASSERT((int)in_values.size() == comm.size() * n);
Chris@16 147 out_values.resize(comm.size() * n);
Chris@16 148 ::boost::mpi::all_to_all(comm, &in_values[0], n, &out_values[0]);
Chris@16 149 }
Chris@16 150
Chris@16 151 } } // end namespace boost::mpi
Chris@16 152
Chris@16 153 #endif // BOOST_MPI_ALL_TO_ALL_HPP