TIMPI
communicator.h
Go to the documentation of this file.
1 // The TIMPI Message-Passing Parallelism Library.
2 // Copyright (C) 2002-2025 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 TIMPI_COMMUNICATOR_H
20 #define TIMPI_COMMUNICATOR_H
21 
22 // TIMPI includes
23 #include "timpi/message_tag.h"
24 #include "timpi/packing.h"
25 #include "timpi/request.h"
26 #include "timpi/standard_type.h"
27 #include "timpi/status.h"
28 #include "timpi/timpi_config.h"
29 #include "timpi/timpi_macros.h"
30 
31 // C++ includes
32 #include <cstdint>
33 #include <map>
34 #include <memory> // shared_ptr
35 #include <string>
36 #include <vector>
37 #include <type_traits>
38 
39 // C++ includes needed for parallel_communicator_specializations
40 //
41 // These could be forward declarations if only that wasn't illegal
42 #include <complex> // for specializations
43 #include <set>
44 #include <unordered_map>
45 
46 namespace TIMPI
47 {
48 
51 
52 // Define processor id storage type.
53 #if TIMPI_PROCESSOR_ID_BYTES == 1
54 typedef uint8_t processor_id_type;
55 #elif TIMPI_PROCESSOR_ID_BYTES == 2
56 typedef uint16_t processor_id_type;
57 #elif TIMPI_PROCESSOR_ID_BYTES == 4
58 typedef uint32_t processor_id_type; // default
59 #elif TIMPI_PROCESSOR_ID_BYTES == 8
60 typedef uint64_t processor_id_type;
61 #else
62 // We should not get here: it's not currently possible to set any
63 // other size.
64 DIE A HORRIBLE DEATH HERE...
65 #endif
66 
67 
68 #ifdef TIMPI_HAVE_MPI
69 
70 //-------------------------------------------------------------------
74 typedef MPI_Comm communicator;
75 
79 typedef MPI_Info info;
80 
84 const unsigned int any_source =
85  static_cast<unsigned int>(MPI_ANY_SOURCE);
86 
87 #else
88 
89 // These shouldn't actually be needed, but must be
90 // unique types for function overloading to work
91 // properly.
92 typedef int communicator; // Must match petsc-nompi definition
93 
94 typedef int info;
95 
96 const unsigned int any_source=0;
97 
98 #endif // TIMPI_HAVE_MPI
99 
100 //-------------------------------------------------------------------
109 {
110  // Basic operations:
111 public:
112 
116  Communicator ();
117 
118  /*
119  * Constructor from MPI_Comm
120  */
121  explicit Communicator (const communicator & comm);
122 
123  /*
124  * Don't use copy construction or assignment, just copy by reference
125  * or pointer - it's too hard to keep a common used_tag_values if
126  * each communicator is shared by more than one Communicator
127  */
128  Communicator (const Communicator &) = delete;
129  Communicator & operator= (const Communicator &) = delete;
130 
131  /*
132  * Move constructor and assignment operator
133  */
134  Communicator (Communicator &&) = default;
135  Communicator & operator= (Communicator &&) = default;
136 
137  /*
138  * NON-VIRTUAL destructor
139  */
140  ~Communicator ();
141 
142  /*
143  * Create a new communicator between some subset of \p this,
144  * based on specified "color"
145  */
146  void split(int color, int key, Communicator & target) const;
147 
148  /*
149  * Create a new communicator between some subset of \p this,
150  * based on specified split "type" (e.g. MPI_COMM_TYPE_SHARED)
151  */
152  void split_by_type(int split_type, int key, info i, Communicator & target) const;
153 
154  /*
155  * Make \p this a new duplicate of the Communicator \p comm -
156  * sharing the same processes but with a new communication context
157  * and without sharing unique MessageTag assignment.
158  */
159  void duplicate(const Communicator & comm);
160 
161  /*
162  * Make \p this a new duplicate of the MPI communicator \p comm -
163  * sharing the same processes but with a new communication context.
164  */
165  void duplicate(const communicator & comm);
166 
167  communicator & get() { return _communicator; }
168 
169  const communicator & get() const { return _communicator; }
170 
187  MessageTag get_unique_tag(int tagvalue = MessageTag::invalid_tag) const;
188 
193  void reference_unique_tag(int tagvalue) const;
194 
199  void dereference_unique_tag(int tagvalue) const;
200 
204  void clear();
205 
206  Communicator & operator= (const communicator & comm);
207 
208  processor_id_type rank() const { return _rank; }
209 
210 #ifdef TIMPI_HAVE_MPI
211  processor_id_type size() const { return _size; }
212 #else
213  // Help the compiler optimize in serial
214  constexpr processor_id_type size() const { return 1; }
215 #endif
216 
221 
226 
227 
228 private:
229 
234  void assign(const communicator & comm);
235 
240 
241  // mutable used_tag_values and tag_queue - not thread-safe, but then
242  // TIMPI:: isn't thread-safe in general.
243  mutable std::map<int, unsigned int> used_tag_values;
244  mutable int _next_tag;
245 
246  int _max_tag;
247 
248  // Keep track of duplicate/split operations so we know when to free
250 
256  template <typename Map,
257  typename std::enable_if<std::is_base_of<DataType, StandardType<typename Map::key_type>>::value &&
258  std::is_base_of<DataType, StandardType<typename Map::mapped_type>>::value,
259  int>::type = 0>
260  void map_sum(Map & data) const;
261 
267  template <typename Map,
268  typename std::enable_if<!(std::is_base_of<DataType, StandardType<typename Map::key_type>>::value &&
269  std::is_base_of<DataType, StandardType<typename Map::mapped_type>>::value),
270  int>::type = 0>
271  void map_sum(Map & data) const;
272 
277  template <typename Map,
278  typename std::enable_if<std::is_base_of<DataType, StandardType<typename Map::key_type>>::value &&
279  std::is_base_of<DataType, StandardType<typename Map::mapped_type>>::value,
280  int>::type = 0>
281  void map_broadcast(Map & data,
282  const unsigned int root_id,
283  const bool identical_sizes) const;
284 
291  template <typename Map,
292  typename std::enable_if<!(std::is_base_of<DataType, StandardType<typename Map::key_type>>::value &&
293  std::is_base_of<DataType, StandardType<typename Map::mapped_type>>::value),
294  int>::type = 0>
295  void map_broadcast(Map & data,
296  const unsigned int root_id,
297  const bool identical_sizes) const;
298 
304  template <typename Map,
305  typename std::enable_if<std::is_base_of<DataType, StandardType<typename Map::key_type>>::value &&
306  std::is_base_of<DataType, StandardType<typename Map::mapped_type>>::value,
307  int>::type = 0>
308  void map_max(Map & data) const;
309 
315  template <typename Map,
316  typename std::enable_if<!(std::is_base_of<DataType, StandardType<typename Map::key_type>>::value &&
317  std::is_base_of<DataType, StandardType<typename Map::mapped_type>>::value),
318  int>::type = 0>
319  void map_max(Map & data) const;
320 
321  // Utility function for determining size for buffering of
322  // vector<vector<T>> into vector<char> via MPI_Pack*
323  template <typename T, typename A1, typename A2>
324  std::size_t packed_size_of(const std::vector<std::vector<T,A1>,A2> & buf,
325  const DataType & type) const;
326 
327  // Communication operations:
328 public:
329 
333  void send_mode (const SendMode sm) { _send_mode = sm; }
334 
338  SendMode send_mode() const { return _send_mode; }
339 
343  void sync_type (const SyncType st) { _sync_type = st; }
344 
350  void sync_type (const std::string & st);
351 
355  SyncType sync_type() const { return _sync_type; }
356 
360  void barrier () const;
361 
365  void nonblocking_barrier (Request & req) const;
366 
375  template <typename T>
376  timpi_pure
377  inline
378  bool verify(const T & r) const;
379 
390  template <typename T>
391  timpi_pure
392  inline
393  bool semiverify(const T * r) const;
394 
399  template <typename T>
400  inline
401  void min(const T & r, T & o, Request & req) const;
402 
407  template <typename T>
408  inline
409  void min(T & r) const;
410 
416  template <typename T>
417  inline
418  void minloc(T & r,
419  unsigned int & min_id) const;
420 
426  template <typename T, typename A1, typename A2>
427  inline
428  void minloc(std::vector<T,A1> & r,
429  std::vector<unsigned int,A2> & min_id) const;
430 
435  template <typename T>
436  inline
437  void max(const T & r, T & o, Request & req) const;
438 
443  template <typename T>
444  inline
445  void max(T & r) const;
446 
452  template <typename T>
453  inline
454  void maxloc(T & r,
455  unsigned int & max_id) const;
456 
462  template <typename T, typename A1, typename A2>
463  inline
464  void maxloc(std::vector<T,A1> & r,
465  std::vector<unsigned int,A2> & max_id) const;
466 
471  template <typename T>
472  inline
473  void product(T & r) const;
474 
479  template <typename T>
480  inline
481  void product(const T & r, T & o, Request & req) const;
482 
487  template <typename T>
488  inline
489  void logical_and(T & r) const;
490 
495  template <typename T>
496  inline
497  void logical_and(const T & r, T & o, Request & req) const;
498 
503  template <typename T>
504  inline
505  void bitwise_and(T & r) const;
506 
511  template <typename T>
512  inline
513  void bitwise_and(const T & r, T & o, Request & req) const;
514 
519  template <typename T>
520  inline
521  void logical_or(T & r) const;
522 
527  template <typename T>
528  inline
529  void logical_or(const T & r, T & o, Request & req) const;
530 
535  template <typename T>
536  inline
537  void bitwise_or(T & r) const;
538 
543  template <typename T>
544  inline
545  void bitwise_or(const T & r, T & o, Request & req) const;
546 
551  template <typename T>
552  inline
553  void logical_xor(T & r) const;
554 
559  template <typename T>
560  inline
561  void logical_xor(const T & r, T & o, Request & req) const;
562 
567  template <typename T>
568  inline
569  void bitwise_xor(T & r) const;
570 
575  template <typename T>
576  inline
577  void bitwise_xor(const T & r, T & o, Request & req) const;
578 
583  template <typename T>
584  inline
585  void sum(T & r) const;
586 
591  template <typename T>
592  inline
593  void sum(const T & r, T & o, Request & req) const;
594 
609  template <typename T>
610  inline
611  void set_union(T & data, const unsigned int root_id) const;
612 
622  template <typename T>
623  inline
624  void set_union(T & data) const;
625 
630  status probe (const unsigned int src_processor_id,
631  const MessageTag & tag=any_tag) const;
632 
645  template <typename T>
646  inline
647  Status packed_range_probe (const unsigned int src_processor_id,
648  const MessageTag & tag,
649  bool & flag) const;
650 
654  template <typename T>
655  inline
656  void send (const unsigned int dest_processor_id,
657  const T & buf,
658  const MessageTag & tag=no_tag) const;
659 
663  template <typename T>
664  inline
665  void send (const unsigned int dest_processor_id,
666  const T & buf,
667  Request & req,
668  const MessageTag & tag=no_tag) const;
669 
677  template <typename T>
678  inline
679  void send (const unsigned int dest_processor_id,
680  const T & buf,
681  const DataType & type,
682  const MessageTag & tag=no_tag) const;
683 
691  template <typename T>
692  inline
693  void send (const unsigned int dest_processor_id,
694  const T & buf,
695  const DataType & type,
696  Request & req,
697  const MessageTag & tag=no_tag) const;
698 
703  template <typename T>
704  inline
705  void send (const unsigned int dest_processor_id,
706  const T & buf,
707  const NotADataType & type,
708  Request & req,
709  const MessageTag & tag=no_tag) const;
710 
714  template <typename T>
715  inline
716  Status receive (const unsigned int dest_processor_id,
717  T & buf,
718  const MessageTag & tag=any_tag) const;
719 
723  template <typename T>
724  inline
725  void receive (const unsigned int dest_processor_id,
726  T & buf,
727  Request & req,
728  const MessageTag & tag=any_tag) const;
729 
737  template <typename T>
738  inline
739  Status receive (const unsigned int dest_processor_id,
740  T & buf,
741  const DataType & type,
742  const MessageTag & tag=any_tag) const;
743 
751  template <typename T>
752  inline
753  void receive (const unsigned int dest_processor_id,
754  T & buf,
755  const DataType & type,
756  Request & req,
757  const MessageTag & tag=any_tag) const;
758 
777  template <typename T, typename A,
778  typename std::enable_if<std::is_base_of<DataType, StandardType<T>>::value, int>::type = 0>
779  inline
780  bool possibly_receive (unsigned int & src_processor_id,
781  std::vector<T,A> & buf,
782  Request & req,
783  const MessageTag & tag) const;
784 
793  template <typename T, typename A,
794  typename std::enable_if<Has_buffer_type<Packing<T>>::value, int>::type = 0>
795  inline
796  bool possibly_receive (unsigned int & src_processor_id,
797  std::vector<T,A> & buf,
798  Request & req,
799  const MessageTag & tag) const;
800 
801 
815  template <typename T, typename A, typename std::enable_if<std::is_base_of<DataType, StandardType<T>>::value, int>::type = 0>
816  inline
817  bool possibly_receive (unsigned int & src_processor_id,
818  std::vector<T,A> & buf,
819  const DataType & type,
820  Request & req,
821  const MessageTag & tag) const;
822 
835  template <typename T, typename A,
836  typename std::enable_if<Has_buffer_type<Packing<T>>::value, int>::type = 0>
837  inline
838  bool possibly_receive (unsigned int & src_processor_id,
839  std::vector<T,A> & buf,
840  const NotADataType & type,
841  Request & req,
842  const MessageTag & tag) const;
843 
867  template <typename Context, typename OutputIter, typename T>
868  bool possibly_receive_packed_range (unsigned int & src_processor_id,
869  Context * context,
870  OutputIter out,
871  const T * output_type,
872  Request & req,
873  const MessageTag & tag) const;
874 
894  template <typename Context, typename Iter>
895  inline
896  void send_packed_range (const unsigned int dest_processor_id,
897  const Context * context,
898  Iter range_begin,
899  const Iter range_end,
900  const MessageTag & tag=no_tag,
901  std::size_t approx_buffer_size = 1000000) const;
902 
922  template <typename Context, typename Iter>
923  inline
924  void send_packed_range (const unsigned int dest_processor_id,
925  const Context * context,
926  Iter range_begin,
927  const Iter range_end,
928  Request & req,
929  const MessageTag & tag=no_tag,
930  std::size_t approx_buffer_size = 1000000) const;
931 
940  template <typename Context, typename Iter>
941  inline
942  void nonblocking_send_packed_range (const unsigned int dest_processor_id,
943  const Context * context,
944  Iter range_begin,
945  const Iter range_end,
946  Request & req,
947  const MessageTag & tag=no_tag) const;
948 
949 
958  template <typename Context, typename Iter>
959  inline
960  void nonblocking_send_packed_range (const unsigned int dest_processor_id,
961  const Context * context,
962  Iter range_begin,
963  const Iter range_end,
964  Request & req,
965  std::shared_ptr<std::vector<typename TIMPI::Packing<typename std::iterator_traits<Iter>::value_type>::buffer_type>> & buffer,
966  const MessageTag & tag=no_tag) const;
967 
994  template <typename Context, typename OutputIter, typename T>
995  inline
996  void receive_packed_range (const unsigned int dest_processor_id,
997  Context * context,
998  OutputIter out,
999  const T * output_type, // used only to infer T
1000  const MessageTag & tag=any_tag) const;
1001 
1014  template <typename Context, typename OutputIter, typename T>
1015  inline
1016  void nonblocking_receive_packed_range (const unsigned int src_processor_id,
1017  Context * context,
1018  OutputIter out,
1019  const T * output_type,
1020  Request & req,
1021  Status & stat,
1022  const MessageTag & tag=any_tag) const;
1023 
1036  template <typename Context, typename OutputIter, typename T>
1037  inline
1038  void nonblocking_receive_packed_range (const unsigned int src_processor_id,
1039  Context * context,
1040  OutputIter out,
1041  const T * output_type,
1042  Request & req,
1043  Status & stat,
1044  std::shared_ptr<std::vector<typename TIMPI::Packing<T>::buffer_type>> & buffer,
1045  const MessageTag & tag=any_tag
1046  ) const;
1047 
1055  template <typename T1, typename T2,
1056  typename std::enable_if<std::is_base_of<DataType, StandardType<T1>>::value &&
1057  std::is_base_of<DataType, StandardType<T2>>::value,
1058  int>::type = 0>
1059  inline
1060  void send_receive(const unsigned int dest_processor_id,
1061  const T1 & send_data,
1062  const unsigned int source_processor_id,
1063  T2 & recv_data,
1064  const MessageTag & send_tag = no_tag,
1065  const MessageTag & recv_tag = any_tag) const;
1066 
1103  template <typename Context1, typename RangeIter, typename Context2,
1104  typename OutputIter, typename T>
1105  inline
1106  void send_receive_packed_range(const unsigned int dest_processor_id,
1107  const Context1 * context1,
1108  RangeIter send_begin,
1109  const RangeIter send_end,
1110  const unsigned int source_processor_id,
1111  Context2 * context2,
1112  OutputIter out,
1113  const T * output_type, // used only to infer T
1114  const MessageTag & send_tag = no_tag,
1115  const MessageTag & recv_tag = any_tag,
1116  std::size_t approx_buffer_size = 1000000) const;
1117 
1123  template <typename T1, typename T2>
1124  inline
1125  void send_receive(const unsigned int dest_processor_id,
1126  const T1 & send_data,
1127  const DataType & type1,
1128  const unsigned int source_processor_id,
1129  T2 & recv_data,
1130  const DataType & type2,
1131  const MessageTag & send_tag = no_tag,
1132  const MessageTag & recv_tag = any_tag) const;
1133 
1138  template <typename T, typename A>
1139  inline void gather(const unsigned int root_id,
1140  const T & send_data,
1141  std::vector<T,A> & recv) const;
1142 
1148  template <typename T, typename A>
1149  inline void gather(const unsigned int root_id,
1150  const std::basic_string<T> & send_data,
1151  std::vector<std::basic_string<T>,A> & recv_data,
1152  const bool identical_buffer_sizes=false) const;
1153 
1180  template <typename T, typename A,
1181  typename std::enable_if<std::is_base_of<DataType, StandardType<T>>::value, int>::type = 0>
1182  inline void gather(const unsigned int root_id,
1183  std::vector<T,A> & r) const;
1184 
1185  template <typename T, typename A,
1186  typename std::enable_if<Has_buffer_type<Packing<T>>::value, int>::type = 0>
1187  inline void gather(const unsigned int root_id,
1188  std::vector<T,A> & r) const;
1189 
1195  template <typename T, typename A, typename std::enable_if<std::is_base_of<DataType, StandardType<T>>::value,
1196  int>::type = 0>
1197  inline void allgather(const T & send_data,
1198  std::vector<T,A> & recv_data) const;
1199 
1206  template <typename T, typename A, typename std::enable_if<Has_buffer_type<Packing<T>>::value,
1207  int>::type = 0>
1208  inline void allgather(const T & send_data,
1209  std::vector<T,A> & recv_data) const;
1210 
1216  template <typename T, typename A>
1217  inline void allgather(const std::basic_string<T> & send_data,
1218  std::vector<std::basic_string<T>,A> & recv_data,
1219  const bool identical_buffer_sizes=false) const;
1220 
1245  template <typename T, typename A,
1246  typename std::enable_if<std::is_base_of<DataType, StandardType<T>>::value, int>::type = 0>
1247  inline void allgather(std::vector<T,A> & r,
1248  const bool identical_buffer_sizes = false) const;
1249 
1257  template <typename T, typename A1, typename A2,
1258  typename std::enable_if<std::is_base_of<DataType, StandardType<T>>::value, int>::type = 0>
1259  inline void allgather(const std::vector<T,A1> & send_data,
1260  std::vector<std::vector<T,A1>, A2> & recv_data,
1261  const bool identical_buffer_sizes = false) const;
1262 
1267  template <typename T, typename A1, typename A2,
1268  typename std::enable_if<Has_buffer_type<Packing<T>>::value, int>::type = 0>
1269  inline void allgather(const std::vector<T,A1> & send_data,
1270  std::vector<std::vector<T,A1>, A2> & recv_data,
1271  const bool identical_buffer_sizes = false) const;
1272 
1297  template <typename T, typename A,
1298  typename std::enable_if<Has_buffer_type<Packing<T>>::value, int>::type = 0>
1299  inline void allgather(std::vector<T,A> & r,
1300  const bool identical_buffer_sizes = false) const;
1301 
1305  template <typename T, typename A>
1306  inline void allgather(std::vector<std::basic_string<T>,A> & r,
1307  const bool identical_buffer_sizes = false) const;
1308 
1309  //-------------------------------------------------------------------
1314  template <typename T, typename A>
1315  inline void scatter(const std::vector<T,A> & data,
1316  T & recv,
1317  const unsigned int root_id=0) const;
1318 
1325  template <typename T, typename A>
1326  inline void scatter(const std::vector<T,A> & data,
1327  std::vector<T,A> & recv,
1328  const unsigned int root_id=0) const;
1329 
1336  template <typename T, typename A1, typename A2>
1337  inline void scatter(const std::vector<T,A1> & data,
1338  const std::vector<CountType,A2> counts,
1339  std::vector<T,A1> & recv,
1340  const unsigned int root_id=0) const;
1341 
1342 #ifdef TIMPI_HAVE_MPI
1343 #if MPI_VERSION > 3
1344 
1347  template <typename T, typename A1, typename A2>
1348  inline void scatter(const std::vector<T,A1> & data,
1349  const std::vector<int,A2> counts,
1350  std::vector<T,A1> & recv,
1351  const unsigned int root_id=0) const;
1352 #endif
1353 #endif
1354 
1360  template <typename T, typename A1, typename A2>
1361  inline void scatter(const std::vector<std::vector<T,A1>,A2> & data,
1362  std::vector<T,A1> & recv,
1363  const unsigned int root_id=0,
1364  const bool identical_buffer_sizes=false) const;
1365 
1366  //-------------------------------------------------------------------
1382  template <typename Context, typename Iter, typename OutputIter>
1383  inline void gather_packed_range (const unsigned int root_id,
1384  Context * context,
1385  Iter range_begin,
1386  const Iter range_end,
1387  OutputIter out,
1388  std::size_t approx_buffer_size = 1000000) const;
1389 
1405  template <typename Context, typename Iter, typename OutputIter>
1406  inline void allgather_packed_range (Context * context,
1407  Iter range_begin,
1408  const Iter range_end,
1409  OutputIter out,
1410  std::size_t approx_buffer_size = 1000000) const;
1411 
1417  template <typename T, typename A>
1418  inline void alltoall(std::vector<T,A> & r) const;
1419 
1431  template <typename T
1432 #ifdef TIMPI_HAVE_MPI
1433  ,
1434  typename std::enable_if<std::is_base_of<DataType, StandardType<T>>::value, int>::type = 0
1435 #endif
1436  >
1437  inline void broadcast(T & data, const unsigned int root_id=0,
1438  const bool identical_sizes=false) const;
1439 
1440 #ifdef TIMPI_HAVE_MPI
1441 
1452  template <typename T,
1453  typename std::enable_if<Has_buffer_type<Packing<T>>::value, int>::type = 0>
1454  inline void broadcast(T & data, const unsigned int root_id=0,
1455  const bool identical_sizes=false) const;
1456 #endif
1457 
1481  template <typename Context, typename OutputContext, typename Iter, typename OutputIter>
1482  inline void broadcast_packed_range (const Context * context1,
1483  Iter range_begin,
1484  const Iter range_end,
1485  OutputContext * context2,
1486  OutputIter out,
1487  const unsigned int root_id = 0,
1488  std::size_t approx_buffer_size = 1000000) const;
1489 
1497 #include "timpi/parallel_communicator_specializations"
1498 
1499 }; // class Communicator
1500 
1501 
1502 } // namespace TIMPI
1503 
1504 
1505 // Backwards compatibility for libMesh forward declarations
1506 namespace libMesh {
1507 namespace Parallel {
1509 public:
1510  Communicator () = default;
1511  explicit Communicator (const TIMPI::communicator & comm) : TIMPI::Communicator(comm) {}
1512  Communicator (const Communicator &) = delete;
1513  Communicator & operator= (const Communicator &) = delete;
1514  Communicator (Communicator &&) = default;
1515  Communicator & operator= (Communicator &&) = default;
1516  ~Communicator () = default;
1517 };
1518 }
1519 }
1520 
1521 #endif // TIMPI_COMMUNICATOR_H
void gather_packed_range(const unsigned int root_id, Context *context, Iter range_begin, const Iter range_end, OutputIter out, std::size_t approx_buffer_size=1000000) const
Take a range of local variables, combine it with ranges from all processors, and write the output to ...
void bitwise_and(T &r) const
Take a local variable and replace it with the bitwise_and of its values on all processors.
void logical_xor(T &r) const
Take a local variable and replace it with the logical_xor of its values on all processors.
void send_mode(const SendMode sm)
Explicitly sets the SendMode type used for send operations.
Definition: communicator.h:333
void allgather(const T &send_data, std::vector< T, A > &recv_data) const
Take a vector of length this->size(), and fill in recv[processor_id] = the value of send on that proc...
void nonblocking_send_packed_range(const unsigned int dest_processor_id, const Context *context, Iter range_begin, const Iter range_end, Request &req, const MessageTag &tag=no_tag) const
Similar to the above Nonblocking send_packed_range with a few important differences: ...
void broadcast_packed_range(const Context *context1, Iter range_begin, const Iter range_end, OutputContext *context2, OutputIter out, const unsigned int root_id=0, std::size_t approx_buffer_size=1000000) const
Blocking-broadcast range-of-pointers to one processor.
Status packed_range_probe(const unsigned int src_processor_id, const MessageTag &tag, bool &flag) const
Non-Blocking message probe for a packed range message.
void bitwise_or(T &r) const
Take a local variable and replace it with the bitwise_or of its values on all processors.
void scatter(const std::vector< T, A > &data, T &recv, const unsigned int root_id=0) const
Take a vector of local variables and scatter the ith item to the ith processor in the communicator...
communicator _communicator
Definition: communicator.h:236
void sync_type(const SyncType st)
Explicitly sets the SyncType used for sync operations.
Definition: communicator.h:343
MPI_Info info
Info object used by some MPI-3 methods.
Definition: communicator.h:79
void map_max(Map &data) const
Private implementation function called by the map-based max() specializations.
std::map< int, unsigned int > used_tag_values
Definition: communicator.h:243
void minloc(T &r, unsigned int &min_id) const
Take a local variable and replace it with the minimum of it&#39;s values on all processors, returning the minimum rank of a processor which originally held the minimum value.
void gather(const unsigned int root_id, const T &send_data, std::vector< T, A > &recv) const
Take a vector of length comm.size(), and on processor root_id fill in recv[processor_id] = the value ...
MessageTag get_unique_tag(int tagvalue=MessageTag::invalid_tag) const
Get a tag that is unique to this Communicator.
Definition: communicator.C:251
const MessageTag any_tag
Default message tag ids.
Definition: message_tag.h:114
void sum(T &r) const
Take a local variable and replace it with the sum of it&#39;s values on all processors.
void alltoall(std::vector< T, A > &r) const
Effectively transposes the input vector across all processors.
void barrier() const
Pause execution until all processors reach a certain point.
Definition: communicator.C:225
processor_id_type rank() const
Definition: communicator.h:208
SyncType sync_type() const
Gets the user-requested SyncType.
Definition: communicator.h:355
Encapsulates the MPI_Datatype.
Definition: data_type.h:50
void allgather_packed_range(Context *context, Iter range_begin, const Iter range_end, OutputIter out, std::size_t approx_buffer_size=1000000) const
Take a range of local variables, combine it with ranges from all processors, and write the output to ...
void map_broadcast(Map &data, const unsigned int root_id, const bool identical_sizes) const
Private implementation function called by the map-based broadcast() specializations.
void clear()
Free and reset this communicator.
Definition: communicator.C:162
void assign(const communicator &comm)
Utility function for setting our member variables from an MPI communicator.
Definition: communicator.C:185
void logical_or(T &r) const
Take a local variable and replace it with the logical_or of its values on all processors.
Define data types and (un)serialization functions for use when encoding a potentially-variable-size o...
Definition: packing.h:60
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, std::size_t approx_buffer_size=1000000) const
Blocking-send range-of-pointers to one processor.
Communicator(const TIMPI::communicator &comm)
processor_id_type _size
Definition: communicator.h:237
void nonblocking_receive_packed_range(const unsigned int src_processor_id, Context *context, OutputIter out, const T *output_type, Request &req, Status &stat, const MessageTag &tag=any_tag) const
Non-Blocking-receive range-of-pointers from one processor.
const unsigned int any_source
Processor id meaning "Accept from any source".
Definition: communicator.h:84
bool possibly_receive(unsigned int &src_processor_id, std::vector< T, A > &buf, Request &req, const MessageTag &tag) const
Nonblocking-receive from one processor with user-defined type.
Encapsulates the MPI_Comm object.
Definition: communicator.h:108
const MessageTag no_tag
Definition: message_tag.h:119
processor_id_type size() const
Definition: communicator.h:211
std::size_t packed_size_of(const std::vector< std::vector< T, A1 >, A2 > &buf, const DataType &type) const
uint8_t processor_id_type
Definition: communicator.h:54
SendMode
Whether to use default or synchronous sends?
Definition: communicator.h:220
Status receive(const unsigned int dest_processor_id, T &buf, const MessageTag &tag=any_tag) const
Blocking-receive from one processor with data-defined type.
static const int invalid_tag
Invalid tag, to allow for default construction.
Definition: message_tag.h:53
Encapsulates the MPI tag integers.
Definition: message_tag.h:46
void min(const T &r, T &o, Request &req) const
Non-blocking minimum of the local value r into o with the request req.
void receive_packed_range(const unsigned int dest_processor_id, Context *context, OutputIter out, const T *output_type, const MessageTag &tag=any_tag) const
Blocking-receive range-of-pointers from one processor.
constexpr processor_id_type size() const
Definition: communicator.h:214
status probe(const unsigned int src_processor_id, const MessageTag &tag=any_tag) const
Blocking message probe.
Definition: communicator.C:283
processor_id_type _rank
Definition: communicator.h:237
void product(T &r) const
Take a local variable and replace it with the product of its values on all processors.
void bitwise_xor(T &r) const
Take a local variable and replace it with the bitwise_xor of its values on all processors.
void split(int color, int key, Communicator &target) const
Definition: communicator.C:97
Communicator & operator=(const Communicator &)=delete
SyncType
What algorithm to use for parallel synchronization?
Definition: communicator.h:225
void maxloc(T &r, unsigned int &max_id) const
Take a local variable and replace it with the maximum of it&#39;s values on all processors, returning the minimum rank of a processor which originally held the maximum value.
void send_receive(const unsigned int dest_processor_id, const T1 &send_data, const unsigned int source_processor_id, T2 &recv_data, const MessageTag &send_tag=no_tag, const MessageTag &recv_tag=any_tag) const
Send data send to one processor while simultaneously receiving other data recv from a (potentially di...
bool possibly_receive_packed_range(unsigned int &src_processor_id, Context *context, OutputIter out, const T *output_type, Request &req, const MessageTag &tag) const
Nonblocking packed range receive from one processor with user-defined type.
timpi_pure bool semiverify(const T *r) const
Check whether a local pointer points to the same value on all processors where it is not null...
void broadcast(T &data, const unsigned int root_id=0, const bool identical_sizes=false) const
Take a local value and broadcast it to all processors.
StandardType<T>&#39;s which do not define a way to MPI_Type T should inherit from this class...
Definition: data_type.h:120
void split_by_type(int split_type, int key, info i, Communicator &target) const
Definition: communicator.C:111
void map_sum(Map &data) const
Private implementation function called by the map-based sum() specializations.
Encapsulates the MPI_Request.
Definition: request.h:67
Communicator & operator=(const Communicator &)=delete
timpi_pure bool verify(const T &r) const
Check whether a local variable has the same value on all processors, returning true if it does or fal...
void max(const T &r, T &o, Request &req) const
Non-blocking maximum of the local value r into o with the request req.
DIE A HORRIBLE DEATH HERE typedef MPI_Comm communicator
Communicator object for talking with subsets of processors.
Definition: communicator.h:74
Communicator()
Default Constructor.
Definition: communicator.C:59
void dereference_unique_tag(int tagvalue) const
Dereference an already-acquired tag, and see if we can re-release it.
Definition: communicator.C:46
void send(const unsigned int dest_processor_id, const T &buf, const MessageTag &tag=no_tag) const
Blocking-send to one processor with data-defined type.
SendMode send_mode() const
Gets the user-requested SendMode.
Definition: communicator.h:338
void logical_and(T &r) const
Take a local variable and replace it with the logical_and of its values on all processors.
void reference_unique_tag(int tagvalue) const
Reference an already-acquired tag, so that we know it will be dereferenced multiple times before we c...
Definition: communicator.C:37
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, const T *output_type, const MessageTag &send_tag=no_tag, const MessageTag &recv_tag=any_tag, std::size_t approx_buffer_size=1000000) const
Send a range-of-pointers to one processor while simultaneously receiving another range from a (potent...
Encapsulates the MPI_Status struct.
Definition: status.h:75
void duplicate(const Communicator &comm)
Definition: communicator.C:137
void nonblocking_barrier(Request &req) const
Start a barrier that doesn&#39;t block.
Definition: communicator.C:238
void set_union(T &data, const unsigned int root_id) const
Take a container (set, map, unordered_set, multimap, etc) of local variables on each processor...