TIMPI
Classes | Namespaces | Functions | Variables
packed_range_unit.C File Reference

Go to the source code of this file.

Classes

struct  null_output_iterator< T >
 
class  libMesh::Parallel::Packing< std::unique_ptr< int > >
 

Namespaces

 libMesh
 
 libMesh::Parallel
 

Functions

std::string stringy_number (int number)
 
std::vector< char > fake_stringy_number (int number)
 
template<int i, typename T >
auto my_get (T &container) -> decltype(std::get< i >(container))
 
template<int i, typename T , std::size_t N>
auto my_get (std::array< T, N > &container) -> decltype(std::get< i >(container))
 
template<typename T >
void my_resize (T &container, std::size_t size)
 
template<typename T , typename U >
void my_resize (std::pair< T, U > &, std::size_t)
 
template<typename ... Types>
void my_resize (std::tuple< Types... > &, std::size_t)
 
template<typename T , std::size_t N>
void my_resize (std::array< T, N > &, std::size_t)
 
void testNullAllGather ()
 
template<typename PairAtLeast >
void testGettableStringAllGather ()
 
void testPairStringAllGather ()
 
void testArrayStringAllGather ()
 
void testListStringAllGather ()
 
void testVectorStringAllGather ()
 
void testTupleStringAllGather ()
 
void testNestingAllGather ()
 
void testNullSendReceive ()
 
void testContainerAllGather ()
 
void testContainerSendReceive ()
 
void testLargeSetUnion ()
 
void testPushPackedImpl (int M)
 
void testPushPacked ()
 
void testPushPackedOversized ()
 
template<typename FillFunctor , typename PushFunctor >
void testPushPackedNestedImpl (FillFunctor fill_functor, PushFunctor push_functor)
 
void testPushPackedNested ()
 
void testPushPackedDispatch ()
 
void testPushPackedOneTuple ()
 
void testPushPackedFailureCase ()
 
void testPushPackedImplMove (int M)
 
void testPushPackedMove ()
 
void testPushPackedMoveOversized ()
 
int main (int argc, const char *const *argv)
 

Variables

CommunicatorTestCommWorld
 

Function Documentation

◆ fake_stringy_number()

std::vector<char> fake_stringy_number ( int  number)

Definition at line 32 of file packed_range_unit.C.

References stringy_number().

Referenced by testPushPackedDispatch(), and testPushPackedNested().

33 {
34  const std::string returnval = stringy_number(number);
35  return std::vector<char>(returnval.begin(), returnval.end());
36 }
std::string stringy_number(int number)

◆ main()

int main ( int  argc,
const char *const *  argv 
)

Definition at line 763 of file packed_range_unit.C.

References TIMPI::Communicator::ALLTOALL_COUNTS, TIMPI::TIMPIInit::comm(), TIMPI::Communicator::SENDRECEIVE, TIMPI::Communicator::sync_type(), testArrayStringAllGather(), TestCommWorld, testContainerAllGather(), testContainerSendReceive(), testLargeSetUnion(), testNestingAllGather(), testNullAllGather(), testNullSendReceive(), testPairStringAllGather(), testPushPacked(), testPushPackedDispatch(), testPushPackedFailureCase(), testPushPackedMove(), testPushPackedMoveOversized(), testPushPackedNested(), testPushPackedOneTuple(), testPushPackedOversized(), and testTupleStringAllGather().

