Back to home page

EIC code displayed by LXR

 
 

    


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

0001 // Copyright (C) 2011 JĂșlio Hoffimann.
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.6. Scatterv
0008 #ifndef BOOST_MPI_SCATTERV_HPP
0009 #define BOOST_MPI_SCATTERV_HPP
0010 
0011 #include <boost/scoped_array.hpp>
0012 #include <boost/mpi/collectives/scatter.hpp>
0013 #include <boost/mpi/detail/offsets.hpp>
0014 #include <boost/mpi/detail/antiques.hpp>
0015 
0016 namespace boost { namespace mpi {
0017 
0018 namespace detail {
0019 
0020 //////////////////////////////////////////////
0021 /// Implementation for MPI primitive types ///
0022 //////////////////////////////////////////////
0023 
0024 // We're scattering from the root for a type that has an associated MPI
0025 // datatype, so we'll use MPI_Scatterv to do all of the work.
0026 template<typename T>
0027 void
0028 scatterv_impl(const communicator& comm, const T* in_values, T* out_values, int out_size,
0029               const int* sizes, const int* displs, int root, mpl::true_)
0030 {
0031   assert(!sizes || out_size == sizes[comm.rank()]);
0032   assert(!bool(in_values) || bool(sizes));
0033   
0034   scoped_array<int> new_offsets_mem(make_offsets(comm, sizes, displs, root));
0035   if (new_offsets_mem) displs = new_offsets_mem.get();
0036   MPI_Datatype type = get_mpi_datatype<T>(*in_values);
0037   BOOST_MPI_CHECK_RESULT(MPI_Scatterv,
0038                          (const_cast<T*>(in_values), const_cast<int*>(sizes),
0039                           const_cast<int*>(displs), type,
0040                           out_values, out_size, type, root, comm));
0041 }
0042 
0043 // We're scattering from a non-root for a type that has an associated MPI
0044 // datatype, so we'll use MPI_Scatterv to do all of the work.
0045 template<typename T>
0046 void
0047 scatterv_impl(const communicator& comm, T* out_values, int out_size, int root, 
0048               mpl::true_ is_mpi_type)
0049 {
0050   scatterv_impl(comm, (T const*)0, out_values, out_size, 
0051                 (const int*)0, (const int*)0, root, is_mpi_type);
0052 }
0053 
0054 //////////////////////////////////////////////////
0055 /// Implementation for non MPI primitive types ///
0056 //////////////////////////////////////////////////
0057 
0058 // We're scattering from the root for a type that does not have an
0059 // associated MPI datatype, so we'll need to serialize it.
0060 template<typename T>
0061 void
0062 scatterv_impl(const communicator& comm, const T* in_values, T* out_values, int out_size,
0063               int const* sizes, int const* displs, int root, mpl::false_)
0064 {
0065   packed_oarchive::buffer_type sendbuf;
0066   bool is_root = comm.rank() == root;
0067   int nproc = comm.size();
0068   std::vector<int> archsizes;
0069   if (is_root) {
0070     assert(out_size == sizes[comm.rank()]);
0071     archsizes.resize(nproc);
0072     std::vector<int> skipped;
0073     if (displs) {
0074       skipped.resize(nproc);
0075       offsets2skipped(sizes, displs, c_data(skipped), nproc);
0076       displs = c_data(skipped);
0077     }
0078     fill_scatter_sendbuf(comm, in_values, sizes, (int const*)0, sendbuf, archsizes);
0079   }
0080   dispatch_scatter_sendbuf(comm, sendbuf, archsizes, (T const*)0, out_values, out_size, root);
0081 }
0082 
0083 // We're scattering to a non-root for a type that does not have an
0084 // associated MPI datatype. input data not needed.
0085 // it.
0086 template<typename T>
0087 void
0088 scatterv_impl(const communicator& comm, T* out_values, int n, int root, 
0089               mpl::false_ isnt_mpi_type)
0090 {
0091   assert(root != comm.rank());
0092   scatterv_impl(comm, (T const*)0, out_values, n, (int const*)0, (int const*)0, root, isnt_mpi_type);
0093 }
0094 
0095 } // end namespace detail
0096 
0097 template<typename T>
0098 void
0099 scatterv(const communicator& comm, const T* in_values,
0100          const std::vector<int>& sizes, const std::vector<int>& displs,
0101          T* out_values, int out_size, int root)
0102 {
0103   using detail::c_data;
0104   detail::scatterv_impl(comm, in_values, out_values, out_size, c_data(sizes), c_data(displs), 
0105                 root, is_mpi_datatype<T>());
0106 }
0107 
0108 template<typename T>
0109 void
0110 scatterv(const communicator& comm, const std::vector<T>& in_values, 
0111          const std::vector<int>& sizes, const std::vector<int>& displs,
0112          T* out_values, int out_size, int root)
0113 {
0114   using detail::c_data;
0115   ::boost::mpi::scatterv(comm, c_data(in_values), sizes, displs,
0116                          out_values, out_size, root);
0117 }
0118 
0119 template<typename T>
0120 void scatterv(const communicator& comm, T* out_values, int out_size, int root)
0121 {
0122   BOOST_ASSERT(comm.rank() != root);
0123   detail::scatterv_impl(comm, out_values, out_size, root, is_mpi_datatype<T>());
0124 }
0125 
0126 ///////////////////////
0127 // common use versions
0128 ///////////////////////
0129 template<typename T>
0130 void
0131 scatterv(const communicator& comm, const T* in_values,
0132          const std::vector<int>& sizes, T* out_values, int root)
0133 {
0134   using detail::c_data;
0135   detail::scatterv_impl(comm, in_values, out_values, sizes[comm.rank()], 
0136                         c_data(sizes), (int const*)0,
0137                         root, is_mpi_datatype<T>());
0138 }
0139 
0140 template<typename T>
0141 void
0142 scatterv(const communicator& comm, const std::vector<T>& in_values,
0143          const std::vector<int>& sizes, T* out_values, int root)
0144 {
0145   ::boost::mpi::scatterv(comm, detail::c_data(in_values), sizes, out_values, root);
0146 }
0147 
0148 template<typename T>
0149 void
0150 scatterv(const communicator& comm, const T* in_values,
0151          T* out_values, int n, int root)
0152 {
0153   detail::scatterv_impl(comm, in_values, out_values, n, (int const*)0, (int const*)0,
0154                 root, is_mpi_datatype<T>());
0155 }
0156 
0157 template<typename T>
0158 void
0159 scatterv(const communicator& comm, const std::vector<T>& in_values,
0160          T* out_values, int out_size, int root)
0161 {
0162   ::boost::mpi::scatterv(comm, detail::c_data(in_values), out_values, out_size, root);
0163 }
0164 
0165 } } // end namespace boost::mpi
0166 
0167 #endif // BOOST_MPI_SCATTERV_HPP