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;
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'll let the destructor do the wait this time
467  }
468 
469 
471  {
472  constexpr std::size_t N=5;
473  std::vector<unsigned int> local_vals(N),
474  min_vals(N, std::numeric_limits<unsigned int>::max());
475  std::iota(local_vals.begin(), local_vals.end(), TestCommWorld->rank()+4);
476 
477  std::size_t tests_done = 0;
478 
479  std::vector<Request> reqs;
480  for (std::size_t i=0; i != N; ++i)
481  {
482  Request req;
483  TestCommWorld->min(local_vals[i], min_vals[i], req);
484 
485  // We might have finished immediately, e.g. if we're on one
486  // processor
487  if (*req.get() == Request::null_request)
488  {
489  TIMPI_UNIT_ASSERT (min_vals[i] == static_cast<unsigned int>(4+i));
490  ++tests_done;
491  }
492  reqs.push_back(req);
493  }
494 
495  std::size_t i = std::size_t(-1);
496  if (tests_done != N)
497  i = waitany(reqs);
498  while (i != std::size_t(-1))
499  {
500  TIMPI_UNIT_ASSERT (min_vals[i] == static_cast<unsigned int>(4+i));
501  ++tests_done;
502  i = waitany(reqs);
503  }
504 
505  TIMPI_UNIT_ASSERT (tests_done == N);
506  }
507 
508 
509 
511  {
512  int true_sum = 0;
513  for (int rank = 0; rank < (int)TestCommWorld->size(); ++rank)
514  true_sum += rank + 1;
515 
516  int local_val = TestCommWorld->rank() + 1;
517  int sum;
518 
520  TestCommWorld->sum(local_val, sum, request);
521  request.wait();
522 
523  TIMPI_UNIT_ASSERT (true_sum == sum);
524  }
525 
526 
527 
529  {
530  unsigned int local_val = TestCommWorld->rank();
531  unsigned int min = std::numeric_limits<unsigned int>::max();
532 
533  Request req;
534  TestCommWorld->min(local_val, min, req);
535  req.wait();
536 
537  TIMPI_UNIT_ASSERT (min == static_cast<unsigned int>(0));
538  }
539 
540 
541 
542  void testMin ()
543  {
544  unsigned int min = TestCommWorld->rank();
545 
546  TestCommWorld->min(min);
547 
548  TIMPI_UNIT_ASSERT (min == static_cast<unsigned int>(0));
549  }
550 
551 
553  {
554  const processor_id_type rank = TestCommWorld->rank();
555  const processor_id_type N = TestCommWorld->size();
556 
557  // Use a long vector, so we can be sure that many bits extends
558  // over multiple unsigned integers; use a weird size to test the
559  // not-evenly-divisible case.
560  constexpr std::size_t vec_size = 2345;
561  std::vector<bool> vec_bool(vec_size, true);
562  for (std::size_t i=0; i < vec_size; i += (rank+2))
563  vec_bool[i] = false;
564 
565  TestCommWorld->min(vec_bool);
566 
567  for (std::size_t i=0; i != vec_size; ++i)
568  {
569  bool should_be_true = true;
570  for (processor_id_type p=0; p < N; ++p)
571  if (i % (p+2) == 0)
572  {
573  should_be_true = false;
574  break;
575  }
576  TIMPI_UNIT_ASSERT (vec_bool[i] == should_be_true);
577  }
578  }
579 
580 
581 
582 
584  {
585  unsigned long min = 1;
586  if (TestCommWorld->rank() % 2)
587  min = std::numeric_limits<unsigned long>::max();
588 
589  timpi_call_mpi
590  (MPI_Allreduce (MPI_IN_PLACE, &min, 1,
591  MPI_UNSIGNED_LONG, MPI_MIN,
592  TestCommWorld->get()));
593 
594  TIMPI_UNIT_ASSERT (min == 1);
595  }
596 
597  template <typename T>
598  void testMinLarge ()
599  {
600  T min = 1;
601 
602  if (TestCommWorld->rank() % 2)
603  min = std::numeric_limits<T>::max();
604 
605  TestCommWorld->min(min);
606 
607  TIMPI_UNIT_ASSERT (min == 1);
608  }
609 
610 
611 
613  {
614  processor_id_type local_val = TestCommWorld->rank();
615  processor_id_type max = std::numeric_limits<processor_id_type>::min();
616 
617  Request req;
618  TestCommWorld->max(local_val, max, req);
619  req.wait();
620 
621  TIMPI_UNIT_ASSERT (cast_int<processor_id_type>(max+1) ==
622  cast_int<processor_id_type>(TestCommWorld->size()));
623  }
624 
625 
626 
627  void testMax ()
628  {
630 
631  TestCommWorld->max(max);
632 
633  TIMPI_UNIT_ASSERT (cast_int<processor_id_type>(max+1) ==
634  cast_int<processor_id_type>(TestCommWorld->size()));
635  }
636 
637 
638 
640  {
641  const processor_id_type rank = TestCommWorld->rank();
642  const processor_id_type N = TestCommWorld->size();
643 
644  // Use a long vector, so we can be sure it extends over multiple
645  // unsigned integers; use a weird size to test the
646  // not-evenly-divisible case.
647  constexpr std::size_t vec_size = 2345;
648  std::vector<bool> vec_bool(vec_size, false);
649  for (std::size_t i=0; i < vec_size; i += (rank+2))
650  vec_bool[i] = true;
651 
652  TestCommWorld->max(vec_bool);
653 
654  for (std::size_t i=0; i != vec_size; ++i)
655  {
656  bool should_be_true = false;
657  for (processor_id_type p=0; p < N; ++p)
658  if (i % (p+2) == 0)
659  {
660  should_be_true = true;
661  break;
662  }
663  TIMPI_UNIT_ASSERT (vec_bool[i] == should_be_true);
664  }
665  }
666 
667 
668 
669  template <class Map>
670  void testMapMax ()
671  {
672  Map data;
673 
674  int rank = TestCommWorld->rank();
675  int N = TestCommWorld->size();
676 
677  // On each proc, the map has the single entry (rank, rank)
678  data[rank] = rank;
679 
680  // Compute the max
681  TestCommWorld->max(data);
682 
683  // After calling max, there should be an entry for each rank
684  for (int p=0; p<N; ++p)
685  TIMPI_UNIT_ASSERT (data[p] == p);
686  }
687 
688 
689 
690  template <class Map>
692  {
693  Map data;
694 
695  int rank = TestCommWorld->rank();
696  int N = TestCommWorld->size();
697 
698  // On each proc, the map has a single entry, e.g. ("key0", 0)
699  data[std::string("key") + std::to_string(rank)] = rank;
700 
701  // Compute the max
702  TestCommWorld->max(data);
703 
704  // After calling max, there should be an entry for each rank
705  for (int p=0; p<N; ++p)
706  TIMPI_UNIT_ASSERT (data[std::string("key") + std::to_string(p)] == p);
707  }
708 
709 
710 
711  void testMinloc ()
712  {
713  int min = (TestCommWorld->rank() + 1) % TestCommWorld->size();
714  unsigned int minid = 0;
715 
716  TestCommWorld->minloc(min, minid);
717 
718  TIMPI_UNIT_ASSERT (min == static_cast<int>(0));
719  TIMPI_UNIT_ASSERT (minid == static_cast<unsigned int>(TestCommWorld->size()-1));
720  }
721 
722 
723 
724  void testMaxloc ()
725  {
726  int max = TestCommWorld->rank();
727  unsigned int maxid = 0;
728 
729  TestCommWorld->maxloc(max, maxid);
730 
731  TIMPI_UNIT_ASSERT (max+1 ==
732  cast_int<int>(TestCommWorld->size()));
733  TIMPI_UNIT_ASSERT (maxid == static_cast<unsigned int>(TestCommWorld->size()-1));
734  }
735 
736 
737 
739  {
740  bool min = ((TestCommWorld->rank() + TestCommWorld->size()-1) % 2);
741  unsigned int minid = 0;
742 
743  TestCommWorld->minloc(min, minid);
744 
745  TIMPI_UNIT_ASSERT (min == static_cast<int>(0));
746  TIMPI_UNIT_ASSERT (minid == static_cast<unsigned int>((TestCommWorld->size()-1)%2));
747  }
748 
749 
750 
752  {
753  double min = (TestCommWorld->rank() + 1) % TestCommWorld->size();
754  unsigned int minid = 0;
755 
756  TestCommWorld->minloc(min, minid);
757 
758  TIMPI_UNIT_ASSERT (min == double(0));
759  TIMPI_UNIT_ASSERT (minid == static_cast<unsigned int>(TestCommWorld->size()-1));
760  }
761 
762 
763 
765  {
766  bool max = ((TestCommWorld->rank() + TestCommWorld->size()) % 2);
767  unsigned int maxid = 0;
768 
769  TestCommWorld->maxloc(max, maxid);
770 
771  TIMPI_UNIT_ASSERT (max == static_cast<int>(1));
772  TIMPI_UNIT_ASSERT (maxid == static_cast<unsigned int>((TestCommWorld->size()-1)%2));
773  }
774 
775 
776 
778  {
779  double max = TestCommWorld->rank();
780  unsigned int maxid = 0;
781 
782  TestCommWorld->maxloc(max, maxid);
783 
784  // Hope nobody uses 1677216 procs with single precision
785  TIMPI_UNIT_ASSERT (max+1 == double(TestCommWorld->size()));
786  TIMPI_UNIT_ASSERT (maxid == static_cast<unsigned int>(TestCommWorld->size()-1));
787  }
788 
789 
790 
792  {
793  int min = (TestCommWorld->rank() + 1) % TestCommWorld->size();
794  int min_tag = min + 3;
795  unsigned int minid = 0;
796 
797  std::pair<int, int> p{min, min_tag};
798 
799  TestCommWorld->minloc(p, minid);
800 
801  TIMPI_UNIT_ASSERT (p.first == static_cast<int>(0));
802  TIMPI_UNIT_ASSERT (p.second == static_cast<int>(3));
803  TIMPI_UNIT_ASSERT (minid == static_cast<unsigned int>(TestCommWorld->size()-1));
804  }
805 
806 
807 
809  {
810  int max = TestCommWorld->rank();
811  int max_tag = max + 3;
812  unsigned int maxid = 0;
813 
814  std::pair<int, int> p{max, max_tag};
815 
816  TestCommWorld->maxloc(p, maxid);
817 
818  TIMPI_UNIT_ASSERT (p.first+1 ==
819  cast_int<int>(TestCommWorld->size()));
820  TIMPI_UNIT_ASSERT (p.second+1 ==
821  cast_int<int>(TestCommWorld->size())+3);
822  TIMPI_UNIT_ASSERT (maxid == static_cast<unsigned int>(TestCommWorld->size()-1));
823  }
824 
825 
826 
828  {
829  double min = std::numeric_limits<double>::infinity();
830 
831  TestCommWorld->min(min);
832 
833  TIMPI_UNIT_ASSERT (min == std::numeric_limits<double>::infinity());
834 
835  min = -std::numeric_limits<double>::infinity();
836 
837  TestCommWorld->min(min);
838 
839  TIMPI_UNIT_ASSERT (min == -std::numeric_limits<double>::infinity());
840  }
841 
842 
843 
845  {
846  double max = std::numeric_limits<double>::infinity();
847 
848  TestCommWorld->max(max);
849 
850  TIMPI_UNIT_ASSERT (max == std::numeric_limits<double>::infinity());
851 
852  max = -std::numeric_limits<double>::infinity();
853 
854  TestCommWorld->max(max);
855 
856  TIMPI_UNIT_ASSERT (max == -std::numeric_limits<double>::infinity());
857  }
858 
859 
860 
862  {
863  unsigned int procup = (TestCommWorld->rank() + 1) %
864  TestCommWorld->size();
865  unsigned int procdown = (TestCommWorld->size() +
866  TestCommWorld->rank() - 1) %
867  TestCommWorld->size();
868 
869  std::vector<unsigned int> src_val(3), recv_val(3);
870 
871  src_val[0] = 0;
872  src_val[1] = 1;
873  src_val[2] = 2;
874 
876 
877  if (TestCommWorld->size() > 1)
878  {
879  // Default communication
881 
882  TestCommWorld->send (procup,
883  src_val,
884  request);
885 
886  TestCommWorld->receive (procdown,
887  recv_val);
888 
890 
891  TIMPI_UNIT_ASSERT ( src_val.size() == recv_val.size() );
892 
893  for (std::size_t i=0; i<src_val.size(); i++)
894  TIMPI_UNIT_ASSERT( src_val[i] == recv_val[i] );
895 
896 
897  // Synchronous communication
899  std::fill (recv_val.begin(), recv_val.end(), 0);
900 
901  TestCommWorld->send (procup,
902  src_val,
903  request);
904 
905  TestCommWorld->receive (procdown,
906  recv_val);
907 
909 
910  TIMPI_UNIT_ASSERT ( src_val.size() == recv_val.size() );
911 
912  for (std::size_t i=0; i<src_val.size(); i++)
913  TIMPI_UNIT_ASSERT( src_val[i] == recv_val[i] );
914 
915  // Restore default communication
917  }
918  }
919 
920 
921 
923  {
924  unsigned int procup = (TestCommWorld->rank() + 1) %
925  TestCommWorld->size();
926  unsigned int procdown = (TestCommWorld->size() +
927  TestCommWorld->rank() - 1) %
928  TestCommWorld->size();
929 
930  std::vector<unsigned int> src_val(3), recv_val(3);
931 
932  src_val[0] = 0;
933  src_val[1] = 1;
934  src_val[2] = 2;
935 
937 
938  if (TestCommWorld->size() > 1)
939  {
940  // Default communication
942 
943  TestCommWorld->receive (procdown,
944  recv_val,
945  request);
946 
947  TestCommWorld->send (procup,
948  src_val);
949 
951 
952  TIMPI_UNIT_ASSERT ( src_val.size() == recv_val.size() );
953 
954  for (std::size_t i=0; i<src_val.size(); i++)
955  TIMPI_UNIT_ASSERT( src_val[i] == recv_val[i] );
956 
957  // Synchronous communication
959  std::fill (recv_val.begin(), recv_val.end(), 0);
960 
961 
962  TestCommWorld->receive (procdown,
963  recv_val,
964  request);
965 
966  TestCommWorld->send (procup,
967  src_val);
968 
970 
971  TIMPI_UNIT_ASSERT ( src_val.size() == recv_val.size() );
972 
973  for (std::size_t i=0; i<src_val.size(); i++)
974  TIMPI_UNIT_ASSERT( src_val[i] == recv_val[i] );
975 
976  // Restore default communication
978  }
979  }
980 
981 
983  {
984  unsigned int procup = (TestCommWorld->rank() + 1) %
985  TestCommWorld->size();
986  unsigned int procdown = (TestCommWorld->size() +
987  TestCommWorld->rank() - 1) %
988  TestCommWorld->size();
989 
990  std::set<unsigned int> src_val, recv_val;
991 
992  src_val.insert(4); // Chosen by fair dice roll
993  src_val.insert(42);
994  src_val.insert(1337);
995 
997 
998  if (TestCommWorld->size() > 1)
999  {
1000  TestCommWorld->send (procup, src_val, request);
1001 
1002  TestCommWorld->receive (procdown,
1003  recv_val);
1004 
1005  TIMPI_UNIT_ASSERT ( src_val.size() == recv_val.size() );
1006 
1007  for (std::set<unsigned int>::const_iterator
1008  it = src_val.begin(), end = src_val.end(); it != end;
1009  ++it)
1010  TIMPI_UNIT_ASSERT ( recv_val.count(*it) );
1011 
1012  TIMPI::wait (request);
1013 
1014  recv_val.clear();
1015  }
1016  }
1017 
1018 
1019 
1021  {
1022  unsigned int procup = (TestCommWorld->rank() + 1) %
1023  TestCommWorld->size();
1024  unsigned int procdown = (TestCommWorld->size() +
1025  TestCommWorld->rank() - 1) %
1026  TestCommWorld->size();
1027 
1028  std::vector<std::vector<unsigned int> > src_val(3), recv_val;
1029 
1030  src_val[0].push_back(4); // Chosen by fair dice roll
1031  src_val[2].push_back(procup);
1032  src_val[2].push_back(TestCommWorld->rank());
1033 
1035 
1036  if (TestCommWorld->size() > 1)
1037  {
1038  TestCommWorld->send (procup, src_val, request);
1039 
1040  TestCommWorld->receive (procdown,
1041  recv_val);
1042 
1043  TIMPI_UNIT_ASSERT ( src_val.size() == recv_val.size() );
1044 
1045  for (std::size_t i = 0; i != 3; ++i)
1046  TIMPI_UNIT_ASSERT ( src_val[i].size() == recv_val[i].size() );
1047 
1048  TIMPI_UNIT_ASSERT ( recv_val[0][0] == static_cast<unsigned int> (4) );
1049  TIMPI_UNIT_ASSERT ( recv_val[2][0] == static_cast<unsigned int> (TestCommWorld->rank()) );
1050  TIMPI_UNIT_ASSERT ( recv_val[2][1] == procdown );
1051 
1052  TIMPI::wait (request);
1053 
1054  recv_val.clear();
1055  }
1056  }
1057 
1058 
1060  {
1061  unsigned int procup = (TestCommWorld->rank() + 1) %
1062  TestCommWorld->size();
1063  unsigned int procdown = (TestCommWorld->size() +
1064  TestCommWorld->rank() - 1) %
1065  TestCommWorld->size();
1066 
1067  // Any odd processor out does nothing
1068  if ((TestCommWorld->size() % 2) && procup == 0)
1069  return;
1070 
1071  std::vector<std::vector<unsigned int> > src_val(3), recv_val;
1072 
1073  src_val[0].push_back(4); // Chosen by fair dice roll
1074  src_val[2].push_back(procup);
1075  src_val[2].push_back(TestCommWorld->rank());
1076 
1077  // Other even numbered processors send
1078  if (TestCommWorld->rank() % 2 == 0)
1079  TestCommWorld->send (procup, src_val);
1080  // Other odd numbered processors receive
1081  else
1082  {
1083  TestCommWorld->receive (procdown,
1084  recv_val);
1085 
1086  TIMPI_UNIT_ASSERT ( src_val.size() == recv_val.size() );
1087 
1088  for (std::size_t i = 0; i != 3; ++i)
1089  TIMPI_UNIT_ASSERT ( src_val[i].size() == recv_val[i].size() );
1090 
1091  TIMPI_UNIT_ASSERT ( recv_val[0][0] == static_cast<unsigned int> (4) );
1092  TIMPI_UNIT_ASSERT ( recv_val[2][0] == static_cast<unsigned int> (TestCommWorld->rank()) );
1093  TIMPI_UNIT_ASSERT ( recv_val[2][1] == procdown );
1094 
1095  recv_val.clear();
1096  }
1097  }
1098 
1099 
1100 
1102  {
1103  double inf = std::numeric_limits<double>::infinity();
1104 
1105  double *infptr = TestCommWorld->rank()%2 ? NULL : &inf;
1106 
1107  TIMPI_UNIT_ASSERT (TestCommWorld->semiverify(infptr));
1108 
1109  inf = -std::numeric_limits<double>::infinity();
1110 
1111  TIMPI_UNIT_ASSERT (TestCommWorld->semiverify(infptr));
1112  }
1113 
1114 
1116  {
1117  const std::string s = "Violin"; // Test requires a string instrument
1118 
1119  const std::string *sptr = TestCommWorld->rank()%2 ? NULL : &s;
1120 
1121  TIMPI_UNIT_ASSERT (TestCommWorld->semiverify(sptr));
1122  }
1123 
1124 
1126  {
1127  const std::vector<int> v = {1, 2, 3};
1128 
1129  const std::vector<int> *vptr = TestCommWorld->rank()%2 ? NULL : &v;
1130 
1131  TIMPI_UNIT_ASSERT (TestCommWorld->semiverify(vptr));
1132  }
1133 
1134 
1135  template<typename T>
1137  {
1138  const T one = 1;
1139 
1140  const T * tptr = TestCommWorld->rank()%2 ? NULL : &one;
1141 
1142  TIMPI_UNIT_ASSERT (TestCommWorld->semiverify(tptr));
1143  }
1144 
1145 
1146  void testSplit ()
1147  {
1148  TIMPI::Communicator subcomm;
1149  unsigned int rank = TestCommWorld->rank();
1150  unsigned int color = rank % 2;
1151  TestCommWorld->split(color, rank, subcomm);
1152 
1153  TIMPI_UNIT_ASSERT(subcomm.size() >= 1);
1154  TIMPI_UNIT_ASSERT(subcomm.size() >= TestCommWorld->size() / 2);
1155  TIMPI_UNIT_ASSERT(subcomm.size() <= TestCommWorld->size() / 2 + 1);
1156  }
1157 
1158 
1160  {
1161  TIMPI::Communicator subcomm;
1162  unsigned int rank = TestCommWorld->rank();
1163  TIMPI::info i = 0;
1164  int type = 0;
1165 #ifdef TIMPI_HAVE_MPI
1166  type = MPI_COMM_TYPE_SHARED;
1167  i = MPI_INFO_NULL;
1168 #endif
1169  TestCommWorld->split_by_type(type, rank, i, subcomm);
1170 
1171  TIMPI_UNIT_ASSERT(subcomm.size() >= 1);
1172  TIMPI_UNIT_ASSERT(subcomm.size() <= TestCommWorld->size());
1173  }
1174 
1175  template <typename NonBuiltin>
1177  {
1178  NonBuiltin ex{};
1179  StandardType<NonBuiltin> a(&ex);
1180  StandardType<NonBuiltin> b(&ex);
1181  a = b;
1182  }
1183 
1184 
1185 int main(int argc, const char * const * argv)
1186 {
1187  TIMPI::TIMPIInit init(argc, argv);
1188  TestCommWorld = &init.comm();
1189 
1190  setUp();
1191 
1192  testSum<std::map<int,int>>();
1193  testSum<std::unordered_map<int,int>>();
1194  testSumOpFunction<std::pair<int,int>>();
1195  testNonFixedTypeSum<std::map<std::string,int>>();
1196  testNonFixedTypeSum<std::unordered_map<std::string,int>>();
1197  testGather();
1198  testAllGather();
1199  testGatherString();
1208  testBroadcast<std::vector<unsigned int>>({0,1,2});
1209  testBroadcast<std::map<int, int>>({{0,0}, {1,1}, {2,2}});
1210  testBroadcast<std::map<int, std::string>>({{0,"foo"}, {1,"bar"}, {2,"baz"}});
1211  testBroadcast<std::unordered_map<int, int>>({{0,0}, {1,1}, {2,2}});
1212  testBroadcast<std::unordered_map<int, std::string>>({{0,"foo"}, {1,"bar"}, {2,"baz"}});
1216  testScatter();
1217  testBarrier();
1218  testMin();
1219  testMinVecBool();
1220  testMax();
1221  testMaxVecBool();
1222  testMPIULongMin();
1223  testMinLarge<char>();
1224  testMinLarge<unsigned char>();
1225  testMinLarge<short>();
1226  testMinLarge<unsigned short>();
1227  testMinLarge<int>();
1228  testMinLarge<unsigned int>();
1229  testMinLarge<long>();
1230  testMinLarge<unsigned long>();
1231  testMinLarge<long long>();
1232  testMinLarge<unsigned long long>();
1233  testMinLarge<float>();
1234  testMinLarge<double>();
1235  testMinLarge<long double>();
1236  testMapMax<std::map<int, int>>();
1237  testMapMax<std::unordered_map<int, int>>();
1238  testNonFixedTypeMapMax<std::map<std::string,int>>();
1239  testNonFixedTypeMapMax<std::unordered_map<std::string,int>>();
1240  testMinloc();
1241  testMaxloc();
1242  testMinlocBool();
1243  testMaxlocBool();
1244  testMinlocDouble();
1245  testMaxlocDouble();
1246  testMinlocPair();
1247  testMaxlocPair();
1248  testInfinityMin();
1249  testInfinityMax();
1250  testIsendRecv();
1251  testIrecvSend();
1258  testSemiVerifyType<bool>();
1259  testSemiVerifyType<char>();
1260  testSemiVerifyType<unsigned char>();
1261  testSemiVerifyType<short>();
1262  testSemiVerifyType<unsigned short>();
1263  testSemiVerifyType<int>();
1264  testSemiVerifyType<unsigned int>();
1265  testSemiVerifyType<long>();
1266  testSemiVerifyType<unsigned long>();
1267  testSemiVerifyType<long long>();
1268  testSemiVerifyType<unsigned long long>();
1269  testSemiVerifyType<float>();
1270  testSemiVerifyType<double>();
1271  testSemiVerifyType<long double>();
1272  testSplit();
1273  testSplitByType();
1279  testStandardTypeAssignment<TIMPI_DEFAULT_SCALAR_TYPE>();
1280  testStandardTypeAssignment<std::pair<unsigned, unsigned>>();
1281  testStandardTypeAssignment<std::array<unsigned, 1>>();
1282  testStandardTypeAssignment<std::tuple<unsigned, unsigned, unsigned>>();
1283 
1284  return 0;
1285 }
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 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()
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()