764 {
765  TIMPI::TIMPIInit init(argc, argv);
766  TestCommWorld = &init.comm();
767 
776 
778 
779  testPushPacked();
785 #if __cplusplus > 201402L
788 #endif
789 
790  TestCommWorld->sync_type(Communicator::ALLTOALL_COUNTS);
791  testPushPacked();
797 #if __cplusplus > 201402L
800 #endif
801 
802  TestCommWorld->sync_type(Communicator::SENDRECEIVE);
803  testPushPacked();
809 #if __cplusplus > 201402L
812 #endif
813 
814  return 0;
815 }
void testPushPackedFailureCase()
void testPushPackedOversized()
void sync_type(const SyncType st)
Explicitly sets the SyncType used for sync operations.
Definition: communicator.h:343
void testPushPackedDispatch()
void testPushPackedMoveOversized()
The TIMPIInit class, when constructed, initializes any dependent libraries (e.g.
Definition: timpi_init.h:57
void testPushPackedMove()
Communicator * TestCommWorld
void testContainerAllGather()
void testPushPacked()
void testNullSendReceive()
void testNestingAllGather()
void testNullAllGather()
void testArrayStringAllGather()
void testContainerSendReceive()
void testLargeSetUnion()
void testPairStringAllGather()
void testPushPackedNested()
void testTupleStringAllGather()
void testPushPackedOneTuple()

◆ my_get() [1/2]

template<int i, typename T >
auto my_get ( T &  container) -> decltype(std::get<i>(container))
inline

Definition at line 66 of file packed_range_unit.C.

67 {
68  return std::get<i>(container);
69 }

◆ my_get() [2/2]

template<int i, typename T , std::size_t N>
auto my_get ( std::array< T, N > &  container) -> decltype(std::get<i>(container))
inline

Definition at line 86 of file packed_range_unit.C.

87 {
88  return std::get<i>(container);
89 }

◆ my_resize() [1/4]

template<typename T >
void my_resize ( T &  container,
std::size_t  size 
)
inline

Definition at line 93 of file packed_range_unit.C.

Referenced by testGettableStringAllGather().

93 { container.resize(size); }

◆ my_resize() [2/4]

template<typename T , typename U >
void my_resize ( std::pair< T, U > &  ,
std::size_t   
)
inline

Definition at line 96 of file packed_range_unit.C.

96 {}

◆ my_resize() [3/4]

template<typename ... Types>
void my_resize ( std::tuple< Types... > &  ,
std::size_t   
)
inline

Definition at line 99 of file packed_range_unit.C.

99 {}

◆ my_resize() [4/4]

template<typename T , std::size_t N>
void my_resize ( std::array< T, N > &  ,
std::size_t   
)
inline

Definition at line 102 of file packed_range_unit.C.

102 {}

◆ stringy_number()

std::string stringy_number ( int  number)

Definition at line 16 of file packed_range_unit.C.

Referenced by fake_stringy_number(), fill_data(), testPushPackedFailureCase(), testPushPackedImpl(), and testPushPackedOneTuple().

17 {
18  std::string digit_strings [10] = {"zero", "one", "two",
19  "three", "four", "five", "six", "seven", "eight", "nine"};
20 
21  std::string returnval = "done";
22  while (number)
23  {
24  returnval = digit_strings[number%10]+" "+returnval;
25  number = number/10;
26  };
27 
28  return returnval;
29 }

◆ testArrayStringAllGather()

void testArrayStringAllGather ( )

Definition at line 203 of file packed_range_unit.C.

Referenced by main().

204  {
205  testGettableStringAllGather<std::array<std::string, 4>>();
206  }

◆ testContainerAllGather()

void testContainerAllGather ( )

Definition at line 343 of file packed_range_unit.C.

References TIMPI::Communicator::allgather(), TIMPI::Communicator::rank(), TIMPI::Communicator::size(), and TestCommWorld.

Referenced by main().

344  {
345  // This method uses a specialized allgather method that is only defined
346  // when we have MPI
347 #ifdef TIMPI_HAVE_MPI
348  std::vector<std::string> vals;
349  const unsigned int my_rank = TestCommWorld->rank();
350  TestCommWorld->allgather(std::string(my_rank+1, '0' + my_rank), vals);
351 
352  const std::size_t comm_size = TestCommWorld->size();
353  const std::size_t vec_size = vals.size();
354  TIMPI_UNIT_ASSERT(comm_size == vec_size);
355 
356  for (std::size_t i = 0; i < vec_size; ++i)
357  TIMPI_UNIT_ASSERT(vals[i] == std::string(i + 1, '0' + i));
358 #endif
359  }
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...
processor_id_type rank() const
Definition: communicator.h:208
Communicator * TestCommWorld
processor_id_type size() const
Definition: communicator.h:211

◆ testContainerSendReceive()

void testContainerSendReceive ( )

Definition at line 361 of file packed_range_unit.C.

References TIMPI::Communicator::rank(), TIMPI::Communicator::send_receive_packed_range(), TIMPI::Communicator::size(), and TestCommWorld.

Referenced by main().

362  {
363  std::vector<processor_id_type> vals;
364 
365  std::vector<std::string> send(1), recv;
366 
367  const unsigned int my_rank = TestCommWorld->rank();
368  const unsigned int dest_rank =
369  (my_rank + 1) % TestCommWorld->size();
370  const unsigned int source_rank =
371  (my_rank + TestCommWorld->size() - 1) % TestCommWorld->size();
372 
373  {
374  std::ostringstream os;
375  os << my_rank;
376  send[0] = os.str();
377  }
378 
380  (dest_rank, (void *)(NULL), send.begin(), send.end(),
381  source_rank, (void *)(NULL),
382  std::back_inserter(recv),
383  (std::string*)NULL);
384 
385  TIMPI_UNIT_ASSERT(recv.size() == std::size_t(1));
386 
387  std::string check;
388  {
389  std::ostringstream os;
390  os << source_rank;
391  check = os.str();
392  }
393 
394  TIMPI_UNIT_ASSERT(recv[0] == check);
395  }
processor_id_type rank() const
Definition: communicator.h:208
Communicator * TestCommWorld
processor_id_type size() const
Definition: communicator.h:211
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...

◆ testGettableStringAllGather()

template<typename PairAtLeast >
void testGettableStringAllGather ( )

Definition at line 153 of file packed_range_unit.C.

References TIMPI::Communicator::allgather_packed_range(), my_resize(), TIMPI::Communicator::rank(), TIMPI::Communicator::size(), and TestCommWorld.

154  {
155  std::vector<PairAtLeast> sendv(2);
156  my_resize(sendv[0], 2);
157  my_resize(sendv[1], 2);
158 
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)
163  s0 = s0+s0;
164  timpi_assert_greater(s0.size(), 256);
165 
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)
170  s1 = s1+s1;
171  timpi_assert_greater(s1.size(), 256);
172 
173  std::vector<PairAtLeast> send(1);
174  my_resize(send[0], 2);
175 
176  if (TestCommWorld->rank() == 0)
177  send[0] = sendv[0];
178  else
179  send[0] = sendv[1];
180 
181  std::vector<PairAtLeast> recv;
182 
184  ((void *)(NULL), send.begin(), send.end(),
185  std::back_inserter(recv));
186 
187  const std::size_t comm_size = TestCommWorld->size();
188  const std::size_t vec_size = recv.size();
189  TIMPI_UNIT_ASSERT(comm_size == vec_size);
190 
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]);
194  }
void my_resize(T &container, std::size_t size)
processor_id_type rank() const
Definition: communicator.h:208
Communicator * TestCommWorld
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 ...
processor_id_type size() const
Definition: communicator.h:211

