parallel.h
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2017 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
3 
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either
7 // version 2.1 of the License, or (at your option) any later version.
8 
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // Lesser General Public License for more details.
13 
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 
18 
19 #ifndef LIBMESH_PARALLEL_H
20 #define LIBMESH_PARALLEL_H
21 
22 // libMesh Includes
23 #include "libmesh/libmesh_common.h" // libmesh_assert, cast_int
25 #include "libmesh/auto_ptr.h"
26 
27 // C++ includes
28 #include <cstddef>
29 #include <climits>
30 #include <iterator>
31 #include <limits>
32 #include <map>
33 #include <set>
34 #include <string>
35 #include <vector>
36 
37 namespace libMesh
38 {
39 
40 
41 // Macro to identify and debug functions which should only be called in
42 // parallel on every processor at once
43 
44 #undef parallel_only
45 #ifndef NDEBUG
46 #define parallel_only() do { \
47  libmesh_deprecated(); \
48  libmesh_assert(CommWorld.verify(std::string(__FILE__).size())); \
49  libmesh_assert(CommWorld.verify(std::string(__FILE__))); \
50  libmesh_assert(CommWorld.verify(__LINE__)); } while (0)
51 #else
52 #define parallel_only() ((void) 0)
53 #endif
54 
55 #undef libmesh_parallel_only
56 #ifndef NDEBUG
57 #define libmesh_parallel_only(comm_obj) do { \
58  libmesh_assert((comm_obj).verify(std::string(__FILE__).size())); \
59  libmesh_assert((comm_obj).verify(std::string(__FILE__))); \
60  libmesh_assert((comm_obj).verify(__LINE__)); } while (0)
61 #else
62 #define libmesh_parallel_only(comm_obj) ((void) 0)
63 #endif
64 
65 // Macro to identify and debug functions which should only be called in
66 // parallel on every processor at once
67 
68 #undef parallel_only_on
69 #ifndef NDEBUG
70 #define parallel_only_on(comm_arg) do { \
71  libmesh_deprecated(); \
72  libmesh_assert(CommWorld.verify(std::string(__FILE__).size(), comm_arg)); \
73  libmesh_assert(CommWorld.verify(std::string(__FILE__), comm_arg)); \
74  libmesh_assert(CommWorld.verify(__LINE__), comm_arg); } while (0)
75 #else
76 #define parallel_only_on(comm_arg) ((void) 0)
77 #endif
78 
79 #undef libmesh_parallel_only_on
80 #ifndef NDEBUG
81 #define libmesh_parallel_only_on(comm_obj,comm_arg) do { \
82  libmesh_assert(comm_obj.verify(std::string(__FILE__).size(), comm_arg)); \
83  libmesh_assert(comm_obj.verify(std::string(__FILE__), comm_arg)); \
84  libmesh_assert(comm_obj.verify(__LINE__), comm_arg); } while (0)
85 #else
86 #define libmesh_parallel_only_on(comm_obj,comm_arg) ((void) 0)
87 #endif
88 
96 namespace Parallel
97 {
98 //-------------------------------------------------------------------
102 class Communicator;
103 class DataType;
104 class Request;
105 class Status;
106 
107 #ifdef LIBMESH_HAVE_MPI
108 
112 #ifndef NDEBUG
113 #define libmesh_assert_mpi_success(error_code) \
114  do \
115  { \
116  if (error_code != MPI_SUCCESS) \
117  { \
118  char libmesh_mpi_error_string[MPI_MAX_ERROR_STRING+1]; \
119  int libmesh_mpi_error_string_len; \
120  MPI_Error_string(error_code, libmesh_mpi_error_string, \
121  &libmesh_mpi_error_string_len); \
122  libmesh_assert_equal_to_msg(error_code, MPI_SUCCESS, \
123  libmesh_mpi_error_string); \
124  } \
125  } \
126  while(0)
127 
128 #else
129 
130 #define libmesh_assert_mpi_success(error_code) ((void) 0)
131 
132 #endif
133 
134 
135 
136 // Only catch MPI return values when asserts are active.
137 #ifndef NDEBUG
138 #define libmesh_call_mpi(mpi_call) \
139  do \
140  { \
141  unsigned int libmesh_mpi_error_code = mpi_call; \
142  libmesh_assert_mpi_success (libmesh_mpi_error_code); \
143  } \
144  while(0)
145 
146 #else
147 
148 #define libmesh_call_mpi(mpi_call) \
149  do \
150  { \
151  mpi_call; \
152  } \
153  while(0)
154 #endif
155 
156 
157 
158 //-------------------------------------------------------------------
162 typedef MPI_Datatype data_type;
163 
167 typedef MPI_Request request;
168 
172 typedef MPI_Status status;
173 
177 typedef MPI_Comm communicator;
178 
183 template <typename T>
184 inline data_type dataplusint_type();
185 
189 template <typename T>
191 {
192 public:
193  T val;
194  int rank;
195 };
196 
200 const unsigned int any_source =
201  static_cast<unsigned int>(MPI_ANY_SOURCE);
202 
203 
204 #else
205 
206 // These shouldn't actually be needed, but must be
207 // unique types for function overloading to work
208 // properly.
209 struct data_type { /* unsigned int t; */ };
210 struct request { /* unsigned int r; */ };
211 struct status { /* unsigned int s; */ };
212 typedef int communicator; // Must match petsc-nompi definition
213 
214 const unsigned int any_source=0;
215 #endif // LIBMESH_HAVE_MPI
216 
217 
218 
219 //-------------------------------------------------------------------
224 {
225 public:
226 
230  static const int invalid_tag = INT_MIN;
231 
236  explicit MessageTag(int tagvalue = invalid_tag)
237  : _tagvalue(tagvalue), _comm(libmesh_nullptr) {}
238 
243  MessageTag(const MessageTag & other);
244 
249  ~MessageTag();
250 
251  int value() const {
252  return _tagvalue;
253  }
254 
255 private:
258 
259  // Constructor for reference-counted unique tags
260  MessageTag(int tagvalue, const Communicator * comm)
261  : _tagvalue(tagvalue), _comm(comm) {}
262 
263  // Let Communicator handle the reference counting
264  friend class Communicator;
265 };
266 
267 
268 //-------------------------------------------------------------------
272 #ifdef LIBMESH_HAVE_MPI
273 const MessageTag any_tag = MessageTag(MPI_ANY_TAG);
274 #else
275 const MessageTag any_tag = MessageTag(-1);
276 #endif
277 
279 
280 
281 //-------------------------------------------------------------------
285 class DataType
286 {
287 public:
288  DataType () : _datatype() {}
289 
290  DataType (const DataType & other) :
291  _datatype(other._datatype)
292  {}
293 
294  DataType (const data_type & type) :
295  _datatype(type)
296  {}
297 
298 #ifdef LIBMESH_HAVE_MPI
299  DataType (const DataType & other, unsigned int count)
300  {
301  // FIXME - if we nest an inner type here will we run into bug
302  // https://github.com/libMesh/libmesh/issues/631 again?
303  MPI_Type_contiguous(count, other._datatype, &_datatype);
304  this->commit();
305  }
306 #else
307  DataType (const DataType &, unsigned int)
308  {
309  }
310 #endif
311 
312  DataType & operator = (const DataType & other)
313  { _datatype = other._datatype; return *this; }
314 
315  DataType & operator = (const data_type & type)
316  { _datatype = type; return *this; }
317 
318  operator const data_type & () const
319  { return _datatype; }
320 
321  operator data_type & ()
322  { return _datatype; }
323 
324  // operator data_type const * () const
325  // { return &_datatype; }
326 
327  // operator data_type * ()
328  // { return &_datatype; }
329 
330  void commit ()
331  {
332 #ifdef LIBMESH_HAVE_MPI
333  MPI_Type_commit (&_datatype);
334 #endif
335  }
336 
337  void free ()
338  {
339 #ifdef LIBMESH_HAVE_MPI
340  MPI_Type_free (&_datatype);
341 #endif
342  }
343 
344 protected:
345 
346  data_type _datatype;
347 };
348 
349 
350 //-------------------------------------------------------------------
351 
352 #ifdef LIBMESH_HAVE_CXX11
353 // A C++03-compatible replacement for std::false_type
355 {
356  static const bool value = false;
357  typedef bool value_type;
358  typedef false_type type;
359  operator value_type() const { return value; }
360 };
361 
362 // Templated helper class to be used with static_assert.
363 template<typename T>
365 {};
366 #endif
367 
375 template <typename T>
376 class StandardType : public DataType
377 {
378 #ifdef LIBMESH_HAVE_CXX11
379  // Get a slightly better compiler diagnostic if we have C++11
380  static_assert(dependent_false<T>::value,
381  "Only specializations of StandardType may be used, did you forget to include a header file (e.g. parallel_algebra.h)?");
382 #endif
383 
384  /*
385  * The unspecialized class is useless, so we make its constructor
386  * private to catch mistakes at compile-time rather than link-time.
387  * Specializations should have a public constructor of the same
388  * form.
389  */
390 private:
391  StandardType(const T * example = libmesh_nullptr);
392 };
393 
394 /*
395  * The unspecialized class gives default, lowest-common-denominator
396  * attributes, for values which can't be used with Parallel min/max.
397  * Specialized classes can set this to true, and should define
398  * the lowest and highest values possible for the type.
399  */
400 template<typename T>
402 {
403  static const bool has_min_max = false;
404  static void set_lowest(T &) {}
405  static void set_highest(T &) {}
406 };
407 
408 
409 
410 //-------------------------------------------------------------------
415 class Status
416 {
417 public:
418  Status ();
419 
420  explicit Status (const data_type & type);
421 
422  explicit Status (const status & status);
423 
424  Status (const status & status,
425  const data_type & type);
426 
427  Status (const Status & status);
428 
429  Status (const Status & status,
430  const data_type & type);
431 
432  status * get() { return &_status; }
433 
434  status const * get() const { return &_status; }
435 
436  int source () const;
437 
438  int tag () const;
439 
440  data_type & datatype () { return _datatype; }
441 
442  const data_type & datatype () const { return _datatype; }
443 
444  unsigned int size (const data_type & type) const;
445 
446  unsigned int size () const;
447 
448 private:
449 
450  status _status;
451  data_type _datatype;
452 };
453 
454 
455 //-------------------------------------------------------------------
460 struct PostWaitWork {
461  virtual ~PostWaitWork() {}
462 
463  virtual void run() {}
464 };
465 
466 
467 //-------------------------------------------------------------------
471 class Request
472 {
473 public:
474  Request ();
475 
476  Request (const request & r);
477 
478  Request (const Request & other);
479 
480  void cleanup();
481 
482  Request & operator = (const Request & other);
483 
484  Request & operator = (const request & r);
485 
486  ~Request ();
487 
488  request * get() { return &_request; }
489 
490  const request * get() const { return &_request; }
491 
492  Status wait ();
493 
494  bool test ();
495 
496  bool test (status & status);
497 
498  void add_prior_request(const Request & req);
499 
500  void add_post_wait_work(PostWaitWork * work);
501 
502 private:
503  request _request;
504 
505  // Breaking non-blocking sends into multiple requests can require chaining
506  // multiple requests into a single Request
508 
509  // post_wait_work->first is a vector of work to do after a wait
510  // finishes; post_wait_work->second is a reference count so that
511  // Request objects will behave roughly like a shared_ptr and be
512  // usable in STL containers
513  std::pair<std::vector <PostWaitWork * >, unsigned int> * post_wait_work;
514 };
515 
519 inline Status wait (Request & r) { return r.wait(); }
520 
524 inline void wait (std::vector<Request> & r)
525 { for (std::size_t i=0; i<r.size(); i++) r[i].wait(); }
526 
527 
535 template <typename T>
536 class Packing {
537 public:
538  // Should be an MPI sendable type in specializations, e.g.
539  // typedef char buffer_type;
540  // typedef unsigned int buffer_type;
541 
542  // Should copy an encoding of the provided object into the provided
543  // output iterator (which is of type buffer_type)
544  template <typename OutputIter, typename Context>
545  static void pack(const T & object,
546  OutputIter data_out,
547  const Context * context);
548 
549  // Should return the number of array entries (of type buffer_type)
550  // required to encode the provided object
551  template <typename Context>
552  static unsigned int packable_size(const T & object,
553  const Context * context);
554 
555  // Should return the number of array entries which were used to
556  // encode the provided serialization of an object which begins at
557  // \p iter
558  template <typename BufferIter>
559  static unsigned int packed_size(BufferIter iter);
560 
561  // Decode a potentially-variable-size object from a subsequence of a
562  // data array, returning a heap-allocated pointer to the result.
563  template <typename BufferIter, typename Context>
564  static T unpack(BufferIter in, Context * ctx);
565 };
566 
567 
572 template <typename Context, typename buffertype,
573  typename OutputIter, typename T>
574 inline void unpack_range (const typename std::vector<buffertype> & buffer,
575  Context * context,
576  OutputIter out,
577  const T * output_type /* used only to infer T */);
578 
587 template <typename Context, typename buffertype, typename Iter>
588 inline Iter pack_range (const Context * context,
589  Iter range_begin,
590  const Iter range_end,
591  typename std::vector<buffertype> & buffer,
592  std::size_t approx_buffer_size = 1000000);
593 
598 template <typename Context, typename Iter>
599 inline std::size_t packed_range_size (const Context * context,
600  Iter range_begin,
601  const Iter range_end);
602 
603 //-------------------------------------------------------------------
612 {
613  // Basic operations:
614 public:
615 
619  Communicator ();
620 
621  /*
622  * Constructor from MPI_Comm
623  */
624  explicit Communicator (const communicator & comm);
625 
626  /*
627  * NON-VIRTUAL destructor
628  */
629  ~Communicator ();
630 
631  /*
632  * Create a new communicator between some subset of \p this
633  */
634  void split(int color, int key, Communicator & target) const;
635 
636  /*
637  * Create a new duplicate of \p this communicator
638  */
639  void duplicate(const Communicator & comm);
640 
641  /*
642  * Create a new duplicate of an MPI communicator
643  */
644  void duplicate(const communicator & comm);
645 
646  communicator & get() { return _communicator; }
647 
648  const communicator & get() const { return _communicator; }
649 
656  MessageTag get_unique_tag(int tagvalue) const;
657 
662  void reference_unique_tag(int tagvalue) const;
663 
668  void dereference_unique_tag(int tagvalue) const;
669 
673  void clear();
674 
675  Communicator & operator= (const communicator & comm);
676 
677  unsigned int rank() const { return _rank; }
678 
679  unsigned int size() const { return _size; }
680 
684  enum SendMode { DEFAULT=0, SYNCHRONOUS };
685 
686 private:
687 
688  // Don't use the copy constructor, just copy by reference or
689  // pointer - it's too hard to keep a common used_tag_values if
690  // each communicator is shared by more than one Communicator
691  explicit Communicator (const Communicator &);
692 
697  void assign(const communicator & comm);
698 
699  communicator _communicator;
700  unsigned int _rank, _size;
702 
703  // mutable used_tag_values - not thread-safe, but then Parallel::
704  // isn't thread-safe in general.
705  mutable std::map<int, unsigned int> used_tag_values;
707 
708  // Communication operations:
709 public:
710 
714  void send_mode (const SendMode sm) { _send_mode = sm; }
715 
719  SendMode send_mode() const { return _send_mode; }
720 
724  void barrier () const;
725 
730  template <typename T>
731  bool verify(const T & r) const;
732 
738  template <typename T>
739  bool semiverify(const T * r) const;
740 
745  template <typename T>
746  void min(T & r) const;
747 
753  template <typename T>
754  void minloc(T & r,
755  unsigned int & min_id) const;
756 
762  template <typename T>
763  void minloc(std::vector<T> & r,
764  std::vector<unsigned int> & min_id) const;
765 
770  template <typename T>
771  void max(T & r) const;
772 
778  template <typename T>
779  void maxloc(T & r,
780  unsigned int & max_id) const;
781 
787  template <typename T>
788  void maxloc(std::vector<T> & r,
789  std::vector<unsigned int> & max_id) const;
790 
795  template <typename T>
796  void sum(T & r) const;
797 
803  template <typename T>
804  void set_union(T & data, const unsigned int root_id) const;
805 
810  template <typename T>
811  void set_union(T & data) const;
812 
817  status probe (const unsigned int src_processor_id,
818  const MessageTag & tag=any_tag) const;
819 
832  template <typename T>
833  Status packed_range_probe (const unsigned int src_processor_id,
834  const MessageTag & tag,
835  bool & flag) const;
836 
840  template <typename T>
841  void send (const unsigned int dest_processor_id,
842  const T & buf,
843  const MessageTag & tag=no_tag) const;
844 
848  template <typename T>
849  void send (const unsigned int dest_processor_id,
850  const T & buf,
851  Request & req,
852  const MessageTag & tag=no_tag) const;
853 
857  template <typename T>
858  void send (const unsigned int dest_processor_id,
859  const T & buf,
860  const DataType & type,
861  const MessageTag & tag=no_tag) const;
862 
866  template <typename T>
867  void send (const unsigned int dest_processor_id,
868  const T & buf,
869  const DataType & type,
870  Request & req,
871  const MessageTag & tag=no_tag) const;
872 
876  template <typename T>
877  Status receive (const unsigned int dest_processor_id,
878  T & buf,
879  const MessageTag & tag=any_tag) const;
880 
884  template <typename T>
885  void receive (const unsigned int dest_processor_id,
886  T & buf,
887  Request & req,
888  const MessageTag & tag=any_tag) const;
889 
893  template <typename T>
894  Status receive (const unsigned int dest_processor_id,
895  T & buf,
896  const DataType & type,
897  const MessageTag & tag=any_tag) const;
898 
902  template <typename T>
903  void receive (const unsigned int dest_processor_id,
904  T & buf,
905  const DataType & type,
906  Request & req,
907  const MessageTag & tag=any_tag) const;
908 
922  template <typename Context, typename Iter>
923  void send_packed_range (const unsigned int dest_processor_id,
924  const Context * context,
925  Iter range_begin,
926  const Iter range_end,
927  const MessageTag & tag=no_tag) const;
928 
942  template <typename Context, typename Iter>
943  void send_packed_range (const unsigned int dest_processor_id,
944  const Context * context,
945  Iter range_begin,
946  const Iter range_end,
947  Request & req,
948  const MessageTag & tag=no_tag) const;
949 
958  template <typename Context, typename Iter>
959  void nonblocking_send_packed_range (const unsigned int dest_processor_id,
960  const Context * context,
961  Iter range_begin,
962  const Iter range_end,
963  Request & req,
964  const MessageTag & tag=no_tag) const;
965 
992  template <typename Context, typename OutputIter, typename T>
993  void receive_packed_range (const unsigned int dest_processor_id,
994  Context * context,
995  OutputIter out,
996  const T * output_type, // used only to infer T
997  const MessageTag & tag=any_tag) const;
998 
1011  template <typename Context, typename OutputIter, typename T>
1012  void nonblocking_receive_packed_range (const unsigned int src_processor_id,
1013  Context * context,
1014  OutputIter out,
1015  const T * output_type,
1016  Request & req,
1017  Status & stat,
1018  const MessageTag & tag=any_tag) const;
1019 
1024  template <typename T1, typename T2>
1025  void send_receive(const unsigned int dest_processor_id,
1026  const T1 & send,
1027  const unsigned int source_processor_id,
1028  T2 & recv,
1029  const MessageTag & send_tag = no_tag,
1030  const MessageTag & recv_tag = any_tag) const;
1031 
1068  template <typename Context1, typename RangeIter, typename Context2,
1069  typename OutputIter, typename T>
1070  void send_receive_packed_range(const unsigned int dest_processor_id,
1071  const Context1 * context1,
1072  RangeIter send_begin,
1073  const RangeIter send_end,
1074  const unsigned int source_processor_id,
1075  Context2 * context2,
1076  OutputIter out,
1077  const T * output_type, // used only to infer T
1078  const MessageTag & send_tag = no_tag,
1079  const MessageTag & recv_tag = any_tag) const;
1080 
1086  template <typename T1, typename T2>
1087  void send_receive(const unsigned int dest_processor_id,
1088  const T1 & send,
1089  const DataType & type1,
1090  const unsigned int source_processor_id,
1091  T2 & recv,
1092  const DataType & type2,
1093  const MessageTag & send_tag = no_tag,
1094  const MessageTag & recv_tag = any_tag) const;
1095 
1100  template <typename T>
1101  inline void gather(const unsigned int root_id,
1102  const T & send,
1103  std::vector<T> & recv) const;
1104 
1108  template <typename T>
1109  inline void gather(const unsigned int root_id,
1110  const std::basic_string<T> & send,
1111  std::vector<std::basic_string<T> > & recv,
1112  const bool identical_buffer_sizes=false) const;
1113 
1136  template <typename T>
1137  inline void gather(const unsigned int root_id,
1138  std::vector<T> & r) const;
1139 
1144  template <typename T>
1145  inline void allgather(const T & send,
1146  std::vector<T> & recv) const;
1147 
1151  template <typename T>
1152  inline void allgather(const std::basic_string<T> & send,
1153  std::vector<std::basic_string<T> > & recv,
1154  const bool identical_buffer_sizes=false) const;
1155 
1156 
1181  template <typename T>
1182  inline void allgather(std::vector<T> & r,
1183  const bool identical_buffer_sizes = false) const;
1184 
1185  //-------------------------------------------------------------------
1190  template <typename T>
1191  inline void scatter(const std::vector<T> & data,
1192  T & recv,
1193  const unsigned int root_id=0) const;
1194 
1201  template <typename T>
1202  inline void scatter(const std::vector<T> & data,
1203  std::vector<T> & recv,
1204  const unsigned int root_id=0) const;
1205 
1212  template <typename T>
1213  inline void scatter(const std::vector<T> & data,
1214  const std::vector<int> counts,
1215  std::vector<T> & recv,
1216  const unsigned int root_id=0) const;
1217 
1223  template <typename T>
1224  inline void scatter(const std::vector<std::vector<T> > & data,
1225  std::vector<T> & recv,
1226  const unsigned int root_id=0,
1227  const bool identical_buffer_sizes=false) const;
1228 
1229  //-------------------------------------------------------------------
1234  template <typename Context, typename Iter, typename OutputIter>
1235  inline void gather_packed_range (const unsigned int root_id,
1236  Context * context,
1237  Iter range_begin,
1238  const Iter range_end,
1239  OutputIter out) const;
1240 
1245  template <typename Context, typename Iter, typename OutputIter>
1246  inline void allgather_packed_range (Context * context,
1247  Iter range_begin,
1248  const Iter range_end,
1249  OutputIter out) const;
1250 
1256  template <typename T>
1257  inline void alltoall(std::vector<T> & r) const;
1258 
1267  template <typename T>
1268  inline void broadcast(T & data, const unsigned int root_id=0) const;
1269 
1287  template <typename Context, typename OutputContext, typename Iter, typename OutputIter>
1288  inline void broadcast_packed_range (const Context * context1,
1289  Iter range_begin,
1290  const Iter range_end,
1291  OutputContext * context2,
1292  OutputIter out,
1293  const unsigned int root_id = 0) const;
1294 
1302 #include "libmesh/parallel_communicator_specializations"
1303 
1304 }; // class Communicator
1305 
1306 // FakeCommunicator for debugging inappropriate CommWorld uses
1308 {
1309  operator Communicator & ()
1310  {
1311  libmesh_not_implemented();
1312  static Communicator temp;
1313  return temp;
1314  }
1315 };
1316 
1317 // PostWaitWork specialization for copying from temporary to
1318 // output containers
1319 template <typename Container, typename OutputIter>
1321  PostWaitCopyBuffer(const Container & buffer, const OutputIter out)
1322  : _buf(buffer), _out(out) {}
1323 
1324  virtual void run() libmesh_override { std::copy(_buf.begin(), _buf.end(), _out); }
1325 
1326 private:
1327  const Container & _buf;
1328  OutputIter _out;
1329 };
1330 
1331 // PostWaitWork specialization for unpacking received buffers.
1332 template <typename Container, typename Context, typename OutputIter,
1333  typename T>
1335  PostWaitUnpackBuffer(const Container & buffer, Context * context, OutputIter out) :
1336  _buf(buffer), _context(context), _out(out) {}
1337 
1338  virtual void run() libmesh_override {
1339 
1340  Parallel::unpack_range(_buf, _context, _out, (T*)libmesh_nullptr);
1341  }
1342 
1343 private:
1344  const Container & _buf;
1345  Context * _context;
1346  OutputIter _out;
1347 };
1348 
1349 
1350 // PostWaitWork specialization for freeing no-longer-needed buffers.
1351 template <typename Container>
1353  PostWaitDeleteBuffer(Container * buffer) : _buf(buffer) {}
1354 
1355  virtual void run() libmesh_override { delete _buf; }
1356 
1357 private:
1358  Container * _buf;
1359 };
1360 
1361 } // namespace Parallel
1362 
1376 #ifdef LIBMESH_DISABLE_COMMWORLD
1378 #define LIBMESH_CAN_DEFAULT_TO_COMMWORLD
1379 #else
1381 #define LIBMESH_CAN_DEFAULT_TO_COMMWORLD = libMesh::CommWorld
1382 #endif
1383 
1384 } // namespace libMesh
1385 
1386 // Define all the implementations separately; users might want to look
1387 // through this file for APIs, and it's long enough already.
1388 
1390 
1391 #endif // LIBMESH_PARALLEL_H
void alltoall(std::vector< T > &r, const Communicator &comm=Communicator_World)
virtual void run() libmesh_override
Definition: parallel.h:1324
void receive_packed_range(const unsigned int src_processor_id, Context *context, OutputIter out_iter, const T *output_type, const MessageTag &tag=any_tag, const Communicator &comm=Communicator_World)
MessageTag(int tagvalue=invalid_tag)
Definition: parallel.h:236
Iter pack_range(const Context *context, Iter range_begin, const Iter range_end, typename std::vector< buffertype > &buffer, std::size_t approx_buffer_size=1000000)
Status wait(Request &r)
Definition: parallel.h:519
void send_packed_range(const unsigned int dest_processor_id, const Context *context, Iter range_begin, const Iter range_end, const MessageTag &tag=no_tag, const Communicator &comm=Communicator_World)
void send(const unsigned int dest_processor_id, const T &data, const MessageTag &tag=no_tag, const Communicator &comm=Communicator_World)
const unsigned int any_source
Definition: parallel.h:200
unsigned int size() const
Definition: parallel.h:679
static void set_lowest(T &)
Definition: parallel.h:404
MPI_Comm communicator
Definition: parallel.h:177
void allgather_packed_range(Context *context, Iter range_begin, const Iter range_end, OutputIter out_iter, const Communicator &comm=Communicator_World)
MPI_Request request
Definition: parallel.h:167
const class libmesh_nullptr_t libmesh_nullptr
MPI_Datatype data_type
Definition: parallel.h:162
void send_mode(const SendMode sm)
Definition: parallel.h:714
Status receive(const unsigned int src_processor_id, T &buf, const MessageTag &tag=any_tag, const Communicator &comm=Communicator_World)
std::pair< std::vector< PostWaitWork * >, unsigned int > * post_wait_work
Definition: parallel.h:513
void sum(T &r, const Communicator &comm=Communicator_World)
void gather_packed_range(const unsigned int root_id, Context *context, Iter range_begin, const Iter range_end, OutputIter out_iter, const Communicator &comm=Communicator_World)
void broadcast_packed_range(const Context *context1, Iter range_begin, const Iter range_end, OutputContext *context2, OutputIter out_iter, const unsigned int root_id=0, const Communicator &comm=Communicator_World)
PostWaitDeleteBuffer(Container *buffer)
Definition: parallel.h:1353
libMesh::Parallel::StandardType< unsigned long long > has_min_max
std::unique_ptr< T > UniquePtr
Definition: auto_ptr.h:46
std::size_t packed_range_size(const Context *context, Iter range_begin, const Iter range_end)
virtual void run() libmesh_override
Definition: parallel.h:1338
void barrier(const Communicator &comm=Communicator_World)
PostWaitCopyBuffer(const Container &buffer, const OutputIter out)
Definition: parallel.h:1321
PostWaitUnpackBuffer(const Container &buffer, Context *context, OutputIter out)
Definition: parallel.h:1335
void broadcast(T &data, const unsigned int root_id=0, const Communicator &comm=Communicator_World)
UniquePtr< Request > _prior_request
Definition: parallel.h:507
void allgather(T send, std::vector< T > &recv, const Communicator &comm=Communicator_World)
MessageTag(int tagvalue, const Communicator *comm)
Definition: parallel.h:260
DataType(const data_type &type)
Definition: parallel.h:294
const data_type & datatype() const
Definition: parallel.h:442
void gather(const unsigned int root_id, T send, std::vector< T > &recv, const Communicator &comm=Communicator_World)
PetscErrorCode Vec Mat Mat void * ctx
MPI_Status status
Definition: parallel.h:172
DataType(const DataType &other)
Definition: parallel.h:290
virtual void run() libmesh_override
Definition: parallel.h:1355
data_type dataplusint_type()
const MessageTag no_tag
Definition: parallel.h:278
tbb::split split
Definition: threads_tbb.h:79
Parallel::FakeCommunicator CommWorld
Definition: libmesh.C:206
bool verify(const T &r, const Communicator &comm=Communicator_World)
DataType(const DataType &, unsigned int)
Definition: parallel.h:307
void set_union(T &data, const unsigned int root_id, const Communicator &comm=Communicator_World)
void max(T &r, const Communicator &comm=Communicator_World)
data_type & datatype()
Definition: parallel.h:440
Iterator & operator=(const Iterator &rhs)
const MessageTag any_tag
Definition: parallel.h:273
DataType(const DataType &other, unsigned int count)
Definition: parallel.h:299
unsigned int rank() const
Definition: parallel.h:677
std::map< int, unsigned int > used_tag_values
Definition: parallel.h:705
IterBase * data
static void set_highest(T &)
Definition: parallel.h:405
OStreamProxy out(std::cout)
void unpack_range(const typename std::vector< buffertype > &buffer, Context *context, OutputIter out, const T *output_type)
void maxloc(T &r, U &max_id, const Communicator &comm=Communicator_World)
void min(T &r, const Communicator &comm=Communicator_World)
void send_receive_packed_range(const unsigned int dest_processor_id, const Context1 *context1, RangeIter send_begin, const RangeIter send_end, const unsigned int source_processor_id, Context2 *context2, OutputIter out_iter, const T *output_type, const MessageTag &send_tag=no_tag, const MessageTag &recv_tag=any_tag, const Communicator &comm=Communicator_World)
status probe(const unsigned int src_processor_id, const MessageTag &tag=any_tag, const Communicator &comm=Communicator_World)
void minloc(T &r, U &min_id, const Communicator &comm=Communicator_World)
const Communicator * _comm
Definition: parallel.h:257
SendMode send_mode() const
Definition: parallel.h:719
void send_receive(const unsigned int dest_processor_id, T1 &send, const unsigned int source_processor_id, T2 &recv, const MessageTag &send_tag=no_tag, const MessageTag &recv_tag=any_tag, const Communicator &comm=Communicator_World)