]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/mpi/collectives/scatter.hpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / boost / mpi / collectives / scatter.hpp
CommitLineData
7c673cae
FG
1// Copyright (C) 2005, 2006 Douglas Gregor.
2
3// Use, modification and distribution is subject to the Boost Software
4// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
5// http://www.boost.org/LICENSE_1_0.txt)
6
7// Message Passing Interface 1.1 -- Section 4.6. Scatter
8#ifndef BOOST_MPI_SCATTER_HPP
9#define BOOST_MPI_SCATTER_HPP
10
11#include <boost/mpi/exception.hpp>
12#include <boost/mpi/datatype.hpp>
13#include <vector>
14#include <boost/mpi/packed_oarchive.hpp>
15#include <boost/mpi/packed_iarchive.hpp>
16#include <boost/mpi/detail/point_to_point.hpp>
17#include <boost/mpi/communicator.hpp>
18#include <boost/mpi/environment.hpp>
11fdf7f2
TL
19#include <boost/mpi/detail/offsets.hpp>
20#include <boost/mpi/detail/antiques.hpp>
7c673cae
FG
21#include <boost/assert.hpp>
22
23namespace boost { namespace mpi {
24
25namespace detail {
11fdf7f2
TL
26// We're scattering from the root for a type that has an associated MPI
27// datatype, so we'll use MPI_Scatter to do all of the work.
28template<typename T>
29void
30scatter_impl(const communicator& comm, const T* in_values, T* out_values,
31 int n, int root, mpl::true_)
32{
33 MPI_Datatype type = get_mpi_datatype<T>(*in_values);
34 BOOST_MPI_CHECK_RESULT(MPI_Scatter,
35 (const_cast<T*>(in_values), n, type,
36 out_values, n, type, root, comm));
37}
7c673cae 38
11fdf7f2
TL
39// We're scattering from a non-root for a type that has an associated MPI
40// datatype, so we'll use MPI_Scatter to do all of the work.
41template<typename T>
42void
43scatter_impl(const communicator& comm, T* out_values, int n, int root,
44 mpl::true_)
45{
46 MPI_Datatype type = get_mpi_datatype<T>(*out_values);
47 BOOST_MPI_CHECK_RESULT(MPI_Scatter,
48 (0, n, type,
49 out_values, n, type,
50 root, comm));
51}
52
53// Fill the sendbuf while keeping trac of the slot's footprints
54// Used in the first steps of both scatter and scatterv
55// Nslots contains the number of slots being sent
56// to each process (identical values for scatter).
57// skiped_slots, if present, is deduced from the
58// displacement array authorised be the MPI API,
59// for some yet to be determined reason.
60template<typename T>
61void
62fill_scatter_sendbuf(const communicator& comm, T const* values,
63 int const* nslots, int const* skipped_slots,
64 packed_oarchive::buffer_type& sendbuf, std::vector<int>& archsizes) {
65 int nproc = comm.size();
66 archsizes.resize(nproc);
67
68 for (int dest = 0; dest < nproc; ++dest) {
69 if (skipped_slots) { // wee need to keep this for backward compatibility
70 for(int k= 0; k < skipped_slots[dest]; ++k) ++values;
71 }
72 packed_oarchive procarchive(comm);
73 for (int i = 0; i < nslots[dest]; ++i) {
74 procarchive << *values++;
75 }
76 int archsize = procarchive.size();
77 sendbuf.resize(sendbuf.size() + archsize);
78 archsizes[dest] = archsize;
79 char const* aptr = static_cast<char const*>(procarchive.address());
80 std::copy(aptr, aptr+archsize, sendbuf.end()-archsize);
7c673cae 81 }
11fdf7f2 82}
7c673cae 83
11fdf7f2
TL
84template<typename T, class A>
85T*
86non_const_data(std::vector<T,A> const& v) {
87 using detail::c_data;
88 return const_cast<T*>(c_data(v));
89}
90
91// Dispatch the sendbuf among proc.
92// Used in the second steps of both scatter and scatterv
93// in_value is only provide in the non variadic case.
94template<typename T>
95void
96dispatch_scatter_sendbuf(const communicator& comm,
97 packed_oarchive::buffer_type const& sendbuf, std::vector<int> const& archsizes,
98 T const* in_values,
99 T* out_values, int n, int root) {
100 // Distribute the sizes
101 int myarchsize;
102 BOOST_MPI_CHECK_RESULT(MPI_Scatter,
92f5a8d4
TL
103 (non_const_data(archsizes), 1, MPI_INT,
104 &myarchsize, 1, MPI_INT, root, comm));
11fdf7f2
TL
105 std::vector<int> offsets;
106 if (root == comm.rank()) {
107 sizes2offsets(archsizes, offsets);
108 }
109 // Get my proc archive
110 packed_iarchive::buffer_type recvbuf;
111 recvbuf.resize(myarchsize);
112 BOOST_MPI_CHECK_RESULT(MPI_Scatterv,
113 (non_const_data(sendbuf), non_const_data(archsizes), c_data(offsets), MPI_BYTE,
114 c_data(recvbuf), recvbuf.size(), MPI_BYTE,
115 root, MPI_Comm(comm)));
116 // Unserialize
117 if ( in_values != 0 && root == comm.rank()) {
118 // Our own local values are already here: just copy them.
119 std::copy(in_values + root * n, in_values + (root + 1) * n, out_values);
120 } else {
121 // Otherwise deserialize:
122 packed_iarchive iarchv(comm, recvbuf);
123 for (int i = 0; i < n; ++i) {
124 iarchv >> out_values[i];
7c673cae
FG
125 }
126 }
11fdf7f2 127}
7c673cae 128
11fdf7f2
TL
129// We're scattering from the root for a type that does not have an
130// associated MPI datatype, so we'll need to serialize it.
131template<typename T>
132void
133scatter_impl(const communicator& comm, const T* in_values, T* out_values,
134 int n, int root, mpl::false_)
135{
136 packed_oarchive::buffer_type sendbuf;
137 std::vector<int> archsizes;
138
139 if (root == comm.rank()) {
140 std::vector<int> nslots(comm.size(), n);
141 fill_scatter_sendbuf(comm, in_values, c_data(nslots), (int const*)0, sendbuf, archsizes);
7c673cae 142 }
11fdf7f2
TL
143 dispatch_scatter_sendbuf(comm, sendbuf, archsizes, in_values, out_values, n, root);
144}
145
146template<typename T>
147void
148scatter_impl(const communicator& comm, T* out_values, int n, int root,
149 mpl::false_ is_mpi_type)
150{
151 scatter_impl(comm, (T const*)0, out_values, n, root, is_mpi_type);
152}
7c673cae
FG
153} // end namespace detail
154
155template<typename T>
156void
157scatter(const communicator& comm, const T* in_values, T& out_value, int root)
158{
11fdf7f2 159 detail::scatter_impl(comm, in_values, &out_value, 1, root, is_mpi_datatype<T>());
7c673cae
FG
160}
161
162template<typename T>
163void
164scatter(const communicator& comm, const std::vector<T>& in_values, T& out_value,
165 int root)
166{
11fdf7f2
TL
167 using detail::c_data;
168 ::boost::mpi::scatter<T>(comm, c_data(in_values), out_value, root);
7c673cae
FG
169}
170
171template<typename T>
172void scatter(const communicator& comm, T& out_value, int root)
173{
174 BOOST_ASSERT(comm.rank() != root);
175 detail::scatter_impl(comm, &out_value, 1, root, is_mpi_datatype<T>());
176}
177
178template<typename T>
179void
180scatter(const communicator& comm, const T* in_values, T* out_values, int n,
181 int root)
182{
11fdf7f2 183 detail::scatter_impl(comm, in_values, out_values, n, root, is_mpi_datatype<T>());
7c673cae
FG
184}
185
186template<typename T>
187void
188scatter(const communicator& comm, const std::vector<T>& in_values,
189 T* out_values, int n, int root)
190{
11fdf7f2 191 ::boost::mpi::scatter(comm, &in_values[0], out_values, n, root);
7c673cae
FG
192}
193
194template<typename T>
195void scatter(const communicator& comm, T* out_values, int n, int root)
196{
197 BOOST_ASSERT(comm.rank() != root);
198 detail::scatter_impl(comm, out_values, n, root, is_mpi_datatype<T>());
199}
200
201} } // end namespace boost::mpi
202
203#endif // BOOST_MPI_SCATTER_HPP