TIMPI
parallel_unit.C
Go to the documentation of this file.
1 #include <timpi/timpi.h>
2 
3 #define TIMPI_UNIT_ASSERT(expr) \
4  do { \
5  if (!(expr)) \
6  timpi_error(); \
7  } while (0)
8 
9 using namespace TIMPI;
10 
12 
13 std::vector<std::string> pt_number;
14 
15  void setUp()
16  {
17  pt_number.resize(10);
18  pt_number[0] = "Zero";
19  pt_number[1] = "One";
20  pt_number[2] = "Two";
21  pt_number[3] = "Three";
22  pt_number[4] = "Four";
23  pt_number[5] = "Five";
24  pt_number[6] = "Six";
25  pt_number[7] = "Seven";
26  pt_number[8] = "Eight";
27  pt_number[9] = "Nine";
28  }
29 
30  template <class Map>
31  void testSum()
32  {
33  Map data;
34 
35  int N = TestCommWorld->size();
36 
37  for (int p=0; p<N; ++p)
38  data[p] = TestCommWorld->rank();
39 
40  TestCommWorld->sum(data);
41 
42  // Each map entry should now contain the sum:
43  // 0 + 1 + ... + N-1 = N*(N-1)/2
44  for (int p=0; p<N; ++p)
45  TIMPI_UNIT_ASSERT( data[p] == N*(N-1)/2 );
46  }
47 
48 
49 
50  template <class Gettable>
52  {
53  Gettable data;
54 
55  int N = TestCommWorld->size();
56 
57  std::get<0>(data) = TestCommWorld->rank();
58  std::get<1>(data) = TestCommWorld->rank()*2;
59 
60  TestCommWorld->sum(data);
61 
62  TIMPI_UNIT_ASSERT(std::get<0>(data) == N*(N-1)/2);
63  TIMPI_UNIT_ASSERT(std::get<1>(data) == N*(N-1));
64  }
65 
66 
67 
68  template <class Map>
70  {
71  Map data;
72 
73  int N = TestCommWorld->size();
74 
75  for (int p=0; p<N; ++p)
76  data[std::string("key") + std::to_string(p)] = TestCommWorld->rank();
77 
78  TestCommWorld->sum(data);
79 
80  // Each map entry should now contain the sum:
81  // 0 + 1 + ... + N-1 = N*(N-1)/2
82  for (int p=0; p<N; ++p)
83  TIMPI_UNIT_ASSERT( data[std::string("key") + std::to_string(p)] == N*(N-1)/2 );
84  }
85 
86 
87 
88 void testGather()
89  {
90  std::vector<processor_id_type> vals;
91  TestCommWorld->gather(0,cast_int<processor_id_type>(TestCommWorld->rank()),vals);
92 
93  if (TestCommWorld->rank() == 0)
94  for (processor_id_type i=0; i<vals.size(); i++)
95  TIMPI_UNIT_ASSERT( i == vals[i] );
96  }
97 
98 
99 
101  {
102  std::vector<std::string> vals;
103  TestCommWorld->gather(0, "Processor" + pt_number[TestCommWorld->rank() % 10], vals);
104 
105  if (TestCommWorld->rank() == 0)
106  for (processor_id_type i=0; i<vals.size(); i++)
107  TIMPI_UNIT_ASSERT( "Processor" + pt_number[i % 10] == vals[i] );
108  }
109 
110 
111 
113  {
114  std::vector<processor_id_type> vals;
115  TestCommWorld->allgather(cast_int<processor_id_type>(TestCommWorld->rank()),vals);
116 
117  for (processor_id_type i=0; i<vals.size(); i++)
118  TIMPI_UNIT_ASSERT( i == vals[i] );
119  }
120 
121 
123  {
124  std::vector<std::string> vals;
125  TestCommWorld->gather(0, "Processor" + pt_number[TestCommWorld->rank() % 10], vals);
126 
127  for (processor_id_type i=0; i<vals.size(); i++)
128  TIMPI_UNIT_ASSERT( "Processor" + pt_number[i % 10] == vals[i] );
129  }
130 
132  {
133  std::string send = "Processor" + std::to_string(TestCommWorld->rank());
134  std::vector<std::string> gathered;
135 
136  TestCommWorld->allgather(send, gathered);
137 
138  TIMPI_UNIT_ASSERT(gathered.size() == TestCommWorld->size());
139  for (std::size_t i = 0; i < gathered.size(); ++i)
140  TIMPI_UNIT_ASSERT(gathered[i] == "Processor" + std::to_string(i));
141  }
142 
144  {
145  std::vector<std::string> vals;
146  vals.push_back("Processor" + pt_number[TestCommWorld->rank() % 10] + "A");
147  vals.push_back("Processor" + pt_number[TestCommWorld->rank() % 10] + "B");
148  TestCommWorld->allgather(vals);
149 
150  for (processor_id_type i=0; i<(vals.size()/2); i++)
151  {
152  TIMPI_UNIT_ASSERT( "Processor" + pt_number[i % 10] + "A" == vals[2*i] );
153  TIMPI_UNIT_ASSERT( "Processor" + pt_number[i % 10] + "B" == vals[2*i+1] );
154  }
155  }
156 
158  {
159  std::vector<int> vals;
160  for (processor_id_type i = 0, iend = TestCommWorld->rank()%10; i != iend; ++i)
161  vals.push_back(3*i);
162  std::vector<std::vector<int>> allvals;
163  TestCommWorld->allgather(vals,allvals);
164 
165  for (processor_id_type i = 0, iend = TestCommWorld->rank(); i != iend; ++i)
166  {
167  TIMPI_UNIT_ASSERT(allvals[i].size() == i%10);
168  for (processor_id_type j = 0, jend = i%10; j != jend; ++j)
169  TIMPI_UNIT_ASSERT(allvals[i][j] == int(3*j));
170  }
171  }
172 
174  {
175  std::vector<std::vector<double>> allvals;
176  if (TestCommWorld->rank() == 1)
177  {
178  // Leave test empty for rank 1
179  }
180  else
181  {
182  allvals.push_back(
183  {static_cast<double>(TestCommWorld->rank()),
184  static_cast<double>(TestCommWorld->rank() * 2)});
185  }
186 
187  TestCommWorld->allgather(allvals, false);
188 
189  if (TestCommWorld->size() > 1)
190  TIMPI_UNIT_ASSERT(allvals.size() == TestCommWorld->size()-1);
191  else
192  TIMPI_UNIT_ASSERT(allvals.size() == 1);
193 
194  for (processor_id_type i = 0, iend = TestCommWorld->size()-1; i != iend; ++i)
195  {
196  int r = i > 0 ? (i+1) : i;
197  TIMPI_UNIT_ASSERT(allvals[i].size() == 2);
198  TIMPI_UNIT_ASSERT(allvals[i][0] == r);
199  TIMPI_UNIT_ASSERT(allvals[i][1] == r*2);
200  }
201  }
202 
204  {
205  std::vector<std::string> vals;
206  for (processor_id_type i = 0, iend = TestCommWorld->rank()%10; i != iend; ++i)
207  vals.push_back(pt_number[i]);
208  std::vector<std::vector<std::string>> allvals;
209  TestCommWorld->allgather(vals,allvals);
210 
211  for (processor_id_type i = 0, iend = TestCommWorld->rank(); i != iend; ++i)
212  {
213  TIMPI_UNIT_ASSERT(allvals[i].size() == i%10);
214  for (processor_id_type j = 0, jend = i%10; j != jend; ++j)
215  TIMPI_UNIT_ASSERT(allvals[i][j] == pt_number[j]);
216  }
217  }
218 
220  {
221  std::vector<std::string> vals;
222  TestCommWorld->allgather(vals);
223 
224  TIMPI_UNIT_ASSERT( vals.empty() );
225  }
226 
227 
228 
230  {
231  std::vector<std::string> vals;
232 
233  if (!TestCommWorld->rank())
234  vals.push_back("Proc 0 only");
235 
236  TestCommWorld->allgather(vals);
237 
238  TIMPI_UNIT_ASSERT( vals[0] == std::string("Proc 0 only") );
239  }
240 
241 
242 
243  template <class Container>
244  void testBroadcast(Container && src)
245  {
246  Container dest = src;
247 
248  // Clear dest on non-root ranks
249  if (TestCommWorld->rank() != 0)
250  dest.clear();
251 
252  TestCommWorld->broadcast(dest);
253 
254  for (std::size_t i=0; i<src.size(); i++)
255  TIMPI_UNIT_ASSERT( src[i] == dest[i] );
256  }
257 
259  {
260  std::string src = "hello";
261  std::string dest = src;
262 
263  // Clear dest on non-root ranks
264  if (TestCommWorld->rank() != 0)
265  dest.clear();
266 
267  // By default the root_id is 0
268  TestCommWorld->broadcast(dest);
269 
270  for (std::size_t i=0; i<src.size(); i++)
271  TIMPI_UNIT_ASSERT( src[i] == dest[i] );
272  }
273 
275  {
276  using std::array;
277  typedef array<array<int, 3>, 2> aa;
278 
279  // Workaround for spurious warning from operator=
280  // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100366
281  aa x{{ {0,1,2},{3,4,5} }};
282  std::vector<aa> src(3), dest(3,x);
283 
284  src[0][0][0] = 0;
285  src[0][0][1] = -1;
286  src[0][0][2] = -2;
287  src[0][1][0] = -3;
288  src[0][1][1] = -4;
289  src[0][1][2] = -5;
290  src[1][0][0] = 10;
291  src[1][0][1] = 9;
292  src[1][0][2] = 8;
293  src[1][1][0] = 7;
294  src[1][1][1] = 6;
295  src[1][1][2] = 5;
296  src[2][0][0] = 20;
297  src[2][0][1] = 19;
298  src[2][0][2] = 18;
299  src[2][1][0] = 17;
300  src[2][1][1] = 16;
301  src[2][1][2] = 15;
302 
303  if (TestCommWorld->rank() == 0)
304  dest = src;
305 
306  TestCommWorld->broadcast(dest);
307 
308  for (std::size_t i=0; i<src.size(); i++)
309  for (std::size_t j=0; j<2; j++)
310  for (std::size_t k=0; k<3; k++)
311  TIMPI_UNIT_ASSERT(src[i][j][k] == dest[i][j][k]);
312  }
313 
315  {
316  using std::pair;
317  typedef pair<pair<pair<pair<int, int>, int>, int>, int> pppp;
318  std::vector<pppp> src(3), dest(3);
319 
320  src[0].first.first.first.first=0;
321  src[0].first.first.first.second=-1;
322  src[0].first.second = -2;
323  src[0].second = -3;
324  src[1].first.first.first.first=10;
325  src[1].first.first.first.second=9;
326  src[1].first.second = 8;
327  src[1].second = 7;
328  src[2].first.first.first.first=20;
329  src[2].first.first.first.second=19;
330  src[2].first.second = 18;
331  src[2].second = 17;
332 
333  if (TestCommWorld->rank() == 0)
334  dest = src;
335 
336  TestCommWorld->broadcast(dest);
337 
338  for (std::size_t i=0; i<src.size(); i++)
339  {
340  TIMPI_UNIT_ASSERT(src[i].first.first.first.first ==
341  dest[i].first.first.first.first);
342  TIMPI_UNIT_ASSERT(src[i].first.first.first.second ==
343  dest[i].first.first.first.second);
344  TIMPI_UNIT_ASSERT(src[i].first.first.second ==
345  dest[i].first.first.second);
346  TIMPI_UNIT_ASSERT(src[i].first.second ==
347  dest[i].first.second);
348  TIMPI_UNIT_ASSERT(src[i].second ==
349  dest[i].second);
350  }
351  }
352 
353 
354 
355  void testScatter()
356  {
357  // Test Scalar scatter
358  {
359  std::vector<processor_id_type> src;
360  processor_id_type dest = 0;
361 
362  if (TestCommWorld->rank() == 0)
363  {
364  src.resize(TestCommWorld->size());
365  for (processor_id_type i=0; i<src.size(); i++)
366  src[i] = i + 1;
367  }
368 
369  TestCommWorld->scatter(src, dest);
370 
371  TIMPI_UNIT_ASSERT( TestCommWorld->rank() + 1 == dest );
372  }
373 
374  // Test Vector Scatter (equal-sized chunks)
375  {
376  std::vector<unsigned int> src;
377  std::vector<unsigned int> dest;
378  static const unsigned int CHUNK_SIZE = 3;
379 
380  if (TestCommWorld->rank() == 0)
381  {
382  src.resize(TestCommWorld->size() * CHUNK_SIZE);
383  for (std::size_t i=0; i<src.size(); i++)
384  src[i] = i;
385  }
386 
387  TestCommWorld->scatter(src, dest);
388 
389  for (unsigned int i=0; i<CHUNK_SIZE; i++)
390  TIMPI_UNIT_ASSERT( TestCommWorld->rank() * CHUNK_SIZE + i == dest[i] );
391  }
392 
393  // Test Vector Scatter (jagged chunks)
394  {
395  std::vector<unsigned int> src;
396  std::vector<unsigned int> dest;
397  std::vector<int> counts;
398 
399  if (TestCommWorld->rank() == 0)
400  {
401  // Give each processor "rank" number of items ( Sum i=1..n == (n * (n + 1))/2 )
402  src.resize((TestCommWorld->size() * (TestCommWorld->size() + 1)) / 2);
403  counts.resize(TestCommWorld->size());
404 
405  for (std::size_t i=0; i<src.size(); i++)
406  src[i] = i;
407  for (unsigned int i=0; i<TestCommWorld->size(); i++)
408  counts[i] = static_cast<int>(i+1);
409  }
410 
411  TestCommWorld->scatter(src, counts, dest);
412 
413  unsigned int start_value = (TestCommWorld->rank() * (TestCommWorld->rank() + 1)) / 2;
414  for (unsigned int i=0; i<=TestCommWorld->rank(); i++)
415  TIMPI_UNIT_ASSERT( start_value + i == dest[i] );
416  }
417 
418  // Test Vector of Vector Scatter
419  {
420  std::vector<std::vector<unsigned int>> src;
421  std::vector<unsigned int> dest;
422 
423  if (TestCommWorld->rank() == 0)
424  {
425  // Give each processor "rank" number of items ( Sum i=1..n == (n * (n + 1))/2 )
426  src.resize(TestCommWorld->size());
427  for (std::size_t i=0; i<src.size(); ++i)
428  src[i].resize(i+1);
429 
430  unsigned int global_counter = 0;
431  for (std::size_t i=0; i<src.size(); i++)
432  for (std::size_t j=0; j<src[i].size(); j++)
433  src[i][j] = global_counter++;
434  }
435 
436  TestCommWorld->scatter(src, dest);
437 
438  unsigned int start_value = (TestCommWorld->rank() * (TestCommWorld->rank() + 1)) / 2;
439  for (unsigned int i=0; i<=TestCommWorld->rank(); i++)
440  TIMPI_UNIT_ASSERT( start_value + i == dest[i] );
441  }
442  }
443 
444 
445 
446  void testBarrier()
447  {
449  }
450 
451 
453  {
454  const unsigned int local_val = TestCommWorld->rank() + 3;
455  unsigned int min = std::numeric_limits<unsigned int>::max();
456 
457  Request req;
458  TestCommWorld->min(local_val, min, req);
459 
460  // not sure what I can safely test here; test() could return true
461  // immediately or could loop an arbitrarily long time first...
462  while(!req.test()) {}
463 
464  TIMPI_UNIT_ASSERT (min == static_cast<unsigned int>(3));
465 
466  // We could get away with destruct-before-wait since there's no
467  // post-wait-work attached to req, but that's not really
468  // *supported* behavior...
469  req.wait();
470  }
471 
472 
474  {
475  // We don't support non-blocking I/O in serial
476  if (TestCommWorld->size() < 2)
477  return;
478 
479  const std::string send_string =
480  "More than 64 bytes to avoid false positives with Small String Optimization libraries";
481 
482  // We need pre-sized buffers for non-blocking receive.
483  std::string recv_string(send_string.size(), ' ');
484 
485  const processor_id_type dest_pid =
486  (TestCommWorld->rank() + 1) % TestCommWorld->size();
487 
488  Request send_req, recv_req;
489  TestCommWorld->send(dest_pid, send_string, send_req);
490  TestCommWorld->receive(any_source, recv_string, recv_req);
491 
492  recv_req.wait();
493 
494  TIMPI_UNIT_ASSERT (send_string == recv_string);
495 
496  send_req.wait();
497  }
498 
499 
501  {
502  constexpr std::size_t N=5;
503  std::vector<unsigned int> local_vals(N),
504  min_vals(N, std::numeric_limits<unsigned int>::max());
505  std::iota(local_vals.begin(), local_vals.end(), TestCommWorld->rank()+4);
506 
507  std::size_t tests_done = 0;
508 
509  std::vector<Request> reqs;
510  for (std::size_t i=0; i != N; ++i)
511  {
512  Request req;
513  TestCommWorld->min(local_vals[i], min_vals[i], req);
514 
515  // We might have finished immediately, e.g. if we're on one
516  // processor
517  if (*req.get() == Request::null_request)
518  {
519  TIMPI_UNIT_ASSERT (min_vals[i] == static_cast<unsigned int>(4+i));
520  ++tests_done;
521  }
522  reqs.push_back(req);
523  }
524 
525  std::size_t i = std::size_t(-1);
526  if (tests_done != N)
527  i = waitany(reqs);
528  while (i != std::size_t(-1))
529  {
530  TIMPI_UNIT_ASSERT (min_vals[i] == static_cast<unsigned int>(4+i));
531  ++tests_done;
532  i = waitany(reqs);
533  }
534 
535  TIMPI_UNIT_ASSERT (tests_done == N);
536  }
537 
538 
539 
541  {
542  int true_sum = 0;
543  for (int rank = 0; rank < (int)TestCommWorld->size(); ++rank)
544  true_sum += rank + 1;
545 
546  int local_val = TestCommWorld->rank() + 1;
547  int sum;
548 
550  TestCommWorld->sum(local_val, sum, request);
551  request.wait();
552 
553  TIMPI_UNIT_ASSERT (true_sum == sum);
554  }
555 
556 
557 
559  {
560  unsigned int local_val = TestCommWorld->rank();
561  unsigned int min = std::numeric_limits<unsigned int>::max();
562 
563  Request req;
564  TestCommWorld->min(local_val, min, req);
565  req.wait();
566 
567  TIMPI_UNIT_ASSERT (min == static_cast<unsigned int>(0));
568  }
569 
570 
571 
572  void testMin ()
573  {
574  unsigned int min = TestCommWorld->rank();
575 
576  TestCommWorld->min(min);
577 
578  TIMPI_UNIT_ASSERT (min == static_cast<unsigned int>(0));
579  }
580 
581 
583  {
584  const processor_id_type rank = TestCommWorld->rank();
585  const processor_id_type N = TestCommWorld->size();
586 
587  // Use a long vector, so we can be sure that many bits extends
588  // over multiple unsigned integers; use a weird size to test the
589  // not-evenly-divisible case.
590  constexpr std::size_t vec_size = 2345;
591  std::vector<bool> vec_bool(vec_size, true);
592  for (std::size_t i=0; i < vec_size; i += (rank+2))
593  vec_bool[i] = false;
594 
595  TestCommWorld->min(vec_bool);
596 
597  for (std::size_t i=0; i != vec_size; ++i)
598  {
599  bool should_be_true = true;
600  for (processor_id_type p=0; p < N; ++p)
601  if (i % (p+2) == 0)
602  {
603  should_be_true = false;
604  break;
605  }
606  TIMPI_UNIT_ASSERT (vec_bool[i] == should_be_true);
607  }
608  }
609 
610 
611 
612 
614  {
615  unsigned long min = 1;
616  if (TestCommWorld->rank() % 2)
617  min = std::numeric_limits<unsigned long>::max();
618 
619  timpi_call_mpi
620  (MPI_Allreduce (MPI_IN_PLACE, &min, 1,
621  MPI_UNSIGNED_LONG, MPI_MIN,
622  TestCommWorld->get()));
623 
624  TIMPI_UNIT_ASSERT (min == 1);
625  }
626 
627  template <typename T>
628  void testMinLarge ()
629  {
630  T min = 1;
631 
632  if (TestCommWorld->rank() % 2)
633  min = std::numeric_limits<T>::max();
634 
635  TestCommWorld->min(min);
636 
637  TIMPI_UNIT_ASSERT (min == 1);
638  }
639 
640 
641 
643  {
644  processor_id_type local_val = TestCommWorld->rank();
645  processor_id_type max = std::numeric_limits<processor_id_type>::min();
646 
647  Request req;
648  TestCommWorld->max(local_val, max, req);
649  req.wait();
650 
651  TIMPI_UNIT_ASSERT (cast_int<processor_id_type>(max+1) ==
652  cast_int<processor_id_type>(TestCommWorld->size()));
653  }
654 
655 
656 
657  void testMax ()
658  {
660 
661  TestCommWorld->max(max);
662 
663  TIMPI_UNIT_ASSERT (cast_int<processor_id_type>(max+1) ==
664  cast_int<processor_id_type>(TestCommWorld->size()));
665  }
666 
667 
668 
670  {
671  const processor_id_type rank = TestCommWorld->rank();
672  const processor_id_type N = TestCommWorld->size();
673 
674  // Use a long vector, so we can be sure it extends over multiple
675  // unsigned integers; use a weird size to test the
676  // not-evenly-divisible case.
677  constexpr std::size_t vec_size = 2345;
678  std::vector<bool> vec_bool(vec_size, false);
679  for (std::size_t i=0; i < vec_size; i += (rank+2))
680  vec_bool[i] = true;
681 
682  TestCommWorld->max(vec_bool);
683 
684  for (std::size_t i=0; i != vec_size; ++i)
685  {
686  bool should_be_true = false;
687  for (processor_id_type p=0; p < N; ++p)
688  if (i % (p+2) == 0)
689  {
690  should_be_true = true;
691  break;
692  }
693  TIMPI_UNIT_ASSERT (vec_bool[i] == should_be_true);
694  }
695  }
696 
697 
698 
699  template <class Map>
700  void testMapMax ()
701  {
702  Map data;
703 
704  int rank = TestCommWorld->rank();
705  int N = TestCommWorld->size();
706 
707  // On each proc, the map has the single entry (rank, rank)
708  data[rank] = rank;
709 
710  // Compute the max
711  TestCommWorld->max(data);
712 
713  // After calling max, there should be an entry for each rank
714  for (int p=0; p<N; ++p)
715  TIMPI_UNIT_ASSERT (data[p] == p);
716  }
717 
718 
719 
720  template <class Map>
722  {
723  Map data;
724 
725  int rank = TestCommWorld->rank();
726  int N = TestCommWorld->size();
727 
728  // On each proc, the map has a single entry, e.g. ("key0", 0)
729  data[std::string("key") + std::to_string(rank)] = rank;
730 
731  // Compute the max
732  TestCommWorld->max(data);
733 
734  // After calling max, there should be an entry for each rank
735  for (int p=0; p<N; ++p)
736  TIMPI_UNIT_ASSERT (data[std::string("key") + std::to_string(p)] == p);
737  }
738 
739 
740 
741  void testMinloc ()
742  {
743  int min = (TestCommWorld->rank() + 1) % TestCommWorld->size();
744  unsigned int minid = 0;
745 
746  TestCommWorld->minloc(min, minid);
747 
748  TIMPI_UNIT_ASSERT (min == static_cast<int>(0));
749  TIMPI_UNIT_ASSERT (minid == static_cast<unsigned int>(TestCommWorld->size()-1));
750  }
751 
752 
753 
754  void testMaxloc ()
755  {
756  int max = TestCommWorld->rank();
757  unsigned int maxid = 0;
758 
759  TestCommWorld->maxloc(max, maxid);
760 
761  TIMPI_UNIT_ASSERT (max+1 ==
762  cast_int<int>(TestCommWorld->size()));
763  TIMPI_UNIT_ASSERT (maxid == static_cast<unsigned int>(TestCommWorld->size()-1));
764  }
765 
766 
767 
769  {
770  bool min = ((TestCommWorld->rank() + TestCommWorld->size()-1) % 2);
771  unsigned int minid = 0;
772 
773  TestCommWorld->minloc(min, minid);
774 
775  TIMPI_UNIT_ASSERT (min == static_cast<int>(0));
776  TIMPI_UNIT_ASSERT (minid == static_cast<unsigned int>((TestCommWorld->size()-1)%2));
777  }
778 
779 
780 
782  {
783  double min = (TestCommWorld->rank() + 1) % TestCommWorld->size();
784  unsigned int minid = 0;
785 
786  TestCommWorld->minloc(min, minid);
787 
788  TIMPI_UNIT_ASSERT (min == double(0));
789  TIMPI_UNIT_ASSERT (minid == static_cast<unsigned int>(TestCommWorld->size()-1));
790  }
791 
792 
793 
795  {
796  bool max = ((TestCommWorld->rank() + TestCommWorld->size()) % 2);
797  unsigned int maxid = 0;
798 
799  TestCommWorld->maxloc(max, maxid);
800 
801  TIMPI_UNIT_ASSERT (max == static_cast<int>(1));
802  TIMPI_UNIT_ASSERT (maxid == static_cast<unsigned int>((TestCommWorld->size()-1)%2));
803  }
804 
805 
806 
808  {
809  double max = TestCommWorld->rank();
810  unsigned int maxid = 0;
811 
812  TestCommWorld->maxloc(max, maxid);
813 
814  // Hope nobody uses 1677216 procs with single precision
815  TIMPI_UNIT_ASSERT (max+1 == double(TestCommWorld->size()));
816  TIMPI_UNIT_ASSERT (maxid == static_cast<unsigned int>(TestCommWorld->size()-1));
817  }
818 
819 
820 
822  {
823  int min = (TestCommWorld->rank() + 1) % TestCommWorld->size();
824  int min_tag = min + 3;
825  unsigned int minid = 0;
826 
827  std::pair<int, int> p{min, min_tag};
828 
829  TestCommWorld->minloc(p, minid);
830 
831  TIMPI_UNIT_ASSERT (p.first == static_cast<int>(0));
832  TIMPI_UNIT_ASSERT (p.second == static_cast<int>(3));
833  TIMPI_UNIT_ASSERT (minid == static_cast<unsigned int>(TestCommWorld->size()-1));
834  }
835 
836 
837 
839  {
840  int max = TestCommWorld->rank();
841  int max_tag = max + 3;
842  unsigned int maxid = 0;
843 
844  std::pair<int, int> p{max, max_tag};
845 
846  TestCommWorld->maxloc(p, maxid);
847 
848  TIMPI_UNIT_ASSERT (p.first+1 ==
849  cast_int<int>(TestCommWorld->size()));
850  TIMPI_UNIT_ASSERT (p.second+1 ==
851  cast_int<int>(TestCommWorld->size())+3);
852  TIMPI_UNIT_ASSERT (maxid == static_cast<unsigned int>(TestCommWorld->size()-1));
853  }
854 
855 
856 
858  {
859  double min = std::numeric_limits<double>::infinity();
860 
861  TestCommWorld->min(min);
862 
863  TIMPI_UNIT_ASSERT (min == std::numeric_limits<double>::infinity());
864 
865  min = -std::numeric_limits<double>::infinity();
866 
867  TestCommWorld->min(min);
868 
869  TIMPI_UNIT_ASSERT (min == -std::numeric_limits<double>::infinity());
870  }
871 
872 
873 
875  {
876  double max = std::numeric_limits<double>::infinity();
877 
878  TestCommWorld->max(max);
879 
880  TIMPI_UNIT_ASSERT (max == std::numeric_limits<double>::infinity());
881 
882  max = -std::numeric_limits<double>::infinity();
883 
884  TestCommWorld->max(max);
885 
886  TIMPI_UNIT_ASSERT (max == -std::numeric_limits<double>::infinity());
887  }
888 
889 
890 
892  {
893  unsigned int procup = (TestCommWorld->rank() + 1) %
894  TestCommWorld->size();
895  unsigned int procdown = (TestCommWorld->size() +
896  TestCommWorld->rank() - 1) %
897  TestCommWorld->size();
898 
899  std::vector<unsigned int> src_val(3), recv_val(3);
900 
901  src_val[0] = 0;
902  src_val[1] = 1;
903  src_val[2] = 2;
904 
906 
907  if (TestCommWorld->size() > 1)
908  {
909  // Default communication
911 
912  TestCommWorld->send (procup,
913  src_val,
914  request);
915 
916  TestCommWorld->receive (procdown,
917  recv_val);
918 
920 
921  TIMPI_UNIT_ASSERT ( src_val.size() == recv_val.size() );
922 
923  for (std::size_t i=0; i<src_val.size(); i++)
924  TIMPI_UNIT_ASSERT( src_val[i] == recv_val[i] );
925 
926 
927  // Synchronous communication
929  std::fill (recv_val.begin(), recv_val.end(), 0);
930 
931  TestCommWorld->send (procup,
932  src_val,
933  request);
934 
935  TestCommWorld->receive (procdown,
936  recv_val);
937 
939 
940  TIMPI_UNIT_ASSERT ( src_val.size() == recv_val.size() );
941 
942  for (std::size_t i=0; i<src_val.size(); i++)
943  TIMPI_UNIT_ASSERT( src_val[i] == recv_val[i] );
944 
945  // Restore default communication
947  }
948  }
949 
950 
951 
953  {
954  unsigned int procup = (TestCommWorld->rank() + 1) %
955  TestCommWorld->size();
956  unsigned int procdown = (TestCommWorld->size() +
957  TestCommWorld->rank() - 1) %
958  TestCommWorld->size();
959 
960  std::vector<unsigned int> src_val(3), recv_val(3);
961 
962  src_val[0] = 0;
963  src_val[1] = 1;
964  src_val[2] = 2;
965 
967 
968  if (TestCommWorld->size() > 1)
969  {
970  // Default communication
972 
973  TestCommWorld->receive (procdown,
974  recv_val,
975  request);
976 
977  TestCommWorld->send (procup,
978  src_val);
979 
981 
982  TIMPI_UNIT_ASSERT ( src_val.size() == recv_val.size() );
983 
984  for (std::size_t i=0; i<src_val.size(); i++)
985  TIMPI_UNIT_ASSERT( src_val[i] == recv_val[i] );
986 
987  // Synchronous communication
989  std::fill (recv_val.begin(), recv_val.end(), 0);
990 
991 
992  TestCommWorld->receive (procdown,
993  recv_val,
994  request);
995 
996  TestCommWorld->send (procup,
997  src_val);
998 
1000 
1001  TIMPI_UNIT_ASSERT ( src_val.size() == recv_val.size() );
1002 
1003  for (std::size_t i=0; i<src_val.size(); i++)
1004  TIMPI_UNIT_ASSERT( src_val[i] == recv_val[i] );
1005 
1006  // Restore default communication
1008  }
1009  }
1010 
1011 
1013  {
1014  unsigned int procup = (TestCommWorld->rank() + 1) %
1015  TestCommWorld->size();
1016  unsigned int procdown = (TestCommWorld->size() +
1017  TestCommWorld->rank() - 1) %
1018  TestCommWorld->size();
1019 
1020  std::set<unsigned int> src_val, recv_val;
1021 
1022  src_val.insert(4); // Chosen by fair dice roll
1023  src_val.insert(42);
1024  src_val.insert(1337);
1025 
1027 
1028  if (TestCommWorld->size() > 1)
1029  {
1030  TestCommWorld->send (procup, src_val, request);
1031 
1032  TestCommWorld->receive (procdown,
1033  recv_val);
1034 
1035  TIMPI_UNIT_ASSERT ( src_val.size() == recv_val.size() );
1036 
1037  for (std::set<unsigned int>::const_iterator
1038  it = src_val.begin(), end = src_val.end(); it != end;
1039  ++it)
1040  TIMPI_UNIT_ASSERT ( recv_val.count(*it) );
1041 
1042  TIMPI::wait (request);
1043 
1044  recv_val.clear();
1045  }
1046  }
1047 
1048 
1049 
1051  {
1052  unsigned int procup = (TestCommWorld->rank() + 1) %
1053  TestCommWorld->size();
1054  unsigned int procdown = (TestCommWorld->size() +
1055  TestCommWorld->rank() - 1) %
1056  TestCommWorld->size();
1057 
1058  std::vector<std::vector<unsigned int> > src_val(3), recv_val;
1059 
1060  src_val[0].push_back(4); // Chosen by fair dice roll
1061  src_val[2].push_back(procup);
1062  src_val[2].push_back(TestCommWorld->rank());
1063 
1065 
1066  if (TestCommWorld->size() > 1)
1067  {
1068  TestCommWorld->send (procup, src_val, request);
1069 
1070  TestCommWorld->receive (procdown,
1071  recv_val);
1072 
1073  TIMPI_UNIT_ASSERT ( src_val.size() == recv_val.size() );
1074 
1075  for (std::size_t i = 0; i != 3; ++i)
1076  TIMPI_UNIT_ASSERT ( src_val[i].size() == recv_val[i].size() );
1077 
1078  TIMPI_UNIT_ASSERT ( recv_val[0][0] == static_cast<unsigned int> (4) );
1079  TIMPI_UNIT_ASSERT ( recv_val[2][0] == static_cast<unsigned int> (TestCommWorld->rank()) );
1080  TIMPI_UNIT_ASSERT ( recv_val[2][1] == procdown );
1081 
1082  TIMPI::wait (request);
1083 
1084  recv_val.clear();
1085  }
1086  }
1087 
1088 
1090  {
1091  unsigned int procup = (TestCommWorld->rank() + 1) %
1092  TestCommWorld->size();
1093  unsigned int procdown = (TestCommWorld->size() +
1094  TestCommWorld->rank() - 1) %
1095  TestCommWorld->size();
1096 
1097  // Any odd processor out does nothing
1098  if ((TestCommWorld->size() % 2) && procup == 0)
1099  return;
1100 
1101  std::vector<std::vector<unsigned int> > src_val(3), recv_val;
1102 
1103  src_val[0].push_back(4); // Chosen by fair dice roll
1104  src_val[2].push_back(procup);
1105  src_val[2].push_back(TestCommWorld->rank());
1106 
1107  // Other even numbered processors send
1108  if (TestCommWorld->rank() % 2 == 0)
1109  TestCommWorld->send (procup, src_val);
1110  // Other odd numbered processors receive
1111  else
1112  {
1113  TestCommWorld->receive (procdown,
1114  recv_val);
1115 
1116  TIMPI_UNIT_ASSERT ( src_val.size() == recv_val.size() );
1117 
1118  for (std::size_t i = 0; i != 3; ++i)
1119  TIMPI_UNIT_ASSERT ( src_val[i].size() == recv_val[i].size() );
1120 
1121  TIMPI_UNIT_ASSERT ( recv_val[0][0] == static_cast<unsigned int> (4) );
1122  TIMPI_UNIT_ASSERT ( recv_val[2][0] == static_cast<unsigned int> (TestCommWorld->rank()) );
1123  TIMPI_UNIT_ASSERT ( recv_val[2][1] == procdown );
1124 
1125  recv_val.clear();
1126  }
1127  }
1128 
1129 
1130 
1132  {
1133  double inf = std::numeric_limits<double>::infinity();
1134 
1135  double *infptr = TestCommWorld->rank()%2 ? NULL : &inf;
1136 
1137  TIMPI_UNIT_ASSERT (TestCommWorld->semiverify(infptr));
1138 
1139  inf = -std::numeric_limits<double>::infinity();
1140 
1141  TIMPI_UNIT_ASSERT (TestCommWorld->semiverify(infptr));
1142  }
1143 
1144 
1146  {
1147  const std::string s = "Violin"; // Test requires a string instrument
1148 
1149  const std::string *sptr = TestCommWorld->rank()%2 ? NULL : &s;
1150 
1151  TIMPI_UNIT_ASSERT (TestCommWorld->semiverify(sptr));
1152  }
1153 
1154 
1156  {
1157  const std::vector<int> v = {1, 2, 3};
1158 
1159  const std::vector<int> *vptr = TestCommWorld->rank()%2 ? NULL : &v;
1160 
1161  TIMPI_UNIT_ASSERT (TestCommWorld->semiverify(vptr));
1162  }
1163 
1164 
1165  template<typename T>
1167  {
1168  const T one = 1;
1169 
1170  const T * tptr = TestCommWorld->rank()%2 ? NULL : &one;
1171 
1172  TIMPI_UNIT_ASSERT (TestCommWorld->semiverify(tptr));
1173  }
1174 
1175 
1176  void testSplit ()
1177  {
1178  TIMPI::Communicator subcomm;
1179  unsigned int rank = TestCommWorld->rank();
1180  unsigned int color = rank % 2;
1181  TestCommWorld->split(color, rank, subcomm);
1182 
1183  TIMPI_UNIT_ASSERT(subcomm.size() >= 1);
1184  TIMPI_UNIT_ASSERT(subcomm.size() >= TestCommWorld->size() / 2);
1185  TIMPI_UNIT_ASSERT(subcomm.size() <= TestCommWorld->size() / 2 + 1);
1186  }
1187 
1188 
1190  {
1191  TIMPI::Communicator subcomm;
1192  unsigned int rank = TestCommWorld->rank();
1193  TIMPI::info i = 0;
1194  int type = 0;
1195 #ifdef TIMPI_HAVE_MPI
1196  type = MPI_COMM_TYPE_SHARED;
1197  i = MPI_INFO_NULL;
1198 #endif
1199  TestCommWorld->split_by_type(type, rank, i, subcomm);
1200 
1201  TIMPI_UNIT_ASSERT(subcomm.size() >= 1);
1202  TIMPI_UNIT_ASSERT(subcomm.size() <= TestCommWorld->size());
1203  }
1204 
1205  template <typename NonBuiltin>
1207  {
1208  NonBuiltin ex{};
1209  StandardType<NonBuiltin> a(&ex);
1210  StandardType<NonBuiltin> b(&ex);
1211  a = b;
1212  }
1213 
1214 
1215 int main(int argc, const char * const * argv)
1216 {
1217  TIMPI::TIMPIInit init(argc, argv);
1218  TestCommWorld = &init.comm();
1219 
1220  setUp();
1221 
1222  testSum<std::map<int,int>>();
1223  testSum<std::unordered_map<int,int>>();
1224  testSumOpFunction<std::pair<int,int>>();
1225  testNonFixedTypeSum<std::map<std::string,int>>();
1226  testNonFixedTypeSum<std::unordered_map<std::string,int>>();
1227  testGather();
1228  testAllGather();
1229  testGatherString();
1238  testBroadcast<std::vector<unsigned int>>({0,1,2});
1239  testBroadcast<std::map<int, int>>({{0,0}, {1,1}, {2,2}});
1240  testBroadcast<std::map<int, std::string>>({{0,"foo"}, {1,"bar"}, {2,"baz"}});
1241  testBroadcast<std::unordered_map<int, int>>({{0,0}, {1,1}, {2,2}});
1242  testBroadcast<std::unordered_map<int, std::string>>({{0,"foo"}, {1,"bar"}, {2,"baz"}});
1246  testScatter();
1247  testBarrier();
1248  testMin();
1249  testMinVecBool();
1250  testMax();
1251  testMaxVecBool();
1252  testMPIULongMin();
1253  testMinLarge<char>();
1254  testMinLarge<unsigned char>();
1255  testMinLarge<short>();
1256  testMinLarge<unsigned short>();
1257  testMinLarge<int>();
1258  testMinLarge<unsigned int>();
1259  testMinLarge<long>();
1260  testMinLarge<unsigned long>();
1261  testMinLarge<long long>();
1262  testMinLarge<unsigned long long>();
1263  testMinLarge<float>();
1264  testMinLarge<double>();
1265  testMinLarge<long double>();
1266  testMapMax<std::map<int, int>>();
1267  testMapMax<std::unordered_map<int, int>>();
1268  testNonFixedTypeMapMax<std::map<std::string,int>>();
1269  testNonFixedTypeMapMax<std::unordered_map<std::string,int>>();
1270  testMinloc();
1271  testMaxloc();
1272  testMinlocBool();
1273  testMaxlocBool();
1274  testMinlocDouble();
1275  testMaxlocDouble();
1276  testMinlocPair();
1277  testMaxlocPair();
1278  testInfinityMin();
1279  testInfinityMax();
1280  testIsendRecv();
1281  testIrecvSend();
1288  testSemiVerifyType<bool>();
1289  testSemiVerifyType<char>();
1290  testSemiVerifyType<unsigned char>();
1291  testSemiVerifyType<short>();
1292  testSemiVerifyType<unsigned short>();
1293  testSemiVerifyType<int>();
1294  testSemiVerifyType<unsigned int>();
1295  testSemiVerifyType<long>();
1296  testSemiVerifyType<unsigned long>();
1297  testSemiVerifyType<long long>();
1298  testSemiVerifyType<unsigned long long>();
1299  testSemiVerifyType<float>();
1300  testSemiVerifyType<double>();
1301  testSemiVerifyType<long double>();
1302  testSplit();
1303  testSplitByType();
1310  testStandardTypeAssignment<TIMPI_DEFAULT_SCALAR_TYPE>();
1311  testStandardTypeAssignment<std::pair<unsigned, unsigned>>();
1312  testStandardTypeAssignment<std::array<unsigned, 1>>();
1313  testStandardTypeAssignment<std::tuple<unsigned, unsigned, unsigned>>();
1314 
1315  return 0;
1316 }
void testBroadcast(Container &&src)
void testSemiVerifyInf()
MPI_Request request
Request object for non-blocking I/O.
Definition: request.h:41
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 testMinLarge()
void testSemiVerifyString()
void testAllGatherVectorVector()
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...
void testBroadcastNestedType()
MPI_Info info
Info object used by some MPI-3 methods.
Definition: communicator.h:79
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.
static const request null_request
Definition: request.h:111
void testAllGatherEmptyVectorString()
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 setUp()
Definition: parallel_unit.C:15
The TIMPIInit class, when constructed, initializes any dependent libraries (e.g.
Definition: timpi_init.h:57
void testScatter()
void testMinlocBool()
void testBroadcastArrayType()
void testNonblockingString()
void sum(T &r) const
Take a local variable and replace it with the sum of it&#39;s values on all processors.
void barrier() const
Pause execution until all processors reach a certain point.
Definition: communicator.C:225
void testMaxVecBool()
void testAllGatherVectorVectorPacked()
void testAllGatherString()
processor_id_type rank() const
Definition: communicator.h:208
void testSum()
Definition: parallel_unit.C:31
void testNonblockingTest()
Templated class to provide the appropriate MPI datatype for use with built-in C types or simple C++ c...
Definition: standard_type.h:83
void testAllGatherHalfEmptyVectorString()
void testMaxlocPair()
void testNonblockingMin()
void testSumOpFunction()
Definition: parallel_unit.C:51
void testStandardTypeAssignment()
void testIrecvSend()
const unsigned int any_source
Processor id meaning "Accept from any source".
Definition: communicator.h:84
Encapsulates the MPI_Comm object.
Definition: communicator.h:108
void testMinlocPair()
void testSendRecvVecVecs()
void testRecvIsendSets()
processor_id_type size() const
Definition: communicator.h:211
std::vector< std::string > pt_number
Definition: parallel_unit.C:13
uint8_t processor_id_type
Definition: communicator.h:54
void testNonblockingSum()
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 testMin()
Communicator * TestCommWorld
Definition: parallel_unit.C:11
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 testSplitByType()
void testAllGatherVectorString()
void split(int color, int key, Communicator &target) const
Definition: communicator.C:97
void testSemiVerifyType()
Status wait()
Definition: request.C:121
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.
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 testNonblockingWaitany()
void testNonblockingMax()
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.
communicator & get()
Definition: communicator.h:167
void testMinloc()
void split_by_type(int split_type, int key, info i, Communicator &target) const
Definition: communicator.C:111
void testInfinityMin()
void testAllGatherVectorVectorInPlace()
void testMinVecBool()
void testMPIULongMin()
Encapsulates the MPI_Request.
Definition: request.h:67
void testAllGather()
std::size_t waitany(std::vector< Request > &r)
Wait for at least one non-blocking operation to finish.
Definition: request.C:219
void max(const T &r, T &o, Request &req) const
Non-blocking maximum of the local value r into o with the request req.
void testMaxloc()
void testIsendRecv()
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.
void testGatherString2()
void testInfinityMax()
request * get()
Definition: request.h:84
void testMinlocDouble()
void testGather()
Definition: parallel_unit.C:88
void testMax()
void testBarrier()
void testBroadcastString()
void testMapMax()
int main(int argc, const char *const *argv)
void testMaxlocDouble()
Status wait(Request &r)
Wait for a non-blocking send or receive to finish.
Definition: request.h:135
void testSplit()
void testNonFixedTypeSum()
Definition: parallel_unit.C:69
void testNonFixedTypeMapMax()
void testRecvIsendVecVecs()
const Communicator & comm() const
Returns the Communicator created by this object, which will be a compatibility shim if MPI is not ena...
Definition: timpi_init.h:100
void testGatherString()
bool test()
Definition: request.C:153
void testSemiVerifyVector()
void testMaxlocBool()