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 sum(T & r) const;
474 
479  template <typename T>
480  inline
481  void sum(const T & r, T & o, Request & req) const;
482 
497  template <typename T>
498  inline
499  void set_union(T & data, const unsigned int root_id) const;
500 
510  template <typename T>
511  inline
512  void set_union(T & data) const;
513 
518  status probe (const unsigned int src_processor_id,
519  const MessageTag & tag=any_tag) const;
520 
533  template <typename T>
534  inline
535  Status packed_range_probe (const unsigned int src_processor_id,
536  const MessageTag & tag,
537  bool & flag) const;
538 
542  template <typename T>
543  inline
544  void send (const unsigned int dest_processor_id,
545  const T & buf,
546  const MessageTag & tag=no_tag) const;
547 
551  template <typename T>
552  inline
553  void send (const unsigned int dest_processor_id,
554  const T & buf,
555  Request & req,
556  const MessageTag & tag=no_tag) const;
557 
565  template <typename T>
566  inline
567  void send (const unsigned int dest_processor_id,
568  const T & buf,
569  const DataType & type,
570  const MessageTag & tag=no_tag) const;
571 
579  template <typename T>
580  inline
581  void send (const unsigned int dest_processor_id,
582  const T & buf,
583  const DataType & type,
584  Request & req,
585  const MessageTag & tag=no_tag) const;
586 
591  template <typename T>
592  inline
593  void send (const unsigned int dest_processor_id,
594  const T & buf,
595  const NotADataType & type,
596  Request & req,
597  const MessageTag & tag=no_tag) const;
598 
602  template <typename T>
603  inline
604  Status receive (const unsigned int dest_processor_id,
605  T & buf,
606  const MessageTag & tag=any_tag) const;
607 
611  template <typename T>
612  inline
613  void receive (const unsigned int dest_processor_id,
614  T & buf,
615  Request & req,
616  const MessageTag & tag=any_tag) const;
617 
625  template <typename T>
626  inline
627  Status receive (const unsigned int dest_processor_id,
628  T & buf,
629  const DataType & type,
630  const MessageTag & tag=any_tag) const;
631 
639  template <typename T>
640  inline
641  void receive (const unsigned int dest_processor_id,
642  T & buf,
643  const DataType & type,
644  Request & req,
645  const MessageTag & tag=any_tag) const;
646 
665  template <typename T, typename A,
666  typename std::enable_if<std::is_base_of<DataType, StandardType<T>>::value, int>::type = 0>
667  inline
668  bool possibly_receive (unsigned int & src_processor_id,
669  std::vector<T,A> & buf,
670  Request & req,
671  const MessageTag & tag) const;
672 
681  template <typename T, typename A,
682  typename std::enable_if<Has_buffer_type<Packing<T>>::value, int>::type = 0>
683  inline
684  bool possibly_receive (unsigned int & src_processor_id,
685  std::vector<T,A> & buf,
686  Request & req,
687  const MessageTag & tag) const;
688 
689 
703  template <typename T, typename A, typename std::enable_if<std::is_base_of<DataType, StandardType<T>>::value, int>::type = 0>
704  inline
705  bool possibly_receive (unsigned int & src_processor_id,
706  std::vector<T,A> & buf,
707  const DataType & type,
708  Request & req,
709  const MessageTag & tag) const;
710 
723  template <typename T, typename A,
724  typename std::enable_if<Has_buffer_type<Packing<T>>::value, int>::type = 0>
725  inline
726  bool possibly_receive (unsigned int & src_processor_id,
727  std::vector<T,A> & buf,
728  const NotADataType & type,
729  Request & req,
730  const MessageTag & tag) const;
731 
755  template <typename Context, typename OutputIter, typename T>
756  bool possibly_receive_packed_range (unsigned int & src_processor_id,
757  Context * context,
758  OutputIter out,
759  const T * output_type,
760  Request & req,
761  const MessageTag & tag) const;
762 
782  template <typename Context, typename Iter>
783  inline
784  void send_packed_range (const unsigned int dest_processor_id,
785  const Context * context,
786  Iter range_begin,
787  const Iter range_end,
788  const MessageTag & tag=no_tag,
789  std::size_t approx_buffer_size = 1000000) const;
790 
810  template <typename Context, typename Iter>
811  inline
812  void send_packed_range (const unsigned int dest_processor_id,
813  const Context * context,
814  Iter range_begin,
815  const Iter range_end,
816  Request & req,
817  const MessageTag & tag=no_tag,
818  std::size_t approx_buffer_size = 1000000) const;
819 
828  template <typename Context, typename Iter>
829  inline
830  void nonblocking_send_packed_range (const unsigned int dest_processor_id,
831  const Context * context,
832  Iter range_begin,
833  const Iter range_end,
834  Request & req,
835  const MessageTag & tag=no_tag) const;
836 
837 
846  template <typename Context, typename Iter>
847  inline
848  void nonblocking_send_packed_range (const unsigned int dest_processor_id,
849  const Context * context,
850  Iter range_begin,
851  const Iter range_end,
852  Request & req,
853  std::shared_ptr<std::vector<typename TIMPI::Packing<typename std::iterator_traits<Iter>::value_type>::buffer_type>> & buffer,
854  const MessageTag & tag=no_tag) const;
855 
882  template <typename Context, typename OutputIter, typename T>
883  inline
884  void receive_packed_range (const unsigned int dest_processor_id,
885  Context * context,
886  OutputIter out,
887  const T * output_type, // used only to infer T
888  const MessageTag & tag=any_tag) const;
889 
902  template <typename Context, typename OutputIter, typename T>
903  inline
904  void nonblocking_receive_packed_range (const unsigned int src_processor_id,
905  Context * context,
906  OutputIter out,
907  const T * output_type,
908  Request & req,
909  Status & stat,
910  const MessageTag & tag=any_tag) const;
911 
924  template <typename Context, typename OutputIter, typename T>
925  inline
926  void nonblocking_receive_packed_range (const unsigned int src_processor_id,
927  Context * context,
928  OutputIter out,
929  const T * output_type,
930  Request & req,
931  Status & stat,
932  std::shared_ptr<std::vector<typename TIMPI::Packing<T>::buffer_type>> & buffer,
933  const MessageTag & tag=any_tag
934  ) const;
935 
943  template <typename T1, typename T2,
944  typename std::enable_if<std::is_base_of<DataType, StandardType<T1>>::value &&
945  std::is_base_of<DataType, StandardType<T2>>::value,
946  int>::type = 0>
947  inline
948  void send_receive(const unsigned int dest_processor_id,
949  const T1 & send_data,
950  const unsigned int source_processor_id,
951  T2 & recv_data,
952  const MessageTag & send_tag = no_tag,
953  const MessageTag & recv_tag = any_tag) const;
954 
991  template <typename Context1, typename RangeIter, typename Context2,
992  typename OutputIter, typename T>
993  inline
994  void send_receive_packed_range(const unsigned int dest_processor_id,
995  const Context1 * context1,
996  RangeIter send_begin,
997  const RangeIter send_end,
998  const unsigned int source_processor_id,
999  Context2 * context2,
1000  OutputIter out,
1001  const T * output_type, // used only to infer T
1002  const MessageTag & send_tag = no_tag,
1003  const MessageTag & recv_tag = any_tag,
1004  std::size_t approx_buffer_size = 1000000) const;
1005 
1011  template <typename T1, typename T2>
1012  inline
1013  void send_receive(const unsigned int dest_processor_id,
1014  const T1 & send_data,
1015  const DataType & type1,
1016  const unsigned int source_processor_id,
1017  T2 & recv_data,
1018  const DataType & type2,
1019  const MessageTag & send_tag = no_tag,
1020  const MessageTag & recv_tag = any_tag) const;
1021 
1026  template <typename T, typename A>
1027  inline void gather(const unsigned int root_id,
1028  const T & send_data,
1029  std::vector<T,A> & recv) const;
1030 
1036  template <typename T, typename A>
1037  inline void gather(const unsigned int root_id,
1038  const std::basic_string<T> & send_data,
1039  std::vector<std::basic_string<T>,A> & recv_data,
1040  const bool identical_buffer_sizes=false) const;
1041 
1068  template <typename T, typename A,
1069  typename std::enable_if<std::is_base_of<DataType, StandardType<T>>::value, int>::type = 0>
1070  inline void gather(const unsigned int root_id,
1071  std::vector<T,A> & r) const;
1072 
1073  template <typename T, typename A,
1074  typename std::enable_if<Has_buffer_type<Packing<T>>::value, int>::type = 0>
1075  inline void gather(const unsigned int root_id,
1076  std::vector<T,A> & r) const;
1077 
1083  template <typename T, typename A, typename std::enable_if<std::is_base_of<DataType, StandardType<T>>::value,
1084  int>::type = 0>
1085  inline void allgather(const T & send_data,
1086  std::vector<T,A> & recv_data) const;
1087 
1094  template <typename T, typename A, typename std::enable_if<Has_buffer_type<Packing<T>>::value,
1095  int>::type = 0>
1096  inline void allgather(const T & send_data,
1097  std::vector<T,A> & recv_data) const;
1098 
1104  template <typename T, typename A>
1105  inline void allgather(const std::basic_string<T> & send_data,
1106  std::vector<std::basic_string<T>,A> & recv_data,
1107  const bool identical_buffer_sizes=false) const;
1108 
1133  template <typename T, typename A,
1134  typename std::enable_if<std::is_base_of<DataType, StandardType<T>>::value, int>::type = 0>
1135  inline void allgather(std::vector<T,A> & r,
1136  const bool identical_buffer_sizes = false) const;
1137 
1145  template <typename T, typename A1, typename A2,
1146  typename std::enable_if<std::is_base_of<DataType, StandardType<T>>::value, int>::type = 0>
1147  inline void allgather(const std::vector<T,A1> & send_data,
1148  std::vector<std::vector<T,A1>, A2> & recv_data,
1149  const bool identical_buffer_sizes = false) const;
1150 
1155  template <typename T, typename A1, typename A2,
1156  typename std::enable_if<Has_buffer_type<Packing<T>>::value, int>::type = 0>
1157  inline void allgather(const std::vector<T,A1> & send_data,
1158  std::vector<std::vector<T,A1>, A2> & recv_data,
1159  const bool identical_buffer_sizes = false) const;
1160 
1185  template <typename T, typename A,
1186  typename std::enable_if<Has_buffer_type<Packing<T>>::value, int>::type = 0>
1187  inline void allgather(std::vector<T,A> & r,
1188  const bool identical_buffer_sizes = false) const;
1189 
1193  template <typename T, typename A>
1194  inline void allgather(std::vector<std::basic_string<T>,A> & r,
1195  const bool identical_buffer_sizes = false) const;
1196 
1197  //-------------------------------------------------------------------
1202  template <typename T, typename A>
1203  inline void scatter(const std::vector<T,A> & data,
1204  T & recv,
1205  const unsigned int root_id=0) const;
1206 
1213  template <typename T, typename A>
1214  inline void scatter(const std::vector<T,A> & data,
1215  std::vector<T,A> & recv,
1216  const unsigned int root_id=0) const;
1217 
1224  template <typename T, typename A1, typename A2>
1225  inline void scatter(const std::vector<T,A1> & data,
1226  const std::vector<CountType,A2> counts,
1227  std::vector<T,A1> & recv,
1228  const unsigned int root_id=0) const;
1229 
1230 #ifdef TIMPI_HAVE_MPI
1231 #if MPI_VERSION > 3
1232 
1235  template <typename T, typename A1, typename A2>
1236  inline void scatter(const std::vector<T,A1> & data,
1237  const std::vector<int,A2> counts,
1238  std::vector<T,A1> & recv,
1239  const unsigned int root_id=0) const;
1240 #endif
1241 #endif
1242 
1248  template <typename T, typename A1, typename A2>
1249  inline void scatter(const std::vector<std::vector<T,A1>,A2> & data,
1250  std::vector<T,A1> & recv,
1251  const unsigned int root_id=0,
1252  const bool identical_buffer_sizes=false) const;
1253 
1254  //-------------------------------------------------------------------
1270  template <typename Context, typename Iter, typename OutputIter>
1271  inline void gather_packed_range (const unsigned int root_id,
1272  Context * context,
1273  Iter range_begin,
1274  const Iter range_end,
1275  OutputIter out,
1276  std::size_t approx_buffer_size = 1000000) const;
1277 
1293  template <typename Context, typename Iter, typename OutputIter>
1294  inline void allgather_packed_range (Context * context,
1295  Iter range_begin,
1296  const Iter range_end,
1297  OutputIter out,
1298  std::size_t approx_buffer_size = 1000000) const;
1299 
1305  template <typename T, typename A>
1306  inline void alltoall(std::vector<T,A> & r) const;
1307 
1319  template <typename T
1320 #ifdef TIMPI_HAVE_MPI
1321  ,
1322  typename std::enable_if<std::is_base_of<DataType, StandardType<T>>::value, int>::type = 0
1323 #endif
1324  >
1325  inline void broadcast(T & data, const unsigned int root_id=0,
1326  const bool identical_sizes=false) const;
1327 
1328 #ifdef TIMPI_HAVE_MPI
1329 
1340  template <typename T,
1341  typename std::enable_if<Has_buffer_type<Packing<T>>::value, int>::type = 0>
1342  inline void broadcast(T & data, const unsigned int root_id=0,
1343  const bool identical_sizes=false) const;
1344 #endif
1345 
1369  template <typename Context, typename OutputContext, typename Iter, typename OutputIter>
1370  inline void broadcast_packed_range (const Context * context1,
1371  Iter range_begin,
1372  const Iter range_end,
1373  OutputContext * context2,
1374  OutputIter out,
1375  const unsigned int root_id = 0,
1376  std::size_t approx_buffer_size = 1000000) const;
1377 
1385 #include "timpi/parallel_communicator_specializations"
1386 
1387 }; // class Communicator
1388 
1389 
1390 } // namespace TIMPI
1391 
1392 
1393 // Backwards compatibility for libMesh forward declarations
1394 namespace libMesh {
1395 namespace Parallel {
1397 public:
1398  Communicator () = default;
1399  explicit Communicator (const TIMPI::communicator & comm) : TIMPI::Communicator(comm) {}
1400  Communicator (const Communicator &) = delete;
1401  Communicator & operator= (const Communicator &) = delete;
1402  Communicator (Communicator &&) = default;
1403  Communicator & operator= (Communicator &&) = default;
1404  ~Communicator () = default;
1405 };
1406 }
1407 }
1408 
1409 #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 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 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
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 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 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...