Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:40:56

0001 // Copyright (C) 2005, 2006 Douglas Gregor.
0002 
0003 // Use, modification and distribution is subject to the Boost Software
0004 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
0005 // http://www.boost.org/LICENSE_1_0.txt)
0006 
0007 // Message Passing Interface 1.1 -- Section 4.5. Gather
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 // We're all-gathering for a type that has an associated MPI
0030 // datatype, so we'll use MPI_Gather to do all of the work.
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 // We're all-gathering for a type that does not have an
0043 // associated MPI datatype, so we'll need to serialize
0044 // it.
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   // first, gather all size, these size can be different for
0052   // each process
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   // Gather the archives, which can be of different sizes, so
0064   // we need to use allgatherv.
0065   // Every thing is contiguous, so the offsets can be
0066   // deduced from the collected sizes.
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()) { // this is our local data
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 // We're all-gathering for a type that does not have an
0092 // associated MPI datatype, so we'll need to serialize
0093 // it.
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 } // end namespace detail
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 } } // end namespace boost::mpi
0136 
0137 #endif // BOOST_MPI_ALL_GATHER_HPP