12 #define TIMPI_UNIT_ASSERT(expr) \ 18 std::string digit_strings [10] = {
"zero",
"one",
"two",
19 "three",
"four",
"five",
"six",
"seven",
"eight",
"nine"};
21 std::string returnval =
"done";
24 returnval = digit_strings[number%10]+
" "+returnval;
35 return std::vector<char>(returnval.begin(), returnval.end());
47 template <
typename T2>
64 template <
int i,
typename T>
66 auto my_get(T & container) -> decltype(std::get<i>(container))
68 return std::get<i>(container);
72 template <
int i,
typename T>
74 auto my_get(T & container) -> decltype(*container.begin())
76 auto fwd_it = container.begin();
77 for (
int n_it = 0; n_it < i; ++n_it)
84 template <
int i,
typename T, std::
size_t N>
86 auto my_get(std::array<T, N> & container) -> decltype(std::get<i>(container))
88 return std::get<i>(container);
93 inline void my_resize(T & container, std::size_t size) { container.resize(size); }
95 template <
typename T,
typename U>
96 inline void my_resize(std::pair<T,U> &, std::size_t) {}
98 template <
typename ... Types>
99 inline void my_resize(std::tuple<Types...> &, std::size_t) {}
101 template <
typename T, std::
size_t N>
102 inline void my_resize(std::array<T,N> &, std::size_t) {}
105 #if __cplusplus > 201402L 116 static unsigned int packed_size(
typename std::vector<int>::const_iterator) {
return 1; }
117 static unsigned int packable_size(
const std::unique_ptr<int> &,
const void *) {
return 1; }
119 template <
typename Iter>
120 static void pack(
const std::unique_ptr<int> &
object, Iter data_out,
const void *) { data_out = *object; }
122 template <
typename BufferIter>
123 static std::unique_ptr<int>
unpack(BufferIter in,
const void *)
125 return std::make_unique<int>(*in++);
132 using namespace TIMPI;
138 std::vector<std::string> send(1);
140 send[0].assign(
"Hello");
142 send[0].assign(
"Goodbye");
145 ((
void *)(NULL), send.begin(), send.end(),
152 template <
typename PairAtLeast>
155 std::vector<PairAtLeast> sendv(2);
159 my_get<0>(sendv[0]).assign(
"Hello");
160 auto & s0 = my_get<1>(sendv[0]);
161 s0.assign(
"Is it me you're looking for?\n");
162 for (
int i=0; i != 6; ++i)
164 timpi_assert_greater(s0.size(), 256);
166 my_get<0>(sendv[1]).assign(
"Goodbye");
167 auto & s1 = my_get<1>(sendv[1]);
168 s1.assign(
"to you! Guess it's better to say, goodbye\n");
169 for (
int i=0; i != 6; ++i)
171 timpi_assert_greater(s1.size(), 256);
173 std::vector<PairAtLeast> send(1);
181 std::vector<PairAtLeast> recv;
184 ((
void *)(NULL), send.begin(), send.end(),
185 std::back_inserter(recv));
188 const std::size_t vec_size = recv.size();
189 TIMPI_UNIT_ASSERT(comm_size == vec_size);
191 TIMPI_UNIT_ASSERT(sendv[0] == recv[0]);
192 for (std::size_t i=1; i < vec_size; ++i)
193 TIMPI_UNIT_ASSERT(sendv[1] == recv[i]);
199 testGettableStringAllGather<std::pair<std::string, std::string>>();
205 testGettableStringAllGather<std::array<std::string, 4>>();
211 testGettableStringAllGather<std::list<std::string>>();
217 testGettableStringAllGather<std::vector<std::string>>();
226 #ifdef TIMPI_HAVE_CXX17 // static_assert without message 236 std::vector<std::tuple<std::string, std::string, int>> sendv(2);
238 auto & s0 = std::get<1>(sendv[0]);
239 std::get<0>(sendv[0]).assign(
"Hello");
240 s0.assign(
"Is it me you're looking for?\n");
241 for (
int i=0; i != 6; ++i)
243 timpi_assert_greater(s0.size(), 256);
244 std::get<2>(sendv[0]) = 257;
246 auto & s1 = std::get<1>(sendv[1]);
247 std::get<0>(sendv[1]).assign(
"Goodbye");
248 s1.assign(
"to you! Guess it's better to say, goodbye\n");
249 for (
int i=0; i != 6; ++i)
251 timpi_assert_greater(s1.size(), 256);
252 std::get<2>(sendv[1]) = 258;
254 std::vector<std::tuple<std::string, std::string, int>> send(1);
260 std::vector<std::tuple<std::string, std::string, int>> recv;
263 ((
void *)(NULL), send.begin(), send.end(),
264 std::back_inserter(recv));
267 const std::size_t vec_size = recv.size();
268 TIMPI_UNIT_ASSERT(comm_size == vec_size);
270 TIMPI_UNIT_ASSERT(sendv[0] == recv[0]);
271 for (std::size_t i=1; i < vec_size; ++i)
272 TIMPI_UNIT_ASSERT(sendv[1] == recv[i]);
281 typedef std::tuple<unsigned int, std::vector<std::tuple<char,int,std::size_t>>,
unsigned int> send_type;
283 #ifdef TIMPI_HAVE_CXX17 // static_assert without message 288 std::vector<send_type> sendv(2);
290 std::get<0>(sendv[0]) = 100;
291 std::get<1>(sendv[0]) = {{
'a', -4, 1000},{
'b', -5, 2000}};
292 std::get<2>(sendv[0]) = 3000;
294 std::get<0>(sendv[1]) = 200;
295 std::get<1>(sendv[1]) = {{
'c', -6, 4000},{
'd', -7, 5000}};
296 std::get<2>(sendv[1]) = 6000;
298 std::vector<send_type> send(1);
304 std::vector<send_type> recv;
307 ((
void *)(NULL), send.begin(), send.end(),
308 std::back_inserter(recv));
311 const std::size_t vec_size = recv.size();
312 TIMPI_UNIT_ASSERT(comm_size == vec_size);
314 TIMPI_UNIT_ASSERT(sendv[0] == recv[0]);
315 for (std::size_t i=1; i < vec_size; ++i)
316 TIMPI_UNIT_ASSERT(sendv[1] == recv[i]);
323 std::vector<std::string> send(1);
325 const unsigned int dest_rank =
327 const unsigned int source_rank =
331 std::ostringstream os;
337 (dest_rank, (
void *)(NULL), send.begin(), send.end(),
338 source_rank, (
void *)(NULL),
347 #ifdef TIMPI_HAVE_MPI 348 std::vector<std::string> vals;
353 const std::size_t vec_size = vals.size();
354 TIMPI_UNIT_ASSERT(comm_size == vec_size);
356 for (std::size_t i = 0; i < vec_size; ++i)
357 TIMPI_UNIT_ASSERT(vals[i] == std::string(i + 1,
'0' + i));
363 std::vector<processor_id_type> vals;
365 std::vector<std::string> send(1), recv;
368 const unsigned int dest_rank =
370 const unsigned int source_rank =
374 std::ostringstream os;
380 (dest_rank, (
void *)(NULL), send.begin(), send.end(),
381 source_rank, (
void *)(NULL),
382 std::back_inserter(recv),
385 TIMPI_UNIT_ASSERT(recv.size() == std::size_t(1));
389 std::ostringstream os;
394 TIMPI_UNIT_ASSERT(recv[0] == check);
400 const unsigned int n_map_entries = 147;
403 const unsigned int map_offset = 1000;
406 const unsigned int string_size = 32768;
409 std::string test_string(string_size,
'a');
411 std::map<unsigned int, std::string> map_of_strings;
414 const unsigned int my_offset =
416 for (
unsigned int i=0; i != n_map_entries; ++i)
417 map_of_strings[my_offset + i] = test_string;
421 TIMPI_UNIT_ASSERT(map_of_strings.size() ==
424 TIMPI_UNIT_ASSERT(map_of_strings.begin()->first == map_offset);
433 std::map<processor_id_type, std::multiset<std::string>>
438 std::string digit_strings [10] = {
"zero",
"one",
"two",
439 "three",
"four",
"five",
"six",
"seven",
"eight",
"nine"};
441 std::string returnval =
"done";
444 returnval = digit_strings[number%10]+
" "+returnval;
451 for (
int d=0; d != M; ++d)
453 int diffsize = std::abs(d-rank);
454 int diffsqrt = std::sqrt(diffsize);
455 if (diffsqrt*diffsqrt == diffsize)
456 for (
int i=-1; i != diffsqrt; ++i)
463 const typename std::multiset<std::string> & multiset_received)
465 auto & received = received_data[pid];
466 received.insert(multiset_received.begin(), multiset_received.end());
471 std::map<processor_id_type, std::multiset<std::string>> preserved_data {data};
474 void * context =
nullptr;
478 TIMPI_UNIT_ASSERT(preserved_data.size() == data.size());
479 for (
const auto & pair: preserved_data)
481 const auto &pd_ms = pair.second;
482 const auto &d_ms = data[pair.first];
483 TIMPI_UNIT_ASSERT(pd_ms.size() == d_ms.size());
484 for (
auto entry : pd_ms)
485 TIMPI_UNIT_ASSERT(pd_ms.count(entry) == d_ms.count(entry));
490 std::vector<std::size_t> checked_sizes(size, 0);
491 for (
int p=rank; p < M; p += size)
492 for (
int srcp=0; srcp != size; ++srcp)
494 int diffsize = std::abs(srcp-p);
495 int diffsqrt = std::sqrt(diffsize);
496 if (diffsqrt*diffsqrt != diffsize)
498 if (received_data.count(srcp))
500 const std::multiset<std::string> & datum = received_data[srcp];
502 (std::count(datum.begin(), datum.end(),
508 TIMPI_UNIT_ASSERT(received_data.count(srcp) == std::size_t(1));
509 const std::multiset<std::string> & datum = received_data[srcp];
512 std::ptrdiff_t(diffsqrt+1));
513 checked_sizes[srcp] += diffsqrt+1;
516 for (
int srcp=0; srcp != size; ++srcp)
517 TIMPI_UNIT_ASSERT(checked_sizes[srcp] == received_data[srcp].size());
531 template <
typename FillFunctor,
typename PushFunctor>
537 typedef decltype(fill_functor(0)) fill_type;
539 typedef std::vector<fill_type> vec_type;
540 std::map<processor_id_type, vec_type> data, received_data;
542 for (
int d=0; d != size; ++d)
544 int diffsize = std::abs(d-rank);
545 int diffsqrt = std::sqrt(diffsize);
546 if (diffsqrt*diffsqrt == diffsize)
547 for (
int i=-1; i != diffsqrt; ++i)
548 data[d].push_back(fill_functor(d));
554 const vec_type & vec_received)
556 auto & received = received_data[pid];
557 received = vec_received;
562 std::map<processor_id_type, vec_type> preserved_data {data};
565 push_functor(data, collect_data);
568 TIMPI_UNIT_ASSERT(preserved_data == data);
572 std::vector<std::size_t> checked_sizes(size, 0);
573 for (
int srcp=0; srcp != size; ++srcp)
575 int diffsize = std::abs(srcp-rank);
576 int diffsqrt = std::sqrt(diffsize);
577 if (diffsqrt*diffsqrt != diffsize)
579 TIMPI_UNIT_ASSERT(!received_data.count(srcp));
583 TIMPI_UNIT_ASSERT(received_data.count(srcp));
584 const auto & rec = received_data[srcp];
585 TIMPI_UNIT_ASSERT(rec.size() == std::size_t(diffsqrt+1));
587 for (
auto & tup : rec)
588 TIMPI_UNIT_ASSERT(tup == fill_functor(rank));
596 auto explicitly_packed_push = [](
auto & data,
auto & collect_data) {
597 void * context =
nullptr;
601 typedef std::tuple<unsigned int, std::vector<char>,
unsigned int,
602 unsigned int,
unsigned int,
unsigned int> tuple_type;
603 auto fill_tuple= [] (
int n) {
614 auto implicitly_packed_push = [](
auto & data,
auto & collect_data) {
618 typedef std::tuple<unsigned int, std::vector<char>,
unsigned int,
619 unsigned int,
unsigned int,
unsigned int> tuple_type;
620 auto fill_tuple= [] (
int n) {
630 typedef std::tuple<std::unordered_map<unsigned int, std::string>> tuple_type;
631 #ifdef TIMPI_HAVE_CXX17 // static_assert without message 634 static_assert(
TIMPI::StandardType<std::pair<const unsigned int, unsigned int>>::is_fixed_type);
645 auto fill_tuple = [] (
int n)
647 tuple_type returnval;
653 auto implicitly_packed_push = [](
auto & data,
auto & collect_data) {
664 typedef std::tuple<std::size_t, int, std::unordered_map<unsigned int, std::string>> tuple_type;
666 auto fill_tuple = [] (
int n)
668 tuple_type returnval;
669 std::get<0>(returnval) = n;
670 std::get<1>(returnval) = n;
676 auto implicitly_packed_push = [](
auto & data,
auto & collect_data) {
684 #if __cplusplus > 201402L 690 std::map<processor_id_type, std::vector<std::unique_ptr<int>>>
693 for (
int d=0; d != M; ++d)
695 int diffsize = std::abs(d-rank);
696 int diffsqrt = std::sqrt(diffsize);
697 if (diffsqrt*diffsqrt == diffsize)
698 for (
int i=-1; i != diffsqrt; ++i)
699 data[d].emplace_back(std::make_unique<int>(d));
705 std::vector<std::unique_ptr<int>> && vector_received)
707 auto & received = received_data[pid];
708 for (
auto & val : vector_received)
709 received.emplace_back(std::move(val));
712 void * context =
nullptr;
717 std::vector<std::size_t> checked_sizes(size, 0);
718 for (
int p=rank; p < M; p += size)
719 for (
int srcp=0; srcp != size; ++srcp)
721 int diffsize = std::abs(srcp-p);
722 int diffsqrt = std::sqrt(diffsize);
723 if (diffsqrt*diffsqrt != diffsize)
725 if (received_data.count(srcp))
727 std::size_t count = 0;
728 for (
const auto & val : received_data[srcp])
732 TIMPI_UNIT_ASSERT(count == (std::size_t)std::ptrdiff_t(0));
737 TIMPI_UNIT_ASSERT(received_data.count(srcp) == std::size_t(1));
739 std::size_t count = 0;
740 for (
const auto & val : received_data[srcp])
744 TIMPI_UNIT_ASSERT(count == (std::size_t)std::ptrdiff_t(diffsqrt+1));
745 checked_sizes[srcp] += diffsqrt+1;
748 for (
int srcp=0; srcp != size; ++srcp)
749 TIMPI_UNIT_ASSERT(checked_sizes[srcp] == received_data[srcp].size());
763 int main(
int argc,
const char *
const * argv)
785 #if __cplusplus > 201402L 797 #if __cplusplus > 201402L 809 #if __cplusplus > 201402L std::vector< char > fake_stringy_number(int number)
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...
std::ptrdiff_t difference_type
void testPushPackedFailureCase()
void testPushPackedOversized()
void sync_type(const SyncType st)
Explicitly sets the SyncType used for sync operations.
void testPushPackedDispatch()
void testPushPackedMoveOversized()
The TIMPIInit class, when constructed, initializes any dependent libraries (e.g.
static void pack(const std::unique_ptr< int > &object, Iter data_out, const void *)
void push_parallel_packed_range(const Communicator &comm, MapToVectors &&data, Context *context, const ActionFunctor &act_on_data)
Send and receive and act on vectors of data.
void testPushPackedMove()
void my_resize(T &container, std::size_t size)
processor_id_type rank() const
Communicator * TestCommWorld
void testContainerAllGather()
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 ...
Templated class to provide the appropriate MPI datatype for use with built-in C types or simple C++ c...
Define data types and (un)serialization functions for use when encoding a potentially-variable-size o...
null_output_iterator & operator*()
void testVectorStringAllGather()
int main(int argc, const char *const *argv)
null_output_iterator operator++(int)
void testNullSendReceive()
Encapsulates the MPI_Comm object.
static unsigned int packable_size(const std::unique_ptr< int > &, const void *)
static unsigned int packed_size(typename std::vector< int >::const_iterator)
processor_id_type size() const
void push_parallel_vector_data(const Communicator &comm, MapToVectors &&data, const ActionFunctor &act_on_data)
Send and receive and act on vectors of data.
std::string stringy_number(int number)
uint8_t processor_id_type
void operator=(const T2 &)
void testPushPackedNestedImpl(FillFunctor fill_functor, PushFunctor push_functor)
null_output_iterator & operator++()
void testNestingAllGather()
void testGettableStringAllGather()
static std::unique_ptr< int > unpack(BufferIter in, const void *)
void testArrayStringAllGather()
void testListStringAllGather()
std::output_iterator_tag iterator_category
void testContainerSendReceive()
auto my_get(T &container) -> decltype(std::get< i >(container))
void testPushPackedImpl(int M)
void testPairStringAllGather()
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...
void testPushPackedNested()
void testTupleStringAllGather()
void testPushPackedImplMove(int M)
void testPushPackedOneTuple()
const Communicator & comm() const
Returns the Communicator created by this object, which will be a compatibility shim if MPI is not ena...
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...