]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/mpi/group.hpp
bump version to 18.2.2-pve1
[ceph.git] / ceph / src / boost / boost / mpi / group.hpp
1 // Copyright (C) 2007 Trustees of Indiana University
2
3 // Authors: Douglas Gregor
4 // Andrew Lumsdaine
5
6 // Use, modification and distribution is subject to the Boost Software
7 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
8 // http://www.boost.org/LICENSE_1_0.txt)
9
10 /** @file group.hpp
11 *
12 * This header defines the @c group class, which allows one to
13 * manipulate and query groups of processes.
14 */
15 #ifndef BOOST_MPI_GROUP_HPP
16 #define BOOST_MPI_GROUP_HPP
17
18 #include <boost/mpi/exception.hpp>
19 #include <boost/mpi/detail/antiques.hpp>
20 #include <boost/shared_ptr.hpp>
21 #include <boost/optional.hpp>
22 #include <vector>
23
24 namespace boost { namespace mpi {
25
26 /**
27 * @brief A @c group is a representation of a subset of the processes
28 * within a @c communicator.
29 *
30 * The @c group class allows one to create arbitrary subsets of the
31 * processes within a communicator. One can compute the union,
32 * intersection, or difference of two groups, or create new groups by
33 * specifically including or excluding certain processes. Given a
34 * group, one can create a new communicator containing only the
35 * processes in that group.
36 */
37 class BOOST_MPI_DECL group
38 {
39 public:
40 /**
41 * @brief Constructs an empty group.
42 */
43 group() : group_ptr() { }
44
45 /**
46 * @brief Constructs a group from an @c MPI_Group.
47 *
48 * This routine allows one to construct a Boost.MPI @c group from a
49 * C @c MPI_Group. The @c group object can (optionally) adopt the @c
50 * MPI_Group, after which point the @c group object becomes
51 * responsible for freeing the @c MPI_Group when the last copy of @c
52 * group disappears.
53 *
54 * @param in_group The @c MPI_Group used to construct this @c group.
55 *
56 * @param adopt Whether the @c group should adopt the @c
57 * MPI_Group. When true, the @c group object (or one of its copies)
58 * will free the group (via @c MPI_Comm_free) when the last copy is
59 * destroyed. Otherwise, the user is responsible for calling @c
60 * MPI_Group_free.
61 */
62 group(const MPI_Group& in_group, bool adopt);
63
64 /**
65 * @brief Determine the rank of the calling process in the group.
66 *
67 * This routine is equivalent to @c MPI_Group_rank.
68 *
69 * @returns The rank of the calling process in the group, which will
70 * be a value in [0, size()). If the calling process is not in the
71 * group, returns an empty value.
72 */
73 optional<int> rank() const;
74
75 /**
76 * @brief Determine the number of processes in the group.
77 *
78 * This routine is equivalent to @c MPI_Group_size.
79 *
80 * @returns The number of processes in the group.
81 */
82 int size() const;
83
84 /**
85 * @brief Translates the ranks from one group into the ranks of the
86 * same processes in another group.
87 *
88 * This routine translates each of the integer rank values in the
89 * iterator range @c [first, last) from the current group into rank
90 * values of the corresponding processes in @p to_group. The
91 * corresponding rank values are written via the output iterator @c
92 * out. When there is no correspondence between a rank in the
93 * current group and a rank in @c to_group, the value @c
94 * MPI_UNDEFINED is written to the output iterator.
95 *
96 * @param first Beginning of the iterator range of ranks in the
97 * current group.
98 *
99 * @param last Past the end of the iterator range of ranks in the
100 * current group.
101 *
102 * @param to_group The group that we are translating ranks to.
103 *
104 * @param out The output iterator to which the translated ranks will
105 * be written.
106 *
107 * @returns the output iterator, which points one step past the last
108 * rank written.
109 */
110 template<typename InputIterator, typename OutputIterator>
111 OutputIterator translate_ranks(InputIterator first, InputIterator last,
112 const group& to_group, OutputIterator out);
113
114 /**
115 * @brief Determines whether the group is non-empty.
116 *
117 * @returns True if the group is not empty, false if it is empty.
118 */
119 operator bool() const { return (bool)group_ptr; }
120
121 /**
122 * @brief Retrieves the underlying @c MPI_Group associated with this
123 * group.
124 *
125 * @returns The @c MPI_Group handle manipulated by this object. If
126 * this object represents the empty group, returns @c
127 * MPI_GROUP_EMPTY.
128 */
129 operator MPI_Group() const
130 {
131 if (group_ptr)
132 return *group_ptr;
133 else
134 return MPI_GROUP_EMPTY;
135 }
136
137 /**
138 * @brief Creates a new group including a subset of the processes
139 * in the current group.
140 *
141 * This routine creates a new @c group which includes only those
142 * processes in the current group that are listed in the integer
143 * iterator range @c [first, last). Equivalent to @c
144 * MPI_Group_incl.
145 *
146 * @c first The beginning of the iterator range of ranks to include.
147 *
148 * @c last Past the end of the iterator range of ranks to include.
149 *
150 * @returns A new group containing those processes with ranks @c
151 * [first, last) in the current group.
152 */
153 template<typename InputIterator>
154 group include(InputIterator first, InputIterator last);
155
156 /**
157 * @brief Creates a new group from all of the processes in the
158 * current group, exluding a specific subset of the processes.
159 *
160 * This routine creates a new @c group which includes all of the
161 * processes in the current group except those whose ranks are
162 * listed in the integer iterator range @c [first,
163 * last). Equivalent to @c MPI_Group_excl.
164 *
165 * @c first The beginning of the iterator range of ranks to exclude.
166 *
167 * @c last Past the end of the iterator range of ranks to exclude.
168 *
169 * @returns A new group containing all of the processes in the
170 * current group except those processes with ranks @c [first, last)
171 * in the current group.
172 */
173 template<typename InputIterator>
174 group exclude(InputIterator first, InputIterator last);
175
176
177 protected:
178 /**
179 * INTERNAL ONLY
180 *
181 * Function object that frees an MPI group and deletes the
182 * memory associated with it. Intended to be used as a deleter with
183 * shared_ptr.
184 */
185 struct group_free
186 {
187 void operator()(MPI_Group* comm) const
188 {
189 int finalized;
190 BOOST_MPI_CHECK_RESULT(MPI_Finalized, (&finalized));
191 if (!finalized)
192 BOOST_MPI_CHECK_RESULT(MPI_Group_free, (comm));
193 delete comm;
194 }
195 };
196
197 /**
198 * The underlying MPI group. This is a shared pointer, so the actual
199 * MPI group which will be shared among all related instances of the
200 * @c group class. When there are no more such instances, the group
201 * will be automatically freed.
202 */
203 shared_ptr<MPI_Group> group_ptr;
204 };
205
206 /**
207 * @brief Determines whether two process groups are identical.
208 *
209 * Equivalent to calling @c MPI_Group_compare and checking whether the
210 * result is @c MPI_IDENT.
211 *
212 * @returns True when the two process groups contain the same
213 * processes in the same order.
214 */
215 BOOST_MPI_DECL bool operator==(const group& g1, const group& g2);
216
217 /**
218 * @brief Determines whether two process groups are not identical.
219 *
220 * Equivalent to calling @c MPI_Group_compare and checking whether the
221 * result is not @c MPI_IDENT.
222 *
223 * @returns False when the two process groups contain the same
224 * processes in the same order.
225 */
226 inline bool operator!=(const group& g1, const group& g2)
227 {
228 return !(g1 == g2);
229 }
230
231 /**
232 * @brief Computes the union of two process groups.
233 *
234 * This routine returns a new @c group that contains all processes
235 * that are either in group @c g1 or in group @c g2 (or both). The
236 * processes that are in @c g1 will be first in the resulting group,
237 * followed by the processes from @c g2 (but not also in @c
238 * g1). Equivalent to @c MPI_Group_union.
239 */
240 BOOST_MPI_DECL group operator|(const group& g1, const group& g2);
241
242 /**
243 * @brief Computes the intersection of two process groups.
244 *
245 * This routine returns a new @c group that contains all processes
246 * that are in group @c g1 and in group @c g2, ordered in the same way
247 * as @c g1. Equivalent to @c MPI_Group_intersection.
248 */
249 BOOST_MPI_DECL group operator&(const group& g1, const group& g2);
250
251 /**
252 * @brief Computes the difference between two process groups.
253 *
254 * This routine returns a new @c group that contains all processes
255 * that are in group @c g1 but not in group @c g2, ordered in the same way
256 * as @c g1. Equivalent to @c MPI_Group_difference.
257 */
258 BOOST_MPI_DECL group operator-(const group& g1, const group& g2);
259
260 /************************************************************************
261 * Implementation details *
262 ************************************************************************/
263 template<typename InputIterator, typename OutputIterator>
264 OutputIterator
265 group::translate_ranks(InputIterator first, InputIterator last,
266 const group& to_group, OutputIterator out)
267 {
268 std::vector<int> in_array(first, last);
269 if (in_array.empty())
270 return out;
271
272 std::vector<int> out_array(in_array.size());
273 BOOST_MPI_CHECK_RESULT(MPI_Group_translate_ranks,
274 ((MPI_Group)*this,
275 in_array.size(),
276 detail::c_data(in_array),
277 (MPI_Group)to_group,
278 detail::c_data(out_array)));
279
280 for (std::vector<int>::size_type i = 0, n = out_array.size(); i < n; ++i)
281 *out++ = out_array[i];
282 return out;
283 }
284
285 /**
286 * INTERNAL ONLY
287 *
288 * Specialization of translate_ranks that handles the one case where
289 * we can avoid any memory allocation or copying.
290 */
291 template<>
292 BOOST_MPI_DECL int*
293 group::translate_ranks(int* first, int* last, const group& to_group, int* out);
294
295 template<typename InputIterator>
296 group group::include(InputIterator first, InputIterator last)
297 {
298 if (first == last)
299 return group();
300
301 std::vector<int> ranks(first, last);
302 MPI_Group result;
303 BOOST_MPI_CHECK_RESULT(MPI_Group_incl,
304 ((MPI_Group)*this, ranks.size(), detail::c_data(ranks), &result));
305 return group(result, /*adopt=*/true);
306 }
307
308 /**
309 * INTERNAL ONLY
310 *
311 * Specialization of group::include that handles the one case where we
312 * can avoid any memory allocation or copying before creating the
313 * group.
314 */
315 template<> BOOST_MPI_DECL group group::include(int* first, int* last);
316
317 template<typename InputIterator>
318 group group::exclude(InputIterator first, InputIterator last)
319 {
320 if (first == last)
321 return group();
322
323 std::vector<int> ranks(first, last);
324 MPI_Group result;
325 BOOST_MPI_CHECK_RESULT(MPI_Group_excl,
326 ((MPI_Group)*this, ranks.size(), detail::c_data(ranks), &result));
327 return group(result, /*adopt=*/true);
328 }
329
330 /**
331 * INTERNAL ONLY
332 *
333 * Specialization of group::exclude that handles the one case where we
334 * can avoid any memory allocation or copying before creating the
335 * group.
336 */
337 template<> BOOST_MPI_DECL group group::exclude(int* first, int* last);
338
339 } } // end namespace boost::mpi
340
341 #endif // BOOST_MPI_GROUP_HPP