◆ testLargeSetUnion()

void testLargeSetUnion ( )

Definition at line 397 of file packed_range_unit.C.

References TIMPI::Communicator::rank(), TIMPI::Communicator::set_union(), TIMPI::Communicator::size(), and TestCommWorld.

Referenced by main().

398  {
399  // Number of entries in the map on each processor
400  const unsigned int n_map_entries = 147;
401 
402  // Offset between blocks of entries; must exceed n_map_entries
403  const unsigned int map_offset = 1000;
404 
405  // Large enough strings that we'll exceed a single packed buffer
406  const unsigned int string_size = 32768;
407 
408  // Each entry in the map will be the same test_string
409  std::string test_string(/*count*/string_size, 'a');
410 
411  std::map<unsigned int, std::string> map_of_strings;
412 
413  // Use an offset so that the map keys do not overlap
414  const unsigned int my_offset =
415  (TestCommWorld->rank() + 1) * map_offset;
416  for (unsigned int i=0; i != n_map_entries; ++i)
417  map_of_strings[my_offset + i] = test_string;
418 
419  TestCommWorld->set_union(map_of_strings);
420 
421  TIMPI_UNIT_ASSERT(map_of_strings.size() ==
422  TestCommWorld->size() * n_map_entries);
423 
424  TIMPI_UNIT_ASSERT(map_of_strings.begin()->first == map_offset);
425  }
processor_id_type rank() const
Definition: communicator.h:208
Communicator * TestCommWorld
processor_id_type size() const
Definition: communicator.h:211
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...

◆ testListStringAllGather()

void testListStringAllGather ( )

Definition at line 209 of file packed_range_unit.C.

210  {
211  testGettableStringAllGather<std::list<std::string>>();
212  }

