group.hpp 11 KB

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