Back to home page

EIC code displayed by LXR

 
 

    


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