◆ testNestingAllGather()

void testNestingAllGather ( )

Definition at line 279 of file packed_range_unit.C.

References TIMPI::Communicator::allgather_packed_range(), TIMPI::Communicator::rank(), TIMPI::Communicator::size(), and TestCommWorld.

Referenced by main().

280  {
281  typedef std::tuple<unsigned int, std::vector<std::tuple<char,int,std::size_t>>, unsigned int> send_type;
282 
283 #ifdef TIMPI_HAVE_CXX17 // static_assert without message
284  static_assert(Has_buffer_type<Packing<std::vector<std::tuple<char,int,std::size_t>>>>::value);
285  static_assert(Has_buffer_type<Packing<send_type>>::value);
286 #endif
287 
288  std::vector<send_type> sendv(2);
289 
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;
293 
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;
297 
298  std::vector<send_type> send(1);
299  if (TestCommWorld->rank() == 0)
300  send[0] = sendv[0];
301  else
302  send[0] = sendv[1];
303 
304  std::vector<send_type> recv;
305 
307  ((void *)(NULL), send.begin(), send.end(),
308  std::back_inserter(recv));
309 
310  const std::size_t comm_size = TestCommWorld->size();
311  const std::size_t vec_size = recv.size();
312  TIMPI_UNIT_ASSERT(comm_size == vec_size);
313 
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]);
317  }
processor_id_type rank() const
Definition: communicator.h:208
Communicator * TestCommWorld
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 ...
Define data types and (un)serialization functions for use when encoding a potentially-variable-size o...
Definition: packing.h:60
processor_id_type size() const
Definition: communicator.h:211

◆ testNullAllGather()

void testNullAllGather ( )

Definition at line 136 of file packed_range_unit.C.

References TIMPI::Communicator::allgather_packed_range(), TIMPI::Communicator::rank(), and TestCommWorld.

Referenced by main().

137  {
138  std::vector<std::string> send(1);
139  if (TestCommWorld->rank() == 0)
140  send[0].assign("Hello");
141  else
142  send[0].assign("Goodbye");
143 
145  ((void *)(NULL), send.begin(), send.end(),
147  }
processor_id_type rank() const
Definition: communicator.h:208
Communicator * TestCommWorld
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 ...

◆ testNullSendReceive()

void testNullSendReceive ( )

Definition at line 321 of file packed_range_unit.C.

References TIMPI::Communicator::rank(), TIMPI::Communicator::send_receive_packed_range(), TIMPI::Communicator::size(), and TestCommWorld.

Referenced by main().

322  {
323  std::vector<std::string> send(1);
324  const unsigned int my_rank = TestCommWorld->rank();
325  const unsigned int dest_rank =
326  (my_rank + 1) % TestCommWorld->size();
327  const unsigned int source_rank =
328  (my_rank + TestCommWorld->size() - 1) % TestCommWorld->size();
329 
330  {
331  std::ostringstream os;
332  os << my_rank;
333  send[0] = os.str();
334  }
335 
337  (dest_rank, (void *)(NULL), send.begin(), send.end(),
338  source_rank, (void *)(NULL),
340  (std::string*)NULL);
341  }
processor_id_type rank() const
Definition: communicator.h:208
Communicator * TestCommWorld
processor_id_type size() const
Definition: communicator.h:211
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...

◆ testPairStringAllGather()

void testPairStringAllGather ( )

Definition at line 197 of file packed_range_unit.C.

Referenced by main().

198  {
199  testGettableStringAllGather<std::pair<std::string, std::string>>();
200  }

◆ testPushPacked()

void testPushPacked ( )

Definition at line 521 of file packed_range_unit.C.

References TIMPI::Communicator::size(), TestCommWorld, and testPushPackedImpl().

Referenced by main().

522  {
524  }
Communicator * TestCommWorld
processor_id_type size() const
Definition: communicator.h:211
void testPushPackedImpl(int M)

◆ testPushPackedDispatch()

void testPushPackedDispatch ( )

Definition at line 611 of file packed_range_unit.C.

References fake_stringy_number(), TIMPI::push_parallel_vector_data(), TestCommWorld, and testPushPackedNestedImpl().

Referenced by main().

612  {
613  // Do the push implicitly with an auto-dispatching function
614  auto implicitly_packed_push = [](auto & data, auto & collect_data) {
615  TIMPI::push_parallel_vector_data(*TestCommWorld, data, collect_data);
616  };
617 
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) {
621  return tuple_type(n, fake_stringy_number(n), n, n, n, n);
622  };
623 
624  testPushPackedNestedImpl(fill_tuple, implicitly_packed_push);
625  }
std::vector< char > fake_stringy_number(int number)
Communicator * TestCommWorld
void push_parallel_vector_data(const Communicator &comm, MapToVectors &&data, const ActionFunctor &act_on_data)
Send and receive and act on vectors of data.
void testPushPackedNestedImpl(FillFunctor fill_functor, PushFunctor push_functor)

◆ testPushPackedFailureCase()

void testPushPackedFailureCase ( )

Definition at line 662 of file packed_range_unit.C.

References TIMPI::push_parallel_vector_data(), stringy_number(), TestCommWorld, and testPushPackedNestedImpl().

Referenced by main().

663  {
664  typedef std::tuple<std::size_t, int, std::unordered_map<unsigned int, std::string>> tuple_type;
665 
666  auto fill_tuple = [] (int n)
667  {
668  tuple_type returnval;
669  std::get<0>(returnval) = n;
670  std::get<1>(returnval) = n;
671  (std::get<2>(returnval))[n] = stringy_number(n);
672  (std::get<2>(returnval))[n+1] = stringy_number(n+1);
673  return returnval;
674  };
675 
676  auto implicitly_packed_push = [](auto & data, auto & collect_data) {
677  TIMPI::push_parallel_vector_data(*TestCommWorld, data, collect_data);
678  };
679 
680  testPushPackedNestedImpl(fill_tuple, implicitly_packed_push);
681  }
Communicator * TestCommWorld
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)
void testPushPackedNestedImpl(FillFunctor fill_functor, PushFunctor push_functor)

◆ testPushPackedImpl()

void testPushPackedImpl ( int  M)

Definition at line 428 of file packed_range_unit.C.

References TIMPI::push_parallel_packed_range(), TIMPI::Communicator::rank(), TIMPI::Communicator::size(), stringy_number(), and TestCommWorld.

Referenced by testPushPacked(), testPushPackedMove(), testPushPackedMoveOversized(), and testPushPackedOversized().

429  {
430  const int size = TestCommWorld->size(),
431  rank = TestCommWorld->rank();
432 
433  std::map<processor_id_type, std::multiset<std::string>>
434  data, received_data;
435 
436  auto stringy_number = [] (int number)
437  {
438  std::string digit_strings [10] = {"zero", "one", "two",
439  "three", "four", "five", "six", "seven", "eight", "nine"};
440 
441  std::string returnval = "done";
442  while (number)
443  {
444  returnval = digit_strings[number%10]+" "+returnval;
445  number = number/10;
446  };
447 
448  return returnval;
449  };
450 
451  for (int d=0; d != M; ++d)
452  {
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)
457  data[d].insert(stringy_number(d));
458  }
459 
460  auto collect_data =
461  [&received_data]
462  (processor_id_type pid,
463  const typename std::multiset<std::string> & multiset_received)
464  {
465  auto & received = received_data[pid];
466  received.insert(multiset_received.begin(), multiset_received.end());
467  };
468 
469  // Ensure that no const_cast perfidy in parallel_sync.h messes up
470  // our original data
471  std::map<processor_id_type, std::multiset<std::string>> preserved_data {data};
472 
473  // Do the push
474  void * context = nullptr;
475  TIMPI::push_parallel_packed_range(*TestCommWorld, data, context, collect_data);
476 
477  // Test the sent data, which shouldn't have changed
478  TIMPI_UNIT_ASSERT(preserved_data.size() == data.size());
479  for (const auto & pair: preserved_data)
480  {
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));
486  }
487 
488  // Test the received results, for each processor id p we're in
489  // charge of.
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)
493  {
494  int diffsize = std::abs(srcp-p);
495  int diffsqrt = std::sqrt(diffsize);
496  if (diffsqrt*diffsqrt != diffsize)
497  {
498  if (received_data.count(srcp))
499  {
500  const std::multiset<std::string> & datum = received_data[srcp];
501  TIMPI_UNIT_ASSERT
502  (std::count(datum.begin(), datum.end(),
503  stringy_number(p)) == std::ptrdiff_t(0));
504  }
505  continue;
506  }
507 
508  TIMPI_UNIT_ASSERT(received_data.count(srcp) == std::size_t(1));
509  const std::multiset<std::string> & datum = received_data[srcp];
510  TIMPI_UNIT_ASSERT
511  (std::count(datum.begin(), datum.end(), stringy_number(p)) ==
512  std::ptrdiff_t(diffsqrt+1));
513  checked_sizes[srcp] += diffsqrt+1;
514  }
515 
516  for (int srcp=0; srcp != size; ++srcp)
517  TIMPI_UNIT_ASSERT(checked_sizes[srcp] == received_data[srcp].size());
518 
519  }
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.
processor_id_type rank() const
Definition: communicator.h:208
Communicator * TestCommWorld
processor_id_type size() const
Definition: communicator.h:211
std::string stringy_number(int number)
uint8_t processor_id_type
Definition: communicator.h:54

