|
||||
File indexing completed on 2025-01-18 09:40:58
0001 // Copyright (C) 2007 Trustees of Indiana University 0002 0003 // Authors: Douglas Gregor 0004 // Andrew Lumsdaine 0005 0006 // Use, modification and distribution is subject to the Boost Software 0007 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at 0008 // http://www.boost.org/LICENSE_1_0.txt) 0009 0010 /** @file group.hpp 0011 * 0012 * This header defines the @c group class, which allows one to 0013 * manipulate and query groups of processes. 0014 */ 0015 #ifndef BOOST_MPI_GROUP_HPP 0016 #define BOOST_MPI_GROUP_HPP 0017 0018 #include <boost/mpi/exception.hpp> 0019 #include <boost/mpi/detail/antiques.hpp> 0020 #include <boost/shared_ptr.hpp> 0021 #include <boost/optional.hpp> 0022 #include <vector> 0023 0024 namespace boost { namespace mpi { 0025 0026 /** 0027 * @brief A @c group is a representation of a subset of the processes 0028 * within a @c communicator. 0029 * 0030 * The @c group class allows one to create arbitrary subsets of the 0031 * processes within a communicator. One can compute the union, 0032 * intersection, or difference of two groups, or create new groups by 0033 * specifically including or excluding certain processes. Given a 0034 * group, one can create a new communicator containing only the 0035 * processes in that group. 0036 */ 0037 class BOOST_MPI_DECL group 0038 { 0039 public: 0040 /** 0041 * @brief Constructs an empty group. 0042 */ 0043 group() : group_ptr() { } 0044 0045 /** 0046 * @brief Constructs a group from an @c MPI_Group. 0047 * 0048 * This routine allows one to construct a Boost.MPI @c group from a 0049 * C @c MPI_Group. The @c group object can (optionally) adopt the @c 0050 * MPI_Group, after which point the @c group object becomes 0051 * responsible for freeing the @c MPI_Group when the last copy of @c 0052 * group disappears. 0053 * 0054 * @param in_group The @c MPI_Group used to construct this @c group. 0055 * 0056 * @param adopt Whether the @c group should adopt the @c 0057 * MPI_Group. When true, the @c group object (or one of its copies) 0058 * will free the group (via @c MPI_Comm_free) when the last copy is 0059 * destroyed. Otherwise, the user is responsible for calling @c 0060 * MPI_Group_free. 0061 */ 0062 group(const MPI_Group& in_group, bool adopt); 0063 0064 /** 0065 * @brief Determine the rank of the calling process in the group. 0066 * 0067 * This routine is equivalent to @c MPI_Group_rank. 0068 * 0069 * @returns The rank of the calling process in the group, which will 0070 * be a value in [0, size()). If the calling process is not in the 0071 * group, returns an empty value. 0072 */ 0073 optional<int> rank() const; 0074 0075 /** 0076 * @brief Determine the number of processes in the group. 0077 * 0078 * This routine is equivalent to @c MPI_Group_size. 0079 * 0080 * @returns The number of processes in the group. 0081 */ 0082 int size() const; 0083 0084 /** 0085 * @brief Translates the ranks from one group into the ranks of the 0086 * same processes in another group. 0087 * 0088 * This routine translates each of the integer rank values in the 0089 * iterator range @c [first, last) from the current group into rank 0090 * values of the corresponding processes in @p to_group. The 0091 * corresponding rank values are written via the output iterator @c 0092 * out. When there is no correspondence between a rank in the 0093 * current group and a rank in @c to_group, the value @c 0094 * MPI_UNDEFINED is written to the output iterator. 0095 * 0096 * @param first Beginning of the iterator range of ranks in the 0097 * current group. 0098 * 0099 * @param last Past the end of the iterator range of ranks in the 0100 * current group. 0101 * 0102 * @param to_group The group that we are translating ranks to. 0103 * 0104 * @param out The output iterator to which the translated ranks will 0105 * be written. 0106 * 0107 * @returns the output iterator, which points one step past the last 0108 * rank written. 0109 */ 0110 template<typename InputIterator, typename OutputIterator> 0111 OutputIterator translate_ranks(InputIterator first, InputIterator last, 0112 const group& to_group, OutputIterator out); 0113 0114 /** 0115 * @brief Determines whether the group is non-empty. 0116 * 0117 * @returns True if the group is not empty, false if it is empty. 0118 */ 0119 operator bool() const { return (bool)group_ptr; } 0120 0121 /** 0122 * @brief Retrieves the underlying @c MPI_Group associated with this 0123 * group. 0124 * 0125 * @returns The @c MPI_Group handle manipulated by this object. If 0126 * this object represents the empty group, returns @c 0127 * MPI_GROUP_EMPTY. 0128 */ 0129 operator MPI_Group() const 0130 { 0131 if (group_ptr) 0132 return *group_ptr; 0133 else 0134 return MPI_GROUP_EMPTY; 0135 } 0136 0137 /** 0138 * @brief Creates a new group including a subset of the processes 0139 * in the current group. 0140 * 0141 * This routine creates a new @c group which includes only those 0142 * processes in the current group that are listed in the integer 0143 * iterator range @c [first, last). Equivalent to @c 0144 * MPI_Group_incl. 0145 * 0146 * @c first The beginning of the iterator range of ranks to include. 0147 * 0148 * @c last Past the end of the iterator range of ranks to include. 0149 * 0150 * @returns A new group containing those processes with ranks @c 0151 * [first, last) in the current group. 0152 */ 0153 template<typename InputIterator> 0154 group include(InputIterator first, InputIterator last); 0155 0156 /** 0157 * @brief Creates a new group from all of the processes in the 0158 * current group, exluding a specific subset of the processes. 0159 * 0160 * This routine creates a new @c group which includes all of the 0161 * processes in the current group except those whose ranks are 0162 * listed in the integer iterator range @c [first, 0163 * last). Equivalent to @c MPI_Group_excl. 0164 * 0165 * @c first The beginning of the iterator range of ranks to exclude. 0166 * 0167 * @c last Past the end of the iterator range of ranks to exclude. 0168 * 0169 * @returns A new group containing all of the processes in the 0170 * current group except those processes with ranks @c [first, last) 0171 * in the current group. 0172 */ 0173 template<typename InputIterator> 0174 group exclude(InputIterator first, InputIterator last); 0175 0176 0177 protected: 0178 /** 0179 * INTERNAL ONLY 0180 * 0181 * Function object that frees an MPI group and deletes the 0182 * memory associated with it. Intended to be used as a deleter with 0183 * shared_ptr. 0184 */ 0185 struct group_free 0186 { 0187 void operator()(MPI_Group* comm) const 0188 { 0189 int finalized; 0190 BOOST_MPI_CHECK_RESULT(MPI_Finalized, (&finalized)); 0191 if (!finalized) 0192 BOOST_MPI_CHECK_RESULT(MPI_Group_free, (comm)); 0193 delete comm; 0194 } 0195 }; 0196 0197 /** 0198 * The underlying MPI group. This is a shared pointer, so the actual 0199 * MPI group which will be shared among all related instances of the 0200 * @c group class. When there are no more such instances, the group 0201 * will be automatically freed. 0202 */ 0203 shared_ptr<MPI_Group> group_ptr; 0204 }; 0205 0206 /** 0207 * @brief Determines whether two process groups are identical. 0208 * 0209 * Equivalent to calling @c MPI_Group_compare and checking whether the 0210 * result is @c MPI_IDENT. 0211 * 0212 * @returns True when the two process groups contain the same 0213 * processes in the same order. 0214 */ 0215 BOOST_MPI_DECL bool operator==(const group& g1, const group& g2); 0216 0217 /** 0218 * @brief Determines whether two process groups are not identical. 0219 * 0220 * Equivalent to calling @c MPI_Group_compare and checking whether the 0221 * result is not @c MPI_IDENT. 0222 * 0223 * @returns False when the two process groups contain the same 0224 * processes in the same order. 0225 */ 0226 inline bool operator!=(const group& g1, const group& g2) 0227 { 0228 return !(g1 == g2); 0229 } 0230 0231 /** 0232 * @brief Computes the union of two process groups. 0233 * 0234 * This routine returns a new @c group that contains all processes 0235 * that are either in group @c g1 or in group @c g2 (or both). The 0236 * processes that are in @c g1 will be first in the resulting group, 0237 * followed by the processes from @c g2 (but not also in @c 0238 * g1). Equivalent to @c MPI_Group_union. 0239 */ 0240 BOOST_MPI_DECL group operator|(const group& g1, const group& g2); 0241 0242 /** 0243 * @brief Computes the intersection of two process groups. 0244 * 0245 * This routine returns a new @c group that contains all processes 0246 * that are in group @c g1 and in group @c g2, ordered in the same way 0247 * as @c g1. Equivalent to @c MPI_Group_intersection. 0248 */ 0249 BOOST_MPI_DECL group operator&(const group& g1, const group& g2); 0250 0251 /** 0252 * @brief Computes the difference between two process groups. 0253 * 0254 * This routine returns a new @c group that contains all processes 0255 * that are in group @c g1 but not in group @c g2, ordered in the same way 0256 * as @c g1. Equivalent to @c MPI_Group_difference. 0257 */ 0258 BOOST_MPI_DECL group operator-(const group& g1, const group& g2); 0259 0260 /************************************************************************ 0261 * Implementation details * 0262 ************************************************************************/ 0263 template<typename InputIterator, typename OutputIterator> 0264 OutputIterator 0265 group::translate_ranks(InputIterator first, InputIterator last, 0266 const group& to_group, OutputIterator out) 0267 { 0268 std::vector<int> in_array(first, last); 0269 if (in_array.empty()) 0270 return out; 0271 0272 std::vector<int> out_array(in_array.size()); 0273 BOOST_MPI_CHECK_RESULT(MPI_Group_translate_ranks, 0274 ((MPI_Group)*this, 0275 in_array.size(), 0276 detail::c_data(in_array), 0277 (MPI_Group)to_group, 0278 detail::c_data(out_array))); 0279 0280 for (std::vector<int>::size_type i = 0, n = out_array.size(); i < n; ++i) 0281 *out++ = out_array[i]; 0282 return out; 0283 } 0284 0285 /** 0286 * INTERNAL ONLY 0287 * 0288 * Specialization of translate_ranks that handles the one case where 0289 * we can avoid any memory allocation or copying. 0290 */ 0291 template<> 0292 BOOST_MPI_DECL int* 0293 group::translate_ranks(int* first, int* last, const group& to_group, int* out); 0294 0295 template<typename InputIterator> 0296 group group::include(InputIterator first, InputIterator last) 0297 { 0298 if (first == last) 0299 return group(); 0300 0301 std::vector<int> ranks(first, last); 0302 MPI_Group result; 0303 BOOST_MPI_CHECK_RESULT(MPI_Group_incl, 0304 ((MPI_Group)*this, ranks.size(), detail::c_data(ranks), &result)); 0305 return group(result, /*adopt=*/true); 0306 } 0307 0308 /** 0309 * INTERNAL ONLY 0310 * 0311 * Specialization of group::include that handles the one case where we 0312 * can avoid any memory allocation or copying before creating the 0313 * group. 0314 */ 0315 template<> BOOST_MPI_DECL group group::include(int* first, int* last); 0316 0317 template<typename InputIterator> 0318 group group::exclude(InputIterator first, InputIterator last) 0319 { 0320 if (first == last) 0321 return group(); 0322 0323 std::vector<int> ranks(first, last); 0324 MPI_Group result; 0325 BOOST_MPI_CHECK_RESULT(MPI_Group_excl, 0326 ((MPI_Group)*this, ranks.size(), detail::c_data(ranks), &result)); 0327 return group(result, /*adopt=*/true); 0328 } 0329 0330 /** 0331 * INTERNAL ONLY 0332 * 0333 * Specialization of group::exclude that handles the one case where we 0334 * can avoid any memory allocation or copying before creating the 0335 * group. 0336 */ 0337 template<> BOOST_MPI_DECL group group::exclude(int* first, int* last); 0338 0339 } } // end namespace boost::mpi 0340 0341 #endif // BOOST_MPI_GROUP_HPP
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |