parallel.h
Go to the documentation of this file.00001 // The libMesh Finite Element Library. 00002 // Copyright (C) 2002-2012 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner 00003 00004 // This library is free software; you can redistribute it and/or 00005 // modify it under the terms of the GNU Lesser General Public 00006 // License as published by the Free Software Foundation; either 00007 // version 2.1 of the License, or (at your option) any later version. 00008 00009 // This library is distributed in the hope that it will be useful, 00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 // Lesser General Public License for more details. 00013 00014 // You should have received a copy of the GNU Lesser General Public 00015 // License along with this library; if not, write to the Free Software 00016 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00017 00018 00019 #ifndef LIBMESH_PARALLEL_H 00020 #define LIBMESH_PARALLEL_H 00021 00022 // Local includes 00023 #include "libmesh/libmesh_common.h" // libmesh_assert, libmesh_cast_int 00024 #include "libmesh/libmesh_logging.h" 00025 00026 // C++ includes 00027 #include <cstddef> 00028 #include <climits> 00029 #include <iterator> 00030 #include <limits> 00031 #include <map> 00032 #include <set> 00033 #include <string> 00034 #include <vector> 00035 00036 namespace libMesh 00037 { 00038 00039 00040 // Macro to identify and debug functions which should only be called in 00041 // parallel on every processor at once 00042 00043 #undef parallel_only 00044 #ifndef NDEBUG 00045 #define parallel_only() do { \ 00046 libmesh_assert(CommWorld.verify(std::string(__FILE__).size())); \ 00047 libmesh_assert(CommWorld.verify(std::string(__FILE__))); \ 00048 libmesh_assert(CommWorld.verify(__LINE__)); } while (0) 00049 #else 00050 #define parallel_only() ((void) 0) 00051 #endif 00052 00053 // Macro to identify and debug functions which should only be called in 00054 // parallel on every processor at once 00055 00056 #undef parallel_only_on 00057 #ifndef NDEBUG 00058 #define parallel_only_on(comm_arg) do { \ 00059 libmesh_assert(CommWorld.verify(std::string(__FILE__).size(), comm_arg)); \ 00060 libmesh_assert(CommWorld.verify(std::string(__FILE__), comm_arg)); \ 00061 libmesh_assert(CommWorld.verify(__LINE__), comm_arg); } while (0) 00062 #else 00063 #define parallel_only_on(comm_arg) ((void) 0) 00064 #endif 00065 00073 namespace Parallel 00074 { 00075 //------------------------------------------------------------------- 00079 class Communicator; 00080 class DataType; 00081 class Request; 00082 class Status; 00083 00084 #ifdef LIBMESH_HAVE_MPI 00085 //------------------------------------------------------------------- 00089 typedef MPI_Datatype data_type; 00090 00094 typedef MPI_Request request; 00095 00099 typedef MPI_Status status; 00100 00104 typedef MPI_Comm communicator; 00105 00110 template <typename T> 00111 inline data_type dataplusint_type(); 00112 00116 template <typename T> 00117 class DataPlusInt 00118 { 00119 public: 00120 T val; 00121 int rank; 00122 }; 00123 00127 const unsigned int any_source = 00128 static_cast<unsigned int>(MPI_ANY_SOURCE); 00129 00130 00131 #else 00132 00133 // These shouldn't actually be needed, but must be 00134 // unique types for function overloading to work 00135 // properly. 00136 struct data_type { /* unsigned int t; */ }; 00137 struct request { /* unsigned int r; */ }; 00138 struct status { /* unsigned int s; */ }; 00139 struct communicator { /* unsigned int s; */ }; 00140 00141 const unsigned int any_source=0; 00142 #endif // LIBMESH_HAVE_MPI 00143 00144 00145 00146 //------------------------------------------------------------------- 00150 class MessageTag 00151 { 00152 public: 00153 00157 static const int invalid_tag = INT_MIN; 00158 00163 explicit MessageTag(int tagvalue = invalid_tag) 00164 : _tagvalue(tagvalue), _comm(NULL) {} 00165 00170 MessageTag(const MessageTag& other); 00171 00176 ~MessageTag(); 00177 00178 int value() const { 00179 return _tagvalue; 00180 } 00181 00182 private: 00183 int _tagvalue; 00184 const Communicator *_comm; 00185 00186 // Constructor for reference-counted unique tags 00187 MessageTag(int tagvalue, const Communicator *comm) 00188 : _tagvalue(tagvalue), _comm(comm) {} 00189 00190 // Let Communicator handle the reference counting 00191 friend class Communicator; 00192 }; 00193 00194 00195 //------------------------------------------------------------------- 00199 #ifdef LIBMESH_HAVE_MPI 00200 const MessageTag any_tag = MessageTag(MPI_ANY_TAG); 00201 #else 00202 const MessageTag any_tag = MessageTag(-1); 00203 #endif 00204 00205 const MessageTag no_tag = MessageTag(0); 00206 00207 00208 //------------------------------------------------------------------- 00212 class DataType 00213 { 00214 public: 00215 DataType () : _datatype() {} 00216 00217 DataType (const DataType &other) : 00218 _datatype(other._datatype) 00219 {} 00220 00221 DataType (const data_type &type) : 00222 _datatype(type) 00223 {} 00224 00225 #ifdef LIBMESH_HAVE_MPI 00226 DataType (const DataType &other, unsigned int count) 00227 { 00228 MPI_Type_contiguous(count, other._datatype, &_datatype); 00229 this->commit(); 00230 } 00231 #else 00232 DataType (const DataType &, unsigned int) 00233 { 00234 } 00235 #endif 00236 00237 DataType & operator = (const DataType &other) 00238 { _datatype = other._datatype; return *this; } 00239 00240 DataType & operator = (const data_type &type) 00241 { _datatype = type; return *this; } 00242 00243 operator const data_type & () const 00244 { return _datatype; } 00245 00246 operator data_type & () 00247 { return _datatype; } 00248 00249 // operator data_type const * () const 00250 // { return &_datatype; } 00251 00252 // operator data_type * () 00253 // { return &_datatype; } 00254 00255 void commit () 00256 { 00257 #ifdef LIBMESH_HAVE_MPI 00258 MPI_Type_commit (&_datatype); 00259 #endif 00260 } 00261 00262 void free () 00263 { 00264 #ifdef LIBMESH_HAVE_MPI 00265 MPI_Type_free (&_datatype); 00266 #endif 00267 } 00268 00269 protected: 00270 00271 data_type _datatype; 00272 }; 00273 00274 00275 //------------------------------------------------------------------- 00283 template <typename T> 00284 class StandardType : public DataType 00285 { 00286 /* 00287 * The unspecialized class is useless, so we make its constructor 00288 * private to catch mistakes at compile-time rather than link-time. 00289 * Specializations should have a public constructor of the same 00290 * form. 00291 */ 00292 private: 00293 StandardType(const T* example = NULL); 00294 }; 00295 00296 /* 00297 * The unspecialized class gives default, lowest-common-denominator 00298 * attributes, for values which can't be used with Parallel min/max. 00299 * Specialized classes can set this to true, and should define 00300 * the lowest and highest values possible for the type. 00301 */ 00302 template<typename T> 00303 struct Attributes 00304 { 00305 static const bool has_min_max = false; 00306 static void set_lowest(T&) {} 00307 static void set_highest(T&) {} 00308 }; 00309 00310 00311 00312 //------------------------------------------------------------------- 00317 class Status 00318 { 00319 public: 00320 Status (); 00321 00322 explicit Status (const data_type &type); 00323 00324 explicit Status (const status &status); 00325 00326 Status (const status &status, 00327 const data_type &type); 00328 00329 Status (const Status &status); 00330 00331 Status (const Status &status, 00332 const data_type &type); 00333 00334 status * get() { return &_status; } 00335 00336 status const * get() const { return &_status; } 00337 00338 int source () const; 00339 00340 int tag () const; 00341 00342 data_type& datatype () { return _datatype; } 00343 00344 const data_type& datatype () const { return _datatype; } 00345 00346 unsigned int size (const data_type &type) const; 00347 00348 unsigned int size () const; 00349 00350 private: 00351 00352 status _status; 00353 data_type _datatype; 00354 }; 00355 00356 00357 //------------------------------------------------------------------- 00362 struct PostWaitWork { 00363 virtual ~PostWaitWork() {}; 00364 00365 virtual void run() {}; 00366 }; 00367 00368 00369 //------------------------------------------------------------------- 00373 class Request 00374 { 00375 public: 00376 Request (); 00377 00378 Request (const request &r); 00379 00380 Request (const Request &other); 00381 00382 void cleanup(); 00383 00384 Request & operator = (const Request &other); 00385 00386 Request & operator = (const request &r); 00387 00388 ~Request (); 00389 00390 request* get() { return &_request; } 00391 00392 const request* get() const { return &_request; } 00393 00394 Status wait (); 00395 00396 bool test (); 00397 00398 bool test (status &status); 00399 00400 void add_post_wait_work(PostWaitWork* work); 00401 00402 private: 00403 request _request; 00404 00405 // post_wait_work->first is a vector of work to do after a wait 00406 // finishes; post_wait_work->second is a reference count so that 00407 // Request objects will behave roughly like a shared_ptr and be 00408 // usable in STL containers 00409 std::pair<std::vector <PostWaitWork* >, unsigned int>* post_wait_work; 00410 }; 00411 00415 inline Status wait (Request &r) { return r.wait(); } 00416 00420 inline void wait (std::vector<Request> &r) 00421 { for (unsigned int i=0; i<r.size(); i++) r[i].wait(); } 00422 00423 00424 00433 template <typename T, typename Context> 00434 void pack(const T* object, 00435 std::vector<int>& data, 00436 const Context* context); 00437 00446 template <typename T, typename Context> 00447 unsigned int packable_size(const T*, const Context*); 00448 00460 template <typename T> 00461 unsigned int packed_size(const T*, 00462 const std::vector<int>::const_iterator); 00463 00472 template <typename T, typename Context> 00473 void unpack(std::vector<int>::const_iterator in, T** out, Context*); 00474 00479 template <typename Context, typename OutputIter> 00480 inline void unpack_range (const std::vector<int>& buffer, 00481 Context *context, 00482 OutputIter out); 00483 00488 template <typename Context, typename Iter> 00489 inline void pack_range (const Context *context, 00490 Iter range_begin, 00491 const Iter range_end, 00492 std::vector<int>& buffer); 00493 00494 //------------------------------------------------------------------- 00502 class Communicator 00503 { 00504 // Basic operations: 00505 public: 00506 00507 Communicator (); 00508 00509 /* 00510 * Constructor from MPI_Comm 00511 */ 00512 explicit Communicator (const communicator &comm); 00513 00514 /* 00515 * NON-VIRTUAL destructor 00516 */ 00517 ~Communicator (); 00518 00519 /* 00520 * Create a new communicator between some subset of \p this 00521 */ 00522 void split(int color, int key, Communicator &target); 00523 00524 /* 00525 * Create a new duplicate of \p this communicator 00526 */ 00527 void duplicate(const Communicator &comm); 00528 00529 /* 00530 * Create a new duplicate of an MPI communicator 00531 */ 00532 void duplicate(const communicator &comm); 00533 00534 communicator& get() { return _communicator; } 00535 00536 const communicator& get() const { return _communicator; } 00537 00544 MessageTag get_unique_tag(int tagvalue) const; 00545 00550 void reference_unique_tag(int tagvalue) const; 00551 00556 void dereference_unique_tag(int tagvalue) const; 00557 00561 void clear(); 00562 00563 Communicator& operator= (const communicator &comm); 00564 00565 unsigned int rank() const { return _rank; } 00566 00567 unsigned int size() const { return _size; } 00568 00569 private: 00570 00571 // Don't use the copy constructor, just copy by reference or 00572 // pointer - it's too hard to keep a common used_tag_values if 00573 // each communicator is shared by more than one Communicator 00574 explicit Communicator (const Communicator &); 00575 00580 void assign(const communicator &comm); 00581 00582 communicator _communicator; 00583 unsigned int _rank, _size; 00584 00585 // mutable used_tag_values - not thread-safe, but then Parallel:: 00586 // isn't thread-safe in general. 00587 mutable std::map<int, unsigned int> used_tag_values; 00588 bool _I_duped_it; 00589 00590 // Communication operations: 00591 public: 00592 00596 void barrier () const; 00597 00602 template <typename T> 00603 bool verify(const T &r) const; 00604 00610 template <typename T> 00611 bool semiverify(const T *r) const; 00612 00617 template <typename T> 00618 void min(T &r) const; 00619 00625 template <typename T> 00626 void minloc(T &r, 00627 unsigned int &min_id) const; 00628 00634 template <typename T> 00635 void minloc(std::vector<T> &r, 00636 std::vector<unsigned int> &min_id) const; 00637 00642 template <typename T> 00643 void max(T &r) const; 00644 00650 template <typename T> 00651 void maxloc(T &r, 00652 unsigned int &max_id) const; 00653 00659 template <typename T> 00660 void maxloc(std::vector<T> &r, 00661 std::vector<unsigned int> &max_id) const; 00662 00667 template <typename T> 00668 void sum(T &r) const; 00669 00675 template <typename T> 00676 void set_union(T &data, const unsigned int root_id) const; 00677 00682 template <typename T> 00683 void set_union(T &data) const; 00684 00689 status probe (const unsigned int src_processor_id, 00690 const MessageTag &tag=any_tag) const; 00691 00695 template <typename T> 00696 void send (const unsigned int dest_processor_id, 00697 T &buf, 00698 const MessageTag &tag=no_tag) const; 00699 00703 template <typename T> 00704 void send (const unsigned int dest_processor_id, 00705 T &buf, 00706 Request &req, 00707 const MessageTag &tag=no_tag) const; 00708 00712 template <typename T> 00713 void send (const unsigned int dest_processor_id, 00714 T &buf, 00715 const DataType &type, 00716 const MessageTag &tag=no_tag) const; 00717 00721 template <typename T> 00722 void send (const unsigned int dest_processor_id, 00723 T &buf, 00724 const DataType &type, 00725 Request &req, 00726 const MessageTag &tag=no_tag) const; 00727 00731 template <typename T> 00732 Status receive (const unsigned int dest_processor_id, 00733 T &buf, 00734 const MessageTag &tag=any_tag) const; 00735 00739 template <typename T> 00740 void receive (const unsigned int dest_processor_id, 00741 T &buf, 00742 Request &req, 00743 const MessageTag &tag=any_tag) const; 00744 00748 template <typename T> 00749 Status receive (const unsigned int dest_processor_id, 00750 T &buf, 00751 const DataType &type, 00752 const MessageTag &tag=any_tag) const; 00753 00757 template <typename T> 00758 void receive (const unsigned int dest_processor_id, 00759 T &buf, 00760 const DataType &type, 00761 Request &req, 00762 const MessageTag &tag=any_tag) const; 00763 00777 template <typename Context, typename Iter> 00778 void send_packed_range (const unsigned int dest_processor_id, 00779 const Context *context, 00780 Iter range_begin, 00781 const Iter range_end, 00782 const MessageTag &tag=no_tag) const; 00783 00797 template <typename Context, typename Iter> 00798 void send_packed_range (const unsigned int dest_processor_id, 00799 const Context *context, 00800 Iter range_begin, 00801 const Iter range_end, 00802 Request &req, 00803 const MessageTag &tag=no_tag) const; 00804 00831 template <typename Context, typename OutputIter> 00832 void receive_packed_range (const unsigned int dest_processor_id, 00833 Context *context, 00834 OutputIter out, 00835 const MessageTag &tag=any_tag) const; 00836 00863 template <typename Context, typename OutputIter> 00864 void receive_packed_range (const unsigned int dest_processor_id, 00865 Context *context, 00866 OutputIter out, 00867 Request &req, 00868 const MessageTag &tag=any_tag) const; 00869 00874 template <typename T1, typename T2> 00875 void send_receive(const unsigned int dest_processor_id, 00876 T1 &send, 00877 const unsigned int source_processor_id, 00878 T2 &recv, 00879 const MessageTag &send_tag = no_tag, 00880 const MessageTag &recv_tag = any_tag) const; 00881 00918 template <typename Context1, typename RangeIter, typename Context2, typename OutputIter> 00919 void send_receive_packed_range(const unsigned int dest_processor_id, 00920 const Context1* context1, 00921 RangeIter send_begin, 00922 const RangeIter send_end, 00923 const unsigned int source_processor_id, 00924 Context2* context2, 00925 OutputIter out, 00926 const MessageTag &send_tag = no_tag, 00927 const MessageTag &recv_tag = any_tag) const; 00928 00934 template <typename T1, typename T2> 00935 void send_receive(const unsigned int dest_processor_id, 00936 T1 &send, 00937 const DataType &type1, 00938 const unsigned int source_processor_id, 00939 T2 &recv, 00940 const DataType &type2, 00941 const MessageTag &send_tag = no_tag, 00942 const MessageTag &recv_tag = any_tag) const; 00943 00948 template <typename T> 00949 inline void gather(const unsigned int root_id, 00950 T send, 00951 std::vector<T> &recv) const; 00952 00977 template <typename T> 00978 inline void gather(const unsigned int root_id, 00979 std::vector<T> &r) const; 00980 00985 template <typename T> 00986 inline void allgather(T send, 00987 std::vector<T> &recv) const; 00988 00989 01014 template <typename T> 01015 inline void allgather(std::vector<T> &r, 01016 const bool identical_buffer_sizes = false) const; 01017 01018 //------------------------------------------------------------------- 01024 template <typename Context, typename Iter, typename OutputIter> 01025 inline void allgather_packed_range (Context *context, 01026 Iter range_begin, 01027 const Iter range_end, 01028 OutputIter out) const; 01029 01035 template <typename T> 01036 inline void alltoall(std::vector<T> &r) const; 01037 01045 template <typename T> 01046 inline void broadcast(T &data, const unsigned int root_id=0) const; 01047 01065 template <typename Context, typename OutputContext, typename Iter, typename OutputIter> 01066 inline void broadcast_packed_range (const Context *context1, 01067 Iter range_begin, 01068 const Iter range_end, 01069 OutputContext *context2, 01070 OutputIter out, 01071 const unsigned int root_id = 0) const; 01072 01080 #include "libmesh/parallel_communicator_specializations" 01081 01082 }; // class Communicator 01083 01084 // PostWaitWork specialization for copying from temporary to 01085 // output containers 01086 template <typename Container, typename OutputIter> 01087 struct PostWaitCopyBuffer : public PostWaitWork { 01088 PostWaitCopyBuffer(const Container& buffer, const OutputIter out) 01089 : _buf(buffer), _out(out) {} 01090 01091 virtual void run() { std::copy(_buf.begin(), _buf.end(), _out); } 01092 01093 private: 01094 const Container& _buf; 01095 OutputIter _out; 01096 }; 01097 01098 // PostWaitWork specialization for unpacking received buffers. 01099 template <typename Container, typename Context, typename OutputIter> 01100 struct PostWaitUnpackBuffer : public PostWaitWork { 01101 PostWaitUnpackBuffer(const Container& buffer, Context *context, OutputIter out) : 01102 _buf(buffer), _context(context), _out(out) {} 01103 01104 virtual void run() { Parallel::unpack_range(_buf, _context, _out); }; 01105 01106 private: 01107 const Container& _buf; 01108 Context *_context; 01109 OutputIter _out; 01110 }; 01111 01112 01113 // PostWaitWork specialization for freeing no-longer-needed buffers. 01114 template <typename Container> 01115 struct PostWaitDeleteBuffer : public PostWaitWork { 01116 PostWaitDeleteBuffer(Container* buffer) : _buf(buffer) {} 01117 01118 virtual void run() { delete _buf; }; 01119 01120 private: 01121 Container* _buf; 01122 }; 01123 01124 } // namespace Parallel 01125 01129 extern Parallel::Communicator CommWorld; 01130 01131 } // namespace libMesh 01132 01133 // Define all the implementations separately; users might want to look 01134 // through this file for APIs, and it's long enough already. 01135 01136 #include "libmesh/parallel_implementation.h" 01137 01138 #endif // LIBMESH_PARALLEL_H
Site Created By: libMesh Developers
Last modified: February 05 2013 19:54:48 UTC
Hosted By: