TIMPI
Loading...
Searching...
No Matches
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
46namespace TIMPI
47{
48
51
52// Define processor id storage type.
53#if TIMPI_PROCESSOR_ID_BYTES == 1
55#elif TIMPI_PROCESSOR_ID_BYTES == 2
57#elif TIMPI_PROCESSOR_ID_BYTES == 4
58typedef uint32_t processor_id_type; // default
59#elif TIMPI_PROCESSOR_ID_BYTES == 8
61#else
62// We should not get here: it's not currently possible to set any
63// other size.
65#endif
66
67
68#ifdef TIMPI_HAVE_MPI
69
70//-------------------------------------------------------------------
75
79typedef MPI_Info info;
80
84const 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.
92typedef int communicator; // Must match petsc-nompi definition
93
94typedef int info;
95
96const unsigned int any_source=0;
97
98#endif // TIMPI_HAVE_MPI
99
100//-------------------------------------------------------------------
109{
110 // Basic operations:
111public:
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;
130
131 /*
132 * Move constructor and assignment operator
133 */
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
168
169 const communicator & get() const { return _communicator; }
170
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
228private:
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
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>
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>
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:
328public:
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>
377 inline
378 bool verify(const T & r) const;
379
390 template <typename T>
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
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>
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,
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,
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,
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
961 const Context * context,
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,
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,
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
1039 Context * context,
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,
1109 const RangeIter send_end,
1110 const unsigned int source_processor_id,
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
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,
1386 const Iter range_end,
1388 std::size_t approx_buffer_size = 1000000) const;
1389
1405 template <typename Context, typename Iter, typename OutputIter>
1408 const Iter range_end,
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
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>
1484 const Iter range_end,
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
1506namespace libMesh {
1507namespace Parallel {
1509public:
1510 Communicator () = default;
1511 explicit Communicator (const TIMPI::communicator & comm) : TIMPI::Communicator(comm) {}
1512 Communicator (const Communicator &) = delete;
1516 ~Communicator () = default;
1517};
1518}
1519}
1520
1521#endif // TIMPI_COMMUNICATOR_H
Encapsulates the MPI_Comm object.
void bitwise_and(T &r) const
Take a local variable and replace it with the bitwise_and of its values on all processors.
void max(const T &r, T &o, Request &req) const
Non-blocking maximum of the local value r into o with the request req.
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.
void bitwise_or(const T &r, T &o, Request &req) const
Non-blocking bitwise_or of the local value r into o with the request req.
void scatter(const std::vector< T, A1 > &data, const std::vector< int, A2 > counts, std::vector< T, A1 > &recv, const unsigned int root_id=0) const
vector<int> based scatter, for backwards compatibility
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.
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 ...
SendMode send_mode() const
Gets the user-requested SendMode.
processor_id_type size() const
void bitwise_or(T &r) const
Take a local variable and replace it with the bitwise_or of its values on all processors.
std::size_t packed_size_of(const std::vector< std::vector< T, A1 >, A2 > &buf, const DataType &type) const
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.
void set_union(T &data) const
Take a container of local variables on each processor, and replace it with their union over all proce...
void allgather(const std::vector< T, A1 > &send_data, std::vector< std::vector< T, A1 >, A2 > &recv_data, const bool identical_buffer_sizes=false) const
Take a vector of fixed size local variables and collect similar vectors from all processors.
void maxloc(T &r, unsigned int &max_id) const
Take a local variable and replace it with the maximum of it's values on all processors,...
MessageTag get_unique_tag(int tagvalue=MessageTag::invalid_tag) const
Get a tag that is unique to this Communicator.
void split(int color, int key, Communicator &target) const
processor_id_type _size
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.
void sum(const T &r, T &o, Request &req) const
Non-blocking sum of the local value r into o with the request req.
void logical_and(const T &r, T &o, Request &req) const
Non-blocking logical_and of the local value r into o with the request req.
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, A1 > &data, const std::vector< CountType, A2 > counts, std::vector< T, A1 > &recv, const unsigned int root_id=0) const
Take a vector of local variables and scatter the ith variable-sized chunk to the ith processor in the...
SendMode
Whether to use default or synchronous sends?
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:
status probe(const unsigned int src_processor_id, const MessageTag &tag=any_tag) const
Blocking message probe.
Communicator()
Default Constructor.
void send_receive(const unsigned int dest_processor_id, const T1 &send_data, const DataType &type1, const unsigned int source_processor_id, T2 &recv_data, const DataType &type2, 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...
Communicator(const Communicator &)=delete
void logical_or(const T &r, T &o, Request &req) const
Non-blocking logical_or of the local value r into o with the request req.
void clear()
Free and reset this communicator.
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.
processor_id_type rank() const
void barrier() const
Pause execution until all processors reach a certain point.
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...
Communicator & operator=(const Communicator &)=delete
Communicator(Communicator &&)=default
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.
void scatter(const std::vector< std::vector< T, A1 >, A2 > &data, std::vector< T, A1 > &recv, const unsigned int root_id=0, const bool identical_buffer_sizes=false) const
Take a vector of vectors and scatter the ith inner vector to the ith processor in the communicator.
void nonblocking_send_packed_range(const unsigned int dest_processor_id, const Context *context, Iter range_begin, const Iter range_end, Request &req, std::shared_ptr< std::vector< typename TIMPI::Packing< typename std::iterator_traits< Iter >::value_type >::buffer_type > > &buffer, const MessageTag &tag=no_tag) const
Similar to the above Nonblocking send_packed_range with a few important differences:
void gather(const unsigned int root_id, const std::basic_string< T > &send_data, std::vector< std::basic_string< T >, A > &recv_data, const bool identical_buffer_sizes=false) const
The gather overload for string types has an optional identical_buffer_sizes optimization for when all...
void logical_and(T &r) const
Take a local variable and replace it with the logical_and of its values on all processors.
void map_max(Map &data) const
Private implementation function called by the map-based max() specializations.
void alltoall(std::vector< T, A > &r) const
Effectively transposes the input vector across all processors.
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 max(T &r) const
Take a local variable and replace it with the maximum of it's 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 map_sum(Map &data) const
Private implementation function called by the map-based sum() specializations.
void min(const T &r, T &o, Request &req) const
Non-blocking minimum of the local value r into o with the request req.
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 send_mode(const SendMode sm)
Explicitly sets the SendMode type used for send operations.
void product(const T &r, T &o, Request &req) const
Non-blocking product of the local value r into o with the request req.
void allgather(std::vector< std::basic_string< T >, A > &r, const bool identical_buffer_sizes=false) const
AllGather overload for vectors of string types.
void logical_xor(T &r) const
Take a local variable and replace it with the logical_xor of its values on all processors.
processor_id_type _rank
void bitwise_xor(const T &r, T &o, Request &req) const
Non-blocking bitwise_xor of the local value r into o with the request req.
void bitwise_and(const T &r, T &o, Request &req) const
Non-blocking bitwise_and of the local value r into o with the request req.
void min(T &r) const
Take a local variable and replace it with the minimum of it's values on all processors.
void product(T &r) const
Take a local variable and replace it with the product of its values on all processors.
communicator _communicator
void duplicate(const Communicator &comm)
void minloc(T &r, unsigned int &min_id) const
Take a local variable and replace it with the minimum of it's values on all processors,...
void sum(T &r) const
Take a local variable and replace it with the sum of it's values on all processors.
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...
void scatter(const std::vector< T, A > &data, std::vector< T, A > &recv, const unsigned int root_id=0) const
Take a vector of local variables and scatter the ith equal-sized chunk to the ith processor in the co...
void dereference_unique_tag(int tagvalue) const
Dereference an already-acquired tag, and see if we can re-release it.
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,...
void allgather(std::vector< T, A > &r, const bool identical_buffer_sizes=false) const
Take a vector of fixed size local variables and expand it to include values from all processors.
void nonblocking_receive_packed_range(const unsigned int src_processor_id, Context *context, OutputIter out, const T *output_type, Request &req, Status &stat, std::shared_ptr< std::vector< typename TIMPI::Packing< T >::buffer_type > > &buffer, const MessageTag &tag=any_tag) const
Non-Blocking-receive range-of-pointers from one processor.
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 logical_xor(const T &r, T &o, Request &req) const
Non-blocking logical_xor of the local value r into o with the request req.
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.
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.
SyncType
What algorithm to use for parallel synchronization?
void logical_or(T &r) const
Take a local variable and replace it with the logical_or of its values on all processors.
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.
void assign(const communicator &comm)
Utility function for setting our member variables from an MPI communicator.
void sync_type(const SyncType st)
Explicitly sets the SyncType used for sync operations.
void nonblocking_barrier(Request &req) const
Start a barrier that doesn't block.
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.
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 ...
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...
SyncType sync_type() const
Gets the user-requested SyncType.
void split_by_type(int split_type, int key, info i, Communicator &target) const
constexpr processor_id_type size() const
void gather(const unsigned int root_id, std::vector< T, A > &r) const
Take a vector of local variables and expand it on processor root_id to include values from all proces...
const communicator & get() const
std::map< int, unsigned int > used_tag_values
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 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.
communicator & get()
Encapsulates the MPI_Datatype.
Definition data_type.h:51
Encapsulates the MPI tag integers.
Definition message_tag.h:47
static const int invalid_tag
Invalid tag, to allow for default construction.
Definition message_tag.h:53
StandardType<T>'s which do not define a way to MPI_Type T should inherit from this class.
Definition data_type.h:121
Encapsulates the MPI_Request.
Definition request.h:68
Encapsulates the MPI_Status struct.
Definition status.h:76
Communicator(const TIMPI::communicator &comm)
Communicator(const Communicator &)=delete
Communicator & operator=(const Communicator &)=delete
Communicator(Communicator &&)=default
Define data types and (un)serialization functions for use when encoding a potentially-variable-size o...
Definition packing.h:60
const MessageTag any_tag
Default message tag ids.
MPI_Info info
Info object used by some MPI-3 methods.
DIE A HORRIBLE DEATH HERE typedef MPI_Comm communicator
Communicator object for talking with subsets of processors.
uint8_t processor_id_type
const unsigned int any_source
Processor id meaning "Accept from any source".
Tnew cast_int(Told oldvar)
const MessageTag no_tag