◆ testPushPackedImplMove()

void testPushPackedImplMove ( int  M)

Definition at line 685 of file packed_range_unit.C.

References TIMPI::push_parallel_packed_range(), TIMPI::Communicator::rank(), TIMPI::Communicator::size(), and TestCommWorld.

686  {
687  const int size = TestCommWorld->size(),
688  rank = TestCommWorld->rank();
689 
690  std::map<processor_id_type, std::vector<std::unique_ptr<int>>>
691  data, received_data;
692 
693  for (int d=0; d != M; ++d)
694  {
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));
700  }
701 
702  auto collect_data =
703  [&received_data]
704  (processor_id_type pid,
705  std::vector<std::unique_ptr<int>> && vector_received)
706  {
707  auto & received = received_data[pid];
708  for (auto & val : vector_received)
709  received.emplace_back(std::move(val));
710  };
711 
712  void * context = nullptr;
713  TIMPI::push_parallel_packed_range(*TestCommWorld, std::move(data), context, collect_data);
714 
715  // Test the received results, for each processor id p we're in
716  // charge of.
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)
720  {
721  int diffsize = std::abs(srcp-p);
722  int diffsqrt = std::sqrt(diffsize);
723  if (diffsqrt*diffsqrt != diffsize)
724  {
725  if (received_data.count(srcp))
726  {
727  std::size_t count = 0;
728  for (const auto & val : received_data[srcp])
729  if (*val == p)
730  ++count;
731 
732  TIMPI_UNIT_ASSERT(count == (std::size_t)std::ptrdiff_t(0));
733  }
734  continue;
735  }
736 
737  TIMPI_UNIT_ASSERT(received_data.count(srcp) == std::size_t(1));
738 
739  std::size_t count = 0;
740  for (const auto & val : received_data[srcp])
741  if (*val == p)
742  ++count;
743 
744  TIMPI_UNIT_ASSERT(count == (std::size_t)std::ptrdiff_t(diffsqrt+1));
745  checked_sizes[srcp] += diffsqrt+1;
746  }
747 
748  for (int srcp=0; srcp != size; ++srcp)
749  TIMPI_UNIT_ASSERT(checked_sizes[srcp] == received_data[srcp].size());
750  }
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.
processor_id_type rank() const
Definition: communicator.h:208
Communicator * TestCommWorld
processor_id_type size() const
Definition: communicator.h:211
uint8_t processor_id_type
Definition: communicator.h:54

◆ testPushPackedMove()

void testPushPackedMove ( )

Definition at line 752 of file packed_range_unit.C.

References TIMPI::Communicator::size(), TestCommWorld, and testPushPackedImpl().

Referenced by main().

753  {
755  }
Communicator * TestCommWorld
processor_id_type size() const
Definition: communicator.h:211
void testPushPackedImpl(int M)

◆ testPushPackedMoveOversized()

void testPushPackedMoveOversized ( )

Definition at line 757 of file packed_range_unit.C.

References TIMPI::Communicator::size(), TestCommWorld, and testPushPackedImpl().

Referenced by main().

758  {
759  testPushPackedImpl((TestCommWorld->size() + 4) * 2);
760  }
Communicator * TestCommWorld
processor_id_type size() const
Definition: communicator.h:211
void testPushPackedImpl(int M)

