$extrastylesheet
00001 // The libMesh Finite Element Library. 00002 // Copyright (C) 2002-2014 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, cast_int 00024 #include "libmesh/libmesh_logging.h" 00025 #include "libmesh/auto_ptr.h" 00026 00027 // C++ includes 00028 #include <cstddef> 00029 #include <climits> 00030 #include <iterator> 00031 #include <limits> 00032 #include <map> 00033 #include <set> 00034 #include <string> 00035 #include <vector> 00036 00037 namespace libMesh 00038 { 00039 00040 00041 // Macro to identify and debug functions which should only be called in 00042 // parallel on every processor at once 00043 00044 #undef parallel_only 00045 #ifndef NDEBUG 00046 #define parallel_only() do { \ 00047 libmesh_deprecated(); \ 00048 libmesh_assert(CommWorld.verify(std::string(__FILE__).size())); \ 00049 libmesh_assert(CommWorld.verify(std::string(__FILE__))); \ 00050 libmesh_assert(CommWorld.verify(__LINE__)); } while (0) 00051 #else 00052 #define parallel_only() ((void) 0) 00053 #endif 00054 00055 #undef libmesh_parallel_only 00056 #ifndef NDEBUG 00057 #define libmesh_parallel_only(comm_obj) do { \ 00058 libmesh_assert((comm_obj).verify(std::string(__FILE__).size())); \ 00059 libmesh_assert((comm_obj).verify(std::string(__FILE__))); \ 00060 libmesh_assert((comm_obj).verify(__LINE__)); } while (0) 00061 #else 00062 #define libmesh_parallel_only(comm_obj) ((void) 0) 00063 #endif 00064 00065 // Macro to identify and debug functions which should only be called in 00066 // parallel on every processor at once 00067 00068 #undef parallel_only_on 00069 #ifndef NDEBUG 00070 #define parallel_only_on(comm_arg) do { \ 00071 libmesh_deprecated(); \ 00072 libmesh_assert(CommWorld.verify(std::string(__FILE__).size(), comm_arg)); \ 00073 libmesh_assert(CommWorld.verify(std::string(__FILE__), comm_arg)); \ 00074 libmesh_assert(CommWorld.verify(__LINE__), comm_arg); } while (0) 00075 #else 00076 #define parallel_only_on(comm_arg) ((void) 0) 00077 #endif 00078 00079 #undef libmesh_parallel_only_on 00080 #ifndef NDEBUG 00081 #define libmesh_parallel_only_on(comm_obj,comm_arg) do { \ 00082 libmesh_assert(comm_obj.verify(std::string(__FILE__).size(), comm_arg)); \ 00083 libmesh_assert(comm_obj.verify(std::string(__FILE__), comm_arg)); \ 00084 libmesh_assert(comm_obj.verify(__LINE__), comm_arg); } while (0) 00085 #else 00086 #define libmesh_parallel_only_on(comm_obj,comm_arg) ((void) 0) 00087 #endif 00088 00096 namespace Parallel 00097 { 00098 //------------------------------------------------------------------- 00102 class Communicator; 00103 class DataType; 00104 class Request; 00105 class Status; 00106 00107 #ifdef LIBMESH_HAVE_MPI 00108 //------------------------------------------------------------------- 00112 typedef MPI_Datatype data_type; 00113 00117 typedef MPI_Request request; 00118 00122 typedef MPI_Status status; 00123 00127 typedef MPI_Comm communicator; 00128 00133 template <typename T> 00134 inline data_type dataplusint_type(); 00135 00139 template <typename T> 00140 class DataPlusInt 00141 { 00142 public: 00143 T val; 00144 int rank; 00145 }; 00146 00150 const unsigned int any_source = 00151 static_cast<unsigned int>(MPI_ANY_SOURCE); 00152 00153 00154 #else 00155 00156 // These shouldn't actually be needed, but must be 00157 // unique types for function overloading to work 00158 // properly. 00159 struct data_type { /* unsigned int t; */ }; 00160 struct request { /* unsigned int r; */ }; 00161 struct status { /* unsigned int s; */ }; 00162 typedef int communicator; // Must match petsc-nompi definition 00163 00164 const unsigned int any_source=0; 00165 #endif // LIBMESH_HAVE_MPI 00166 00167 00168 00169 //------------------------------------------------------------------- 00173 class MessageTag 00174 { 00175 public: 00176 00180 static const int invalid_tag = INT_MIN; 00181 00186 explicit MessageTag(int tagvalue = invalid_tag) 00187 : _tagvalue(tagvalue), _comm(NULL) {} 00188 00193 MessageTag(const MessageTag& other); 00194 00199 ~MessageTag(); 00200 00201 int value() const { 00202 return _tagvalue; 00203 } 00204 00205 private: 00206 int _tagvalue; 00207 const Communicator *_comm; 00208 00209 // Constructor for reference-counted unique tags 00210 MessageTag(int tagvalue, const Communicator *comm) 00211 : _tagvalue(tagvalue), _comm(comm) {} 00212 00213 // Let Communicator handle the reference counting 00214 friend class Communicator; 00215 }; 00216 00217 00218 //------------------------------------------------------------------- 00222 #ifdef LIBMESH_HAVE_MPI 00223 const MessageTag any_tag = MessageTag(MPI_ANY_TAG); 00224 #else 00225 const MessageTag any_tag = MessageTag(-1); 00226 #endif 00227 00228 const MessageTag no_tag = MessageTag(0); 00229 00230 00231 //------------------------------------------------------------------- 00235 class DataType 00236 { 00237 public: 00238 DataType () : _datatype() {} 00239 00240 DataType (const DataType &other) : 00241 _datatype(other._datatype) 00242 {} 00243 00244 DataType (const data_type &type) : 00245 _datatype(type) 00246 {} 00247 00248 #ifdef LIBMESH_HAVE_MPI 00249 DataType (const DataType &other, unsigned int count) 00250 { 00251 MPI_Type_contiguous(count, other._datatype, &_datatype); 00252 this->commit(); 00253 } 00254 #else 00255 DataType (const DataType &, unsigned int) 00256 { 00257 } 00258 #endif 00259 00260 DataType & operator = (const DataType &other) 00261 { _datatype = other._datatype; return *this; } 00262 00263 DataType & operator = (const data_type &type) 00264 { _datatype = type; return *this; } 00265 00266 operator const data_type & () const 00267 { return _datatype; } 00268 00269 operator data_type & () 00270 { return _datatype; } 00271 00272 // operator data_type const * () const 00273 // { return &_datatype; } 00274 00275 // operator data_type * () 00276 // { return &_datatype; } 00277 00278 void commit () 00279 { 00280 #ifdef LIBMESH_HAVE_MPI 00281 MPI_Type_commit (&_datatype); 00282 #endif 00283 } 00284 00285 void free () 00286 { 00287 #ifdef LIBMESH_HAVE_MPI 00288 MPI_Type_free (&_datatype); 00289 #endif 00290 } 00291 00292 protected: 00293 00294 data_type _datatype; 00295 }; 00296 00297 00298 //------------------------------------------------------------------- 00299 00300 #ifdef LIBMESH_HAVE_CXX11 00301 // A C++03-compatible replacement for std::false_type 00302 struct false_type 00303 { 00304 static const bool value = false; 00305 typedef bool value_type; 00306 typedef false_type type; 00307 operator value_type() const { return value; } 00308 }; 00309 00310 // Templated helper class to be used with static_assert. 00311 template<typename T> 00312 struct dependent_false : false_type 00313 {}; 00314 #endif 00315 00323 template <typename T> 00324 class StandardType : public DataType 00325 { 00326 #ifdef LIBMESH_HAVE_CXX11 00327 // Get a slightly better compiler diagnostic if we have C++11 00328 static_assert(dependent_false<T>::value, 00329 "Only specializations of StandardType may be used, did you forget to include a header file (e.g. parallel_algebra.h)?"); 00330 #endif 00331 00332 /* 00333 * The unspecialized class is useless, so we make its constructor 00334 * private to catch mistakes at compile-time rather than link-time. 00335 * Specializations should have a public constructor of the same 00336 * form. 00337 */ 00338 private: 00339 StandardType(const T* example = NULL); 00340 }; 00341 00342 /* 00343 * The unspecialized class gives default, lowest-common-denominator 00344 * attributes, for values which can't be used with Parallel min/max. 00345 * Specialized classes can set this to true, and should define 00346 * the lowest and highest values possible for the type. 00347 */ 00348 template<typename T> 00349 struct Attributes 00350 { 00351 static const bool has_min_max = false; 00352 static void set_lowest(T&) {} 00353 static void set_highest(T&) {} 00354 }; 00355 00356 00357 00358 //------------------------------------------------------------------- 00363 class Status 00364 { 00365 public: 00366 Status (); 00367 00368 explicit Status (const data_type &type); 00369 00370 explicit Status (const status &status); 00371 00372 Status (const status &status, 00373 const data_type &type); 00374 00375 Status (const Status &status); 00376 00377 Status (const Status &status, 00378 const data_type &type); 00379 00380 status * get() { return &_status; } 00381 00382 status const * get() const { return &_status; } 00383 00384 int source () const; 00385 00386 int tag () const; 00387 00388 data_type& datatype () { return _datatype; } 00389 00390 const data_type& datatype () const { return _datatype; } 00391 00392 unsigned int size (const data_type &type) const; 00393 00394 unsigned int size () const; 00395 00396 private: 00397 00398 status _status; 00399 data_type _datatype; 00400 }; 00401 00402 00403 //------------------------------------------------------------------- 00408 struct PostWaitWork { 00409 virtual ~PostWaitWork() {} 00410 00411 virtual void run() {} 00412 }; 00413 00414 00415 //------------------------------------------------------------------- 00419 class Request 00420 { 00421 public: 00422 Request (); 00423 00424 Request (const request &r); 00425 00426 Request (const Request &other); 00427 00428 void cleanup(); 00429 00430 Request & operator = (const Request &other); 00431 00432 Request & operator = (const request &r); 00433 00434 ~Request (); 00435 00436 request* get() { return &_request; } 00437 00438 const request* get() const { return &_request; } 00439 00440 Status wait (); 00441 00442 bool test (); 00443 00444 bool test (status &status); 00445 00446 void add_prior_request(const Request& req); 00447 00448 void add_post_wait_work(PostWaitWork* work); 00449 00450 private: 00451 request _request; 00452 00453 // Breaking non-blocking sends into multiple requests can require chaining 00454 // multiple requests into a single Request 00455 UniquePtr<Request> _prior_request; 00456 00457 // post_wait_work->first is a vector of work to do after a wait 00458 // finishes; post_wait_work->second is a reference count so that 00459 // Request objects will behave roughly like a shared_ptr and be 00460 // usable in STL containers 00461 std::pair<std::vector <PostWaitWork* >, unsigned int>* post_wait_work; 00462 }; 00463 00467 inline Status wait (Request &r) { return r.wait(); } 00468 00472 inline void wait (std::vector<Request> &r) 00473 { for (unsigned int i=0; i<r.size(); i++) r[i].wait(); } 00474 00475 00480 template <typename T> 00481 struct BufferType; 00482 00488 template <typename T> 00489 struct BufferType<T*> { 00490 typedef typename BufferType<const T*>::type type; 00491 }; 00492 00501 template <typename T, typename buffertype, typename Context> 00502 void pack(const T* object, 00503 typename std::vector<buffertype>& data, 00504 const Context* context); 00505 00514 template <typename T, typename Context> 00515 unsigned int packable_size(const T*, const Context*); 00516 00528 template <typename T, typename BufferIter> 00529 unsigned int packed_size(const T*, 00530 BufferIter); 00531 00540 template <typename T, typename BufferIter, typename Context> 00541 void unpack(BufferIter in, T** out, Context* ctx); 00542 00547 template <typename Context, typename buffertype, typename OutputIter> 00548 inline void unpack_range (const typename std::vector<buffertype>& buffer, 00549 Context *context, 00550 OutputIter out); 00551 00556 template <typename Context, typename buffertype, typename Iter> 00557 inline Iter pack_range (const Context *context, 00558 Iter range_begin, 00559 const Iter range_end, 00560 typename std::vector<buffertype>& buffer); 00561 00566 template <typename Context, typename Iter> 00567 inline std::size_t packed_range_size (const Context *context, 00568 Iter range_begin, 00569 const Iter range_end); 00570 00571 //------------------------------------------------------------------- 00579 class Communicator 00580 { 00581 // Basic operations: 00582 public: 00583 00587 Communicator (); 00588 00589 /* 00590 * Constructor from MPI_Comm 00591 */ 00592 explicit Communicator (const communicator &comm); 00593 00594 /* 00595 * NON-VIRTUAL destructor 00596 */ 00597 ~Communicator (); 00598 00599 /* 00600 * Create a new communicator between some subset of \p this 00601 */ 00602 void split(int color, int key, Communicator &target) const; 00603 00604 /* 00605 * Create a new duplicate of \p this communicator 00606 */ 00607 void duplicate(const Communicator &comm); 00608 00609 /* 00610 * Create a new duplicate of an MPI communicator 00611 */ 00612 void duplicate(const communicator &comm); 00613 00614 communicator& get() { return _communicator; } 00615 00616 const communicator& get() const { return _communicator; } 00617 00624 MessageTag get_unique_tag(int tagvalue) const; 00625 00630 void reference_unique_tag(int tagvalue) const; 00631 00636 void dereference_unique_tag(int tagvalue) const; 00637 00641 void clear(); 00642 00643 Communicator& operator= (const communicator &comm); 00644 00645 unsigned int rank() const { return _rank; } 00646 00647 unsigned int size() const { return _size; } 00648 00652 enum SendMode { DEFAULT=0, SYNCHRONOUS }; 00653 00654 private: 00655 00656 // Don't use the copy constructor, just copy by reference or 00657 // pointer - it's too hard to keep a common used_tag_values if 00658 // each communicator is shared by more than one Communicator 00659 explicit Communicator (const Communicator &); 00660 00665 void assign(const communicator &comm); 00666 00667 communicator _communicator; 00668 unsigned int _rank, _size; 00669 SendMode _send_mode; 00670 00671 // mutable used_tag_values - not thread-safe, but then Parallel:: 00672 // isn't thread-safe in general. 00673 mutable std::map<int, unsigned int> used_tag_values; 00674 bool _I_duped_it; 00675 00676 // Communication operations: 00677 public: 00678 00682 void send_mode (const SendMode sm) { _send_mode = sm; } 00683 00687 SendMode send_mode() const { return _send_mode; } 00688 00692 void barrier () const; 00693 00698 template <typename T> 00699 bool verify(const T &r) const; 00700 00706 template <typename T> 00707 bool semiverify(const T *r) const; 00708 00713 template <typename T> 00714 void min(T &r) const; 00715 00721 template <typename T> 00722 void minloc(T &r, 00723 unsigned int &min_id) const; 00724 00730 template <typename T> 00731 void minloc(std::vector<T> &r, 00732 std::vector<unsigned int> &min_id) const; 00733 00738 template <typename T> 00739 void max(T &r) const; 00740 00746 template <typename T> 00747 void maxloc(T &r, 00748 unsigned int &max_id) const; 00749 00755 template <typename T> 00756 void maxloc(std::vector<T> &r, 00757 std::vector<unsigned int> &max_id) const; 00758 00763 template <typename T> 00764 void sum(T &r) const; 00765 00771 template <typename T> 00772 void set_union(T &data, const unsigned int root_id) const; 00773 00778 template <typename T> 00779 void set_union(T &data) const; 00780 00785 status probe (const unsigned int src_processor_id, 00786 const MessageTag &tag=any_tag) const; 00787 00791 template <typename T> 00792 void send (const unsigned int dest_processor_id, 00793 T &buf, 00794 const MessageTag &tag=no_tag) const; 00795 00799 template <typename T> 00800 void send (const unsigned int dest_processor_id, 00801 T &buf, 00802 Request &req, 00803 const MessageTag &tag=no_tag) const; 00804 00808 template <typename T> 00809 void send (const unsigned int dest_processor_id, 00810 T &buf, 00811 const DataType &type, 00812 const MessageTag &tag=no_tag) const; 00813 00817 template <typename T> 00818 void send (const unsigned int dest_processor_id, 00819 T &buf, 00820 const DataType &type, 00821 Request &req, 00822 const MessageTag &tag=no_tag) const; 00823 00827 template <typename T> 00828 Status receive (const unsigned int dest_processor_id, 00829 T &buf, 00830 const MessageTag &tag=any_tag) const; 00831 00835 template <typename T> 00836 void receive (const unsigned int dest_processor_id, 00837 T &buf, 00838 Request &req, 00839 const MessageTag &tag=any_tag) const; 00840 00844 template <typename T> 00845 Status receive (const unsigned int dest_processor_id, 00846 T &buf, 00847 const DataType &type, 00848 const MessageTag &tag=any_tag) const; 00849 00853 template <typename T> 00854 void receive (const unsigned int dest_processor_id, 00855 T &buf, 00856 const DataType &type, 00857 Request &req, 00858 const MessageTag &tag=any_tag) const; 00859 00873 template <typename Context, typename Iter> 00874 void send_packed_range (const unsigned int dest_processor_id, 00875 const Context *context, 00876 Iter range_begin, 00877 const Iter range_end, 00878 const MessageTag &tag=no_tag) const; 00879 00893 template <typename Context, typename Iter> 00894 void send_packed_range (const unsigned int dest_processor_id, 00895 const Context *context, 00896 Iter range_begin, 00897 const Iter range_end, 00898 Request &req, 00899 const MessageTag &tag=no_tag) const; 00900 00927 template <typename Context, typename OutputIter> 00928 void receive_packed_range (const unsigned int dest_processor_id, 00929 Context *context, 00930 OutputIter out, 00931 const MessageTag &tag=any_tag) const; 00932 00937 // template <typename Context, typename OutputIter> 00938 // void receive_packed_range (const unsigned int dest_processor_id, 00939 // Context *context, 00940 // OutputIter out, 00941 // Request &req, 00942 // const MessageTag &tag=any_tag) const; 00943 00948 template <typename T1, typename T2> 00949 void send_receive(const unsigned int dest_processor_id, 00950 T1 &send, 00951 const unsigned int source_processor_id, 00952 T2 &recv, 00953 const MessageTag &send_tag = no_tag, 00954 const MessageTag &recv_tag = any_tag) const; 00955 00992 template <typename Context1, typename RangeIter, typename Context2, typename OutputIter> 00993 void send_receive_packed_range(const unsigned int dest_processor_id, 00994 const Context1* context1, 00995 RangeIter send_begin, 00996 const RangeIter send_end, 00997 const unsigned int source_processor_id, 00998 Context2* context2, 00999 OutputIter out, 01000 const MessageTag &send_tag = no_tag, 01001 const MessageTag &recv_tag = any_tag) const; 01002 01008 template <typename T1, typename T2> 01009 void send_receive(const unsigned int dest_processor_id, 01010 T1 &send, 01011 const DataType &type1, 01012 const unsigned int source_processor_id, 01013 T2 &recv, 01014 const DataType &type2, 01015 const MessageTag &send_tag = no_tag, 01016 const MessageTag &recv_tag = any_tag) const; 01017 01022 template <typename T> 01023 inline void gather(const unsigned int root_id, 01024 T send, 01025 std::vector<T> &recv) const; 01026 01049 template <typename T> 01050 inline void gather(const unsigned int root_id, 01051 std::vector<T> &r) const; 01052 01057 template <typename T> 01058 inline void allgather(T send, 01059 std::vector<T> &recv) const; 01060 01061 01086 template <typename T> 01087 inline void allgather(std::vector<T> &r, 01088 const bool identical_buffer_sizes = false) const; 01089 01090 //------------------------------------------------------------------- 01095 template <typename Context, typename Iter, typename OutputIter> 01096 inline void gather_packed_range (const unsigned int root_id, 01097 Context *context, 01098 Iter range_begin, 01099 const Iter range_end, 01100 OutputIter out) const; 01101 01106 template <typename Context, typename Iter, typename OutputIter> 01107 inline void allgather_packed_range (Context *context, 01108 Iter range_begin, 01109 const Iter range_end, 01110 OutputIter out) const; 01111 01117 template <typename T> 01118 inline void alltoall(std::vector<T> &r) const; 01119 01128 template <typename T> 01129 inline void broadcast(T &data, const unsigned int root_id=0) const; 01130 01148 template <typename Context, typename OutputContext, typename Iter, typename OutputIter> 01149 inline void broadcast_packed_range (const Context *context1, 01150 Iter range_begin, 01151 const Iter range_end, 01152 OutputContext *context2, 01153 OutputIter out, 01154 const unsigned int root_id = 0) const; 01155 01163 #include "libmesh/parallel_communicator_specializations" 01164 01165 }; // class Communicator 01166 01167 // FakeCommunicator for debugging inappropriate CommWorld uses 01168 class FakeCommunicator 01169 { 01170 operator Communicator& () 01171 { 01172 libmesh_not_implemented(); 01173 static Communicator temp; 01174 return temp; 01175 } 01176 }; 01177 01178 // PostWaitWork specialization for copying from temporary to 01179 // output containers 01180 template <typename Container, typename OutputIter> 01181 struct PostWaitCopyBuffer : public PostWaitWork { 01182 PostWaitCopyBuffer(const Container& buffer, const OutputIter out) 01183 : _buf(buffer), _out(out) {} 01184 01185 virtual void run() { std::copy(_buf.begin(), _buf.end(), _out); } 01186 01187 private: 01188 const Container& _buf; 01189 OutputIter _out; 01190 }; 01191 01192 // PostWaitWork specialization for unpacking received buffers. 01193 template <typename Container, typename Context, typename OutputIter> 01194 struct PostWaitUnpackBuffer : public PostWaitWork { 01195 PostWaitUnpackBuffer(const Container& buffer, Context *context, OutputIter out) : 01196 _buf(buffer), _context(context), _out(out) {} 01197 01198 virtual void run() { Parallel::unpack_range(_buf, _context, _out); } 01199 01200 private: 01201 const Container& _buf; 01202 Context *_context; 01203 OutputIter _out; 01204 }; 01205 01206 01207 // PostWaitWork specialization for freeing no-longer-needed buffers. 01208 template <typename Container> 01209 struct PostWaitDeleteBuffer : public PostWaitWork { 01210 PostWaitDeleteBuffer(Container* buffer) : _buf(buffer) {} 01211 01212 virtual void run() { delete _buf; } 01213 01214 private: 01215 Container* _buf; 01216 }; 01217 01218 } // namespace Parallel 01219 01233 #ifdef LIBMESH_DISABLE_COMMWORLD 01234 extern Parallel::FakeCommunicator CommWorld; 01235 #define LIBMESH_CAN_DEFAULT_TO_COMMWORLD 01236 #else 01237 extern Parallel::Communicator CommWorld; 01238 #define LIBMESH_CAN_DEFAULT_TO_COMMWORLD = libMesh::CommWorld 01239 #endif 01240 01241 } // namespace libMesh 01242 01243 // Define all the implementations separately; users might want to look 01244 // through this file for APIs, and it's long enough already. 01245 01246 #include "libmesh/parallel_implementation.h" 01247 01248 #endif // LIBMESH_PARALLEL_H