File indexing completed on 2025-01-18 09:40:56
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef BOOST_MPI_ALLGATHER_HPP
0009 #define BOOST_MPI_ALLGATHER_HPP
0010
0011 #include <cassert>
0012 #include <cstddef>
0013 #include <numeric>
0014 #include <boost/mpi/exception.hpp>
0015 #include <boost/mpi/datatype.hpp>
0016 #include <vector>
0017 #include <boost/mpi/packed_oarchive.hpp>
0018 #include <boost/mpi/packed_iarchive.hpp>
0019 #include <boost/mpi/detail/point_to_point.hpp>
0020 #include <boost/mpi/communicator.hpp>
0021 #include <boost/mpi/environment.hpp>
0022 #include <boost/mpi/detail/offsets.hpp>
0023 #include <boost/mpi/detail/antiques.hpp>
0024 #include <boost/assert.hpp>
0025
0026 namespace boost { namespace mpi {
0027
0028 namespace detail {
0029
0030
0031 template<typename T>
0032 void
0033 all_gather_impl(const communicator& comm, const T* in_values, int n,
0034 T* out_values, mpl::true_)
0035 {
0036 MPI_Datatype type = get_mpi_datatype<T>(*in_values);
0037 BOOST_MPI_CHECK_RESULT(MPI_Allgather,
0038 (const_cast<T*>(in_values), n, type,
0039 out_values, n, type, comm));
0040 }
0041
0042
0043
0044
0045 template<typename T>
0046 void
0047 all_gather_impl(const communicator& comm, const T* in_values, int n,
0048 T* out_values, int const* sizes, int const* skips, mpl::false_)
0049 {
0050 int nproc = comm.size();
0051
0052
0053 packed_oarchive oa(comm);
0054 for (int i = 0; i < n; ++i) {
0055 oa << in_values[i];
0056 }
0057 std::vector<int> oasizes(nproc);
0058 int oasize = oa.size();
0059 BOOST_MPI_CHECK_RESULT(MPI_Allgather,
0060 (&oasize, 1, MPI_INT,
0061 c_data(oasizes), 1, MPI_INT,
0062 MPI_Comm(comm)));
0063
0064
0065
0066
0067 std::vector<int> offsets(nproc);
0068 sizes2offsets(oasizes, offsets);
0069 packed_iarchive::buffer_type recv_buffer(std::accumulate(oasizes.begin(), oasizes.end(), 0));
0070 BOOST_MPI_CHECK_RESULT(MPI_Allgatherv,
0071 (const_cast<void*>(oa.address()), int(oa.size()), MPI_BYTE,
0072 c_data(recv_buffer), c_data(oasizes), c_data(offsets), MPI_BYTE,
0073 MPI_Comm(comm)));
0074 for (int src = 0; src < nproc; ++src) {
0075 int nb = sizes ? sizes[src] : n;
0076 int skip = skips ? skips[src] : 0;
0077 std::advance(out_values, skip);
0078 if (src == comm.rank()) {
0079 for (int i = 0; i < nb; ++i) {
0080 *out_values++ = *in_values++;
0081 }
0082 } else {
0083 packed_iarchive ia(comm, recv_buffer, boost::archive::no_header, offsets[src]);
0084 for (int i = 0; i < nb; ++i) {
0085 ia >> *out_values++;
0086 }
0087 }
0088 }
0089 }
0090
0091
0092
0093
0094 template<typename T>
0095 void
0096 all_gather_impl(const communicator& comm, const T* in_values, int n,
0097 T* out_values, mpl::false_ isnt_mpi_type)
0098 {
0099 all_gather_impl(comm, in_values, n, out_values, (int const*)0, (int const*)0, isnt_mpi_type);
0100 }
0101 }
0102
0103 template<typename T>
0104 void
0105 all_gather(const communicator& comm, const T& in_value, T* out_values)
0106 {
0107 detail::all_gather_impl(comm, &in_value, 1, out_values, is_mpi_datatype<T>());
0108 }
0109
0110 template<typename T>
0111 void
0112 all_gather(const communicator& comm, const T& in_value, std::vector<T>& out_values)
0113 {
0114 using detail::c_data;
0115 out_values.resize(comm.size());
0116 ::boost::mpi::all_gather(comm, in_value, c_data(out_values));
0117 }
0118
0119 template<typename T>
0120 void
0121 all_gather(const communicator& comm, const T* in_values, int n, T* out_values)
0122 {
0123 detail::all_gather_impl(comm, in_values, n, out_values, is_mpi_datatype<T>());
0124 }
0125
0126 template<typename T>
0127 void
0128 all_gather(const communicator& comm, const T* in_values, int n, std::vector<T>& out_values)
0129 {
0130 using detail::c_data;
0131 out_values.resize(comm.size() * n);
0132 ::boost::mpi::all_gather(comm, in_values, n, c_data(out_values));
0133 }
0134
0135 } }
0136
0137 #endif