◆ testPushPackedNested()

void testPushPackedNested ( )

Definition at line 593 of file packed_range_unit.C.

References fake_stringy_number(), TIMPI::push_parallel_packed_range(), TestCommWorld, and testPushPackedNestedImpl().

Referenced by main().

594  {
595  // Do the push explicitly with a packed_range function
596  auto explicitly_packed_push = [](auto & data, auto & collect_data) {
597  void * context = nullptr;
598  TIMPI::push_parallel_packed_range(*TestCommWorld, data, context, collect_data);
599  };
600 
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) {
604  return tuple_type(n, fake_stringy_number(n), n, n, n, n);
605  };
606 
607  testPushPackedNestedImpl(fill_tuple, explicitly_packed_push);
608  }
std::vector< char > fake_stringy_number(int number)
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.
Communicator * TestCommWorld
void testPushPackedNestedImpl(FillFunctor fill_functor, PushFunctor push_functor)

◆ testPushPackedNestedImpl()

template<typename FillFunctor , typename PushFunctor >
void testPushPackedNestedImpl ( FillFunctor  fill_functor,
PushFunctor  push_functor 
)

Definition at line 532 of file packed_range_unit.C.

References TIMPI::Communicator::rank(), TIMPI::Communicator::size(), and TestCommWorld.

Referenced by testPushPackedDispatch(), testPushPackedFailureCase(), testPushPackedNested(), and testPushPackedOneTuple().

533  {
534  const int size = TestCommWorld->size(),
535  rank = TestCommWorld->rank();
536 
537  typedef decltype(fill_functor(0)) fill_type;
538 
539  typedef std::vector<fill_type> vec_type;
540  std::map<processor_id_type, vec_type> data, received_data;
541 
542  for (int d=0; d != size; ++d)
543  {
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));
549  }
550 
551  auto collect_data =
552  [&received_data]
553  (processor_id_type pid,
554  const vec_type & vec_received)
555  {
556  auto & received = received_data[pid];
557  received = vec_received;
558  };
559 
560  // Ensure that no const_cast perfidy in parallel_sync.h messes up
561  // our original data
562  std::map<processor_id_type, vec_type> preserved_data {data};
563 
564  // Do the push
565  push_functor(data, collect_data);
566 
567  // Test the sent data, which shouldn't have changed
568  TIMPI_UNIT_ASSERT(preserved_data == data);
569 
570  // Test the received results, for each processor id p we're in
571  // charge of.
572  std::vector<std::size_t> checked_sizes(size, 0);
573  for (int srcp=0; srcp != size; ++srcp)
574  {
575  int diffsize = std::abs(srcp-rank);
576  int diffsqrt = std::sqrt(diffsize);
577  if (diffsqrt*diffsqrt != diffsize)
578  {
579  TIMPI_UNIT_ASSERT(!received_data.count(srcp));
580  continue;
581  }
582 
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));
586 
587  for (auto & tup : rec)
588  TIMPI_UNIT_ASSERT(tup == fill_functor(rank));
589  }
590  }
processor_id_type rank() const
Definition: communicator.h:208
Communicator * TestCommWorld
processor_id_type size() const
Definition: communicator.h:211
uint8_t processor_id_type
Definition: communicator.h:54

◆ testPushPackedOneTuple()

void testPushPackedOneTuple ( )

Definition at line 628 of file packed_range_unit.C.

References TIMPI::push_parallel_vector_data(), stringy_number(), TestCommWorld, and testPushPackedNestedImpl().

Referenced by main().

629  {
630  typedef std::tuple<std::unordered_map<unsigned int, std::string>> tuple_type;
631 #ifdef TIMPI_HAVE_CXX17 // static_assert without message
632  static_assert(Has_buffer_type<Packing<std::string>>::value);
633  static_assert(TIMPI::StandardType<std::pair<unsigned int, unsigned int>>::is_fixed_type);
634  static_assert(TIMPI::StandardType<std::pair<const unsigned int, unsigned int>>::is_fixed_type);
635  static_assert(Has_buffer_type<Packing<std::unordered_map<unsigned int, unsigned int>>>::value);
636  static_assert(Has_buffer_type<Packing<std::pair<std::string, std::string>>>::value);
637  static_assert(Has_buffer_type<Packing<std::pair<const std::string, std::string>>>::value);
638  static_assert(Has_buffer_type<Packing<std::unordered_map<std::string, std::string>>>::value);
639  static_assert(Has_buffer_type<Packing<std::pair<unsigned int, std::string>>>::value);
640  static_assert(Has_buffer_type<Packing<std::pair<const unsigned int, std::string>>>::value);
641  static_assert(Has_buffer_type<Packing<std::unordered_map<unsigned int, std::string>>>::value);
642  static_assert(Has_buffer_type<Packing<tuple_type>>::value);
643 #endif
644 
645  auto fill_tuple = [] (int n)
646  {
647  tuple_type returnval;
648  (std::get<0>(returnval))[n] = stringy_number(n);
649  (std::get<0>(returnval))[n+1] = stringy_number(n+1);
650  return returnval;
651  };
652 
653  auto implicitly_packed_push = [](auto & data, auto & collect_data) {
654  TIMPI::push_parallel_vector_data(*TestCommWorld, data, collect_data);
655  };
656 
657  testPushPackedNestedImpl(fill_tuple, implicitly_packed_push);
658  }
Communicator * TestCommWorld
Templated class to provide the appropriate MPI datatype for use with built-in C types or simple C++ c...
Definition: standard_type.h:83
Define data types and (un)serialization functions for use when encoding a potentially-variable-size o...
Definition: packing.h:60
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)
void testPushPackedNestedImpl(FillFunctor fill_functor, PushFunctor push_functor)

◆ testPushPackedOversized()

void testPushPackedOversized ( )

Definition at line 526 of file packed_range_unit.C.

References TIMPI::Communicator::size(), TestCommWorld, and testPushPackedImpl().

Referenced by main().

527  {
528  testPushPackedImpl((TestCommWorld->size() + 4) * 2);
529  }
Communicator * TestCommWorld
processor_id_type size() const
Definition: communicator.h:211
void testPushPackedImpl(int M)

◆ testTupleStringAllGather()

void testTupleStringAllGather ( )

Definition at line 224 of file packed_range_unit.C.

References TIMPI::Communicator::allgather_packed_range(), TIMPI::Communicator::rank(), TIMPI::Communicator::size(), and TestCommWorld.

Referenced by main().

225  {
226 #ifdef TIMPI_HAVE_CXX17 // static_assert without message
227  static_assert(Has_buffer_type<Packing<std::string>>::value);
229  static_assert(Has_buffer_type<Packing<std::tuple<std::string>>>::value);
231  static_assert(Has_buffer_type<Packing<std::tuple<std::string, std::string>>>::value);
233  static_assert(Has_buffer_type<Packing<std::tuple<std::string, std::string, int>>>::value);
234 #endif
235 
236  std::vector<std::tuple<std::string, std::string, int>> sendv(2);
237 
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)
242  s0 = s0+s0;
243  timpi_assert_greater(s0.size(), 256);
244  std::get<2>(sendv[0]) = 257;
245 
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)
250  s1 = s1+s1;
251  timpi_assert_greater(s1.size(), 256);
252  std::get<2>(sendv[1]) = 258;
253 
254  std::vector<std::tuple<std::string, std::string, int>> send(1);
255  if (TestCommWorld->rank() == 0)
256  send[0] = sendv[0];
257  else
258  send[0] = sendv[1];
259 
260  std::vector<std::tuple<std::string, std::string, int>> recv;
261 
263  ((void *)(NULL), send.begin(), send.end(),
264  std::back_inserter(recv));
265 
266  const std::size_t comm_size = TestCommWorld->size();
267  const std::size_t vec_size = recv.size();
268  TIMPI_UNIT_ASSERT(comm_size == vec_size);
269 
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]);
273  }
processor_id_type rank() const
Definition: communicator.h:208
Communicator * TestCommWorld
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 ...
Define data types and (un)serialization functions for use when encoding a potentially-variable-size o...
Definition: packing.h:60
processor_id_type size() const
Definition: communicator.h:211

◆ testVectorStringAllGather()

void testVectorStringAllGather ( )

Definition at line 215 of file packed_range_unit.C.

216  {
217  testGettableStringAllGather<std::vector<std::string>>();
218  }

Variable Documentation

◆ TestCommWorld

Communicator* TestCommWorld