1 // Copyright (C) 2007 Trustees of Indiana University
3 // Authors: Douglas Gregor
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)
12 * This header defines the @c group class, which allows one to
13 * manipulate and query groups of processes.
15 #ifndef BOOST_MPI_GROUP_HPP
16 #define BOOST_MPI_GROUP_HPP
18 #include <boost/mpi/exception.hpp>
19 #include <boost/shared_ptr.hpp>
20 #include <boost/optional.hpp>
23 namespace boost
{ namespace mpi
{
26 * @brief A @c group is a representation of a subset of the processes
27 * within a @c communicator.
29 * The @c group class allows one to create arbitrary subsets of the
30 * processes within a communicator. One can compute the union,
31 * intersection, or difference of two groups, or create new groups by
32 * specifically including or excluding certain processes. Given a
33 * group, one can create a new communicator containing only the
34 * processes in that group.
36 class BOOST_MPI_DECL group
40 * @brief Constructs an empty group.
42 group() : group_ptr() { }
45 * @brief Constructs a group from an @c MPI_Group.
47 * This routine allows one to construct a Boost.MPI @c group from a
48 * C @c MPI_Group. The @c group object can (optionally) adopt the @c
49 * MPI_Group, after which point the @c group object becomes
50 * responsible for freeing the @c MPI_Group when the last copy of @c
53 * @param in_group The @c MPI_Group used to construct this @c group.
55 * @param adopt Whether the @c group should adopt the @c
56 * MPI_Group. When true, the @c group object (or one of its copies)
57 * will free the group (via @c MPI_Comm_free) when the last copy is
58 * destroyed. Otherwise, the user is responsible for calling @c
61 group(const MPI_Group
& in_group
, bool adopt
);
64 * @brief Determine the rank of the calling process in the group.
66 * This routine is equivalent to @c MPI_Group_rank.
68 * @returns The rank of the calling process in the group, which will
69 * be a value in [0, size()). If the calling process is not in the
70 * group, returns an empty value.
72 optional
<int> rank() const;
75 * @brief Determine the number of processes in the group.
77 * This routine is equivalent to @c MPI_Group_size.
79 * @returns The number of processes in the group.
84 * @brief Translates the ranks from one group into the ranks of the
85 * same processes in another group.
87 * This routine translates each of the integer rank values in the
88 * iterator range @c [first, last) from the current group into rank
89 * values of the corresponding processes in @p to_group. The
90 * corresponding rank values are written via the output iterator @c
91 * out. When there is no correspondence between a rank in the
92 * current group and a rank in @c to_group, the value @c
93 * MPI_UNDEFINED is written to the output iterator.
95 * @param first Beginning of the iterator range of ranks in the
98 * @param last Past the end of the iterator range of ranks in the
101 * @param to_group The group that we are translating ranks to.
103 * @param out The output iterator to which the translated ranks will
106 * @returns the output iterator, which points one step past the last
109 template<typename InputIterator
, typename OutputIterator
>
110 OutputIterator
translate_ranks(InputIterator first
, InputIterator last
,
111 const group
& to_group
, OutputIterator out
);
114 * @brief Determines whether the group is non-empty.
116 * @returns True if the group is not empty, false if it is empty.
118 operator bool() const { return (bool)group_ptr
; }
121 * @brief Retrieves the underlying @c MPI_Group associated with this
124 * @returns The @c MPI_Group handle manipulated by this object. If
125 * this object represents the empty group, returns @c
128 operator MPI_Group() const
133 return MPI_GROUP_EMPTY
;
137 * @brief Creates a new group including a subset of the processes
138 * in the current group.
140 * This routine creates a new @c group which includes only those
141 * processes in the current group that are listed in the integer
142 * iterator range @c [first, last). Equivalent to @c
145 * @c first The beginning of the iterator range of ranks to include.
147 * @c last Past the end of the iterator range of ranks to include.
149 * @returns A new group containing those processes with ranks @c
150 * [first, last) in the current group.
152 template<typename InputIterator
>
153 group
include(InputIterator first
, InputIterator last
);
156 * @brief Creates a new group from all of the processes in the
157 * current group, exluding a specific subset of the processes.
159 * This routine creates a new @c group which includes all of the
160 * processes in the current group except those whose ranks are
161 * listed in the integer iterator range @c [first,
162 * last). Equivalent to @c MPI_Group_excl.
164 * @c first The beginning of the iterator range of ranks to exclude.
166 * @c last Past the end of the iterator range of ranks to exclude.
168 * @returns A new group containing all of the processes in the
169 * current group except those processes with ranks @c [first, last)
170 * in the current group.
172 template<typename InputIterator
>
173 group
exclude(InputIterator first
, InputIterator last
);
180 * Function object that frees an MPI group and deletes the
181 * memory associated with it. Intended to be used as a deleter with
186 void operator()(MPI_Group
* comm
) const
189 BOOST_MPI_CHECK_RESULT(MPI_Finalized
, (&finalized
));
191 BOOST_MPI_CHECK_RESULT(MPI_Group_free
, (comm
));
197 * The underlying MPI group. This is a shared pointer, so the actual
198 * MPI group which will be shared among all related instances of the
199 * @c group class. When there are no more such instances, the group
200 * will be automatically freed.
202 shared_ptr
<MPI_Group
> group_ptr
;
206 * @brief Determines whether two process groups are identical.
208 * Equivalent to calling @c MPI_Group_compare and checking whether the
209 * result is @c MPI_IDENT.
211 * @returns True when the two process groups contain the same
212 * processes in the same order.
214 BOOST_MPI_DECL
bool operator==(const group
& g1
, const group
& g2
);
217 * @brief Determines whether two process groups are not identical.
219 * Equivalent to calling @c MPI_Group_compare and checking whether the
220 * result is not @c MPI_IDENT.
222 * @returns False when the two process groups contain the same
223 * processes in the same order.
225 inline bool operator!=(const group
& g1
, const group
& g2
)
231 * @brief Computes the union of two process groups.
233 * This routine returns a new @c group that contains all processes
234 * that are either in group @c g1 or in group @c g2 (or both). The
235 * processes that are in @c g1 will be first in the resulting group,
236 * followed by the processes from @c g2 (but not also in @c
237 * g1). Equivalent to @c MPI_Group_union.
239 BOOST_MPI_DECL group
operator|(const group
& g1
, const group
& g2
);
242 * @brief Computes the intersection of two process groups.
244 * This routine returns a new @c group that contains all processes
245 * that are in group @c g1 and in group @c g2, ordered in the same way
246 * as @c g1. Equivalent to @c MPI_Group_intersection.
248 BOOST_MPI_DECL group
operator&(const group
& g1
, const group
& g2
);
251 * @brief Computes the difference between two process groups.
253 * This routine returns a new @c group that contains all processes
254 * that are in group @c g1 but not in group @c g2, ordered in the same way
255 * as @c g1. Equivalent to @c MPI_Group_difference.
257 BOOST_MPI_DECL group
operator-(const group
& g1
, const group
& g2
);
259 /************************************************************************
260 * Implementation details *
261 ************************************************************************/
262 template<typename InputIterator
, typename OutputIterator
>
264 group::translate_ranks(InputIterator first
, InputIterator last
,
265 const group
& to_group
, OutputIterator out
)
267 std::vector
<int> in_array(first
, last
);
268 if (in_array
.empty())
271 std::vector
<int> out_array(in_array
.size());
272 BOOST_MPI_CHECK_RESULT(MPI_Group_translate_ranks
,
279 for (std::vector
<int>::size_type i
= 0, n
= out_array
.size(); i
< n
; ++i
)
280 *out
++ = out_array
[i
];
287 * Specialization of translate_ranks that handles the one case where
288 * we can avoid any memory allocation or copying.
292 group::translate_ranks(int* first
, int* last
, const group
& to_group
, int* out
);
294 template<typename InputIterator
>
295 group
group::include(InputIterator first
, InputIterator last
)
300 std::vector
<int> ranks(first
, last
);
302 BOOST_MPI_CHECK_RESULT(MPI_Group_incl
,
303 ((MPI_Group
)*this, ranks
.size(), &ranks
[0], &result
));
304 return group(result
, /*adopt=*/true);
310 * Specialization of group::include that handles the one case where we
311 * can avoid any memory allocation or copying before creating the
314 template<> BOOST_MPI_DECL group
group::include(int* first
, int* last
);
316 template<typename InputIterator
>
317 group
group::exclude(InputIterator first
, InputIterator last
)
322 std::vector
<int> ranks(first
, last
);
324 BOOST_MPI_CHECK_RESULT(MPI_Group_excl
,
325 ((MPI_Group
)*this, ranks
.size(), &ranks
[0], &result
));
326 return group(result
, /*adopt=*/true);
332 * Specialization of group::exclude that handles the one case where we
333 * can avoid any memory allocation or copying before creating the
336 template<> BOOST_MPI_DECL group
group::exclude(int* first
, int* last
);
338 } } // end namespace boost::mpi
340 #endif // BOOST_MPI_GROUP_HPP