libMesh
Loading...
Searching...
No Matches
parallel_test.C
Go to the documentation of this file.
1#include <libmesh/parallel.h>
2#include <libmesh/stored_range.h>
3
4#include "test_comm.h"
5#include "libmesh_cppunit.h"
6
7#include <atomic>
8#include <memory>
9#include <numeric>
10#include <set>
11#include <thread>
12
13
14using namespace libMesh;
15
16namespace {
17
18using TestRange = StoredRange<std::vector<unsigned int>::const_iterator, unsigned int>;
19
20// Shared helper state for the thread-subset tests. Each body records how many
21// subrange invocations happened, which thread ids executed them, and a few
22// simple aggregate checksums so we can verify every input value was visited.
23struct VisitTracker
24{
25 void record_invocation()
26 {
27 invocations.fetch_add(1, std::memory_order_relaxed);
28
29 Threads::spin_mutex::scoped_lock lock(mutex);
30 thread_ids.insert(std::this_thread::get_id());
31 }
32
33 void record_value(const unsigned int value)
34 {
35 value_count.fetch_add(1, std::memory_order_relaxed);
36 value_sum.fetch_add(value, std::memory_order_relaxed);
37 value_sum_sq.fetch_add(value * value, std::memory_order_relaxed);
38 }
39
40 std::size_t unique_thread_count() const
41 {
42 Threads::spin_mutex::scoped_lock lock(mutex);
43 return thread_ids.size();
44 }
45
46 mutable Threads::spin_mutex mutex;
47 std::set<std::thread::id> thread_ids;
48 std::atomic<unsigned int> invocations{0};
49 std::atomic<unsigned int> value_count{0};
50 std::atomic<unsigned int> value_sum{0};
51 std::atomic<unsigned int> value_sum_sq{0};
52};
53
54// Compare the aggregates collected by VisitTracker against the known test
55// input values. Using count/sum/sum-of-squares gives us a compact way to catch
56// dropped or duplicated work without depending on any particular scheduling.
57void assert_tracker_matches_values(const VisitTracker & tracker,
58 const std::vector<unsigned int> & values)
59{
60 unsigned int expected_sum = 0;
61 unsigned int expected_sum_sq = 0;
62
63 for (const auto value : values)
64 {
65 expected_sum += value;
66 expected_sum_sq += value * value;
67 }
68
69 CPPUNIT_ASSERT_EQUAL(static_cast<unsigned int>(values.size()),
70 tracker.value_count.load(std::memory_order_relaxed));
71 CPPUNIT_ASSERT_EQUAL(expected_sum,
72 tracker.value_sum.load(std::memory_order_relaxed));
73 CPPUNIT_ASSERT_EQUAL(expected_sum_sq,
74 tracker.value_sum_sq.load(std::memory_order_relaxed));
75}
76
77struct ForBody
78{
79 explicit ForBody(VisitTracker & tracker_in) : tracker(tracker_in) {}
80
81 void operator()(const TestRange & range) const
82 {
83 tracker.record_invocation();
84
85 for (const auto value : range)
86 tracker.record_value(value);
87 }
88
89 VisitTracker & tracker;
90};
91
92struct ReduceBody
93{
94 explicit ReduceBody(std::shared_ptr<VisitTracker> tracker_in) :
95 tracker(std::move(tracker_in))
96 {}
97
98 ReduceBody(ReduceBody & other, Threads::split) :
99 tracker(other.tracker)
100 {}
101
102 void operator()(const TestRange & range)
103 {
104 tracker->record_invocation();
105
106 for (const auto value : range)
107 {
108 ++value_count;
109 value_sum += value;
110 value_sum_sq += value * value;
111 tracker->record_value(value);
112 }
113 }
114
115 void join(const ReduceBody & other)
116 {
117 value_count += other.value_count;
118 value_sum += other.value_sum;
119 value_sum_sq += other.value_sum_sq;
120 }
121
122 std::shared_ptr<VisitTracker> tracker;
123 unsigned int value_count = 0;
124 unsigned int value_sum = 0;
125 unsigned int value_sum_sq = 0;
126};
127
128} // anonymous namespace
129
130class ParallelTest : public CppUnit::TestCase {
131public:
133
162#if defined(LIBMESH_ENABLE_EXCEPTIONS)
164#endif
165
167
168private:
169 std::vector<std::string> _number;
170
171public:
172 void setUp()
173 {
174 _number.resize(10);
175 _number[0] = "Zero";
176 _number[1] = "One";
177 _number[2] = "Two";
178 _number[3] = "Three";
179 _number[4] = "Four";
180 _number[5] = "Five";
181 _number[6] = "Six";
182 _number[7] = "Seven";
183 _number[8] = "Eight";
184 _number[9] = "Nine";
185 }
186
187 void tearDown()
188 {}
189
190
191
193 {
194 LOG_UNIT_TEST;
195
196 std::vector<processor_id_type> vals;
197 TestCommWorld->gather(0,cast_int<processor_id_type>(TestCommWorld->rank()),vals);
198
199 if (TestCommWorld->rank() == 0)
200 for (processor_id_type i=0; i<vals.size(); i++)
201 CPPUNIT_ASSERT_EQUAL( i , vals[i] );
202 }
203
204
205
207 {
208 LOG_UNIT_TEST;
209
210 std::vector<std::string> vals;
211 TestCommWorld->gather(0, "Processor" + _number[TestCommWorld->rank() % 10], vals);
212
213 if (TestCommWorld->rank() == 0)
214 for (processor_id_type i=0; i<vals.size(); i++)
215 CPPUNIT_ASSERT_EQUAL( "Processor" + _number[i % 10] , vals[i] );
216 }
217
218
219
221 {
222 LOG_UNIT_TEST;
223
224 std::vector<processor_id_type> vals;
225 TestCommWorld->allgather(cast_int<processor_id_type>(TestCommWorld->rank()),vals);
226
227 for (processor_id_type i=0; i<vals.size(); i++)
228 CPPUNIT_ASSERT_EQUAL( i , vals[i] );
229 }
230
231
232
234 {
235 LOG_UNIT_TEST;
236
237 std::vector<std::string> vals;
238 TestCommWorld->gather(0, "Processor" + _number[TestCommWorld->rank() % 10], vals);
239
240 for (processor_id_type i=0; i<vals.size(); i++)
241 CPPUNIT_ASSERT_EQUAL( "Processor" + _number[i % 10] , vals[i] );
242 }
243
244
245
247 {
248 LOG_UNIT_TEST;
249
250 std::vector<std::string> vals;
251 vals.push_back("Processor" + _number[TestCommWorld->rank() % 10] + "A");
252 vals.push_back("Processor" + _number[TestCommWorld->rank() % 10] + "B");
253 TestCommWorld->allgather(vals);
254
255 for (processor_id_type i=0; i<(vals.size()/2); i++)
256 {
257 CPPUNIT_ASSERT_EQUAL( "Processor" + _number[i % 10] + "A" , vals[2*i] );
258 CPPUNIT_ASSERT_EQUAL( "Processor" + _number[i % 10] + "B" , vals[2*i+1] );
259 }
260 }
261
262
263
265 {
266 LOG_UNIT_TEST;
267
268 std::vector<std::string> vals;
269 TestCommWorld->allgather(vals);
270
271 CPPUNIT_ASSERT( vals.empty() );
272 }
273
274
275
277 {
278 LOG_UNIT_TEST;
279
280 std::vector<std::string> vals;
281
282 if (!TestCommWorld->rank())
283 vals.push_back("Proc 0 only");
284
285 TestCommWorld->allgather(vals);
286
287 CPPUNIT_ASSERT_EQUAL( vals[0], std::string("Proc 0 only") );
288 }
289
290
291
293 {
294 LOG_UNIT_TEST;
295
296 // Workaround for spurious warning from operator=
297 // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100366
298 std::vector<unsigned int> src{0,1,2}, dest(3,0);
299
300 if (TestCommWorld->rank() == 0)
301 dest = src;
302
303 TestCommWorld->broadcast(dest);
304
305 for (std::size_t i=0; i<3; i++)
306 CPPUNIT_ASSERT_EQUAL( src[i] , dest[i] );
307 }
308
309
310
312 {
313 LOG_UNIT_TEST;
314
315 using std::pair;
316 typedef pair<pair<pair<pair<int, int>, int>, int>, int> pppp;
317 std::vector<pppp> src(3), dest(3);
318
319 src[0].first.first.first.first=0;
320 src[0].first.first.first.second=-1;
321 src[0].first.second = -2;
322 src[0].second = -3;
323 src[1].first.first.first.first=10;
324 src[1].first.first.first.second=9;
325 src[1].first.second = 8;
326 src[1].second = 7;
327 src[2].first.first.first.first=20;
328 src[2].first.first.first.second=19;
329 src[2].first.second = 18;
330 src[2].second = 17;
331
332 if (TestCommWorld->rank() == 0)
333 dest = src;
334
335 TestCommWorld->broadcast(dest);
336
337 for (std::size_t i=0; i<src.size(); i++)
338 {
339 CPPUNIT_ASSERT_EQUAL(src[i].first.first.first.first,
340 dest[i].first.first.first.first);
341 CPPUNIT_ASSERT_EQUAL(src[i].first.first.first.second,
342 dest[i].first.first.first.second);
343 CPPUNIT_ASSERT_EQUAL(src[i].first.first.second,
344 dest[i].first.first.second);
345 CPPUNIT_ASSERT_EQUAL(src[i].first.second,
346 dest[i].first.second);
347 CPPUNIT_ASSERT_EQUAL(src[i].second,
348 dest[i].second);
349 }
350 }
351
352
353
355 {
356 LOG_UNIT_TEST;
357
358 // Test Scalar scatter
359 {
360 std::vector<processor_id_type> src;
362
363 if (TestCommWorld->rank() == 0)
364 {
365 src.resize(TestCommWorld->size());
366 for (processor_id_type i=0; i<src.size(); i++)
367 src[i] = i;
368 }
369
370 TestCommWorld->scatter(src, dest);
371
372 CPPUNIT_ASSERT_EQUAL( TestCommWorld->rank(), dest );
373 }
374
375 // Test Vector Scatter (equal-sized chunks)
376 {
377 std::vector<unsigned int> src;
378 std::vector<unsigned int> dest;
379 static const unsigned int CHUNK_SIZE = 3;
380
381 if (TestCommWorld->rank() == 0)
382 {
383 src.resize(TestCommWorld->size() * CHUNK_SIZE);
384 for (std::size_t i=0; i<src.size(); i++)
385 src[i] = i;
386 }
387
388 TestCommWorld->scatter(src, dest);
389
390 for (unsigned int i=0; i<CHUNK_SIZE; i++)
391 CPPUNIT_ASSERT_EQUAL( TestCommWorld->rank() * CHUNK_SIZE + i, dest[i] );
392 }
393
394 // Test Vector Scatter (jagged chunks)
395 {
396 std::vector<unsigned int> src;
397 std::vector<unsigned int> dest;
398 std::vector<int> counts;
399
400 if (TestCommWorld->rank() == 0)
401 {
402 // Give each processor "rank" number of items ( Sum i=1..n == (n * (n + 1))/2 )
403 src.resize((TestCommWorld->size() * (TestCommWorld->size() + 1)) / 2);
404 counts.resize(TestCommWorld->size());
405
406 for (std::size_t i=0; i<src.size(); i++)
407 src[i] = i;
408 for (unsigned int i=0; i<TestCommWorld->size(); i++)
409 counts[i] = static_cast<int>(i+1);
410 }
411
412 TestCommWorld->scatter(src, counts, dest);
413
414 unsigned int start_value = (TestCommWorld->rank() * (TestCommWorld->rank() + 1)) / 2;
415 for (unsigned int i=0; i<=TestCommWorld->rank(); i++)
416 CPPUNIT_ASSERT_EQUAL( start_value + i, dest[i] );
417 }
418
419 // Test Vector of Vector Scatter
420 {
421 std::vector<std::vector<unsigned int>> src;
422 std::vector<unsigned int> dest;
423
424 if (TestCommWorld->rank() == 0)
425 {
426 // Give each processor "rank" number of items ( Sum i=1..n == (n * (n + 1))/2 )
427 src.resize(TestCommWorld->size());
428 for (std::size_t i=0; i<src.size(); ++i)
429 src[i].resize(i+1);
430
431 unsigned int global_counter = 0;
432 for (std::size_t i=0; i<src.size(); i++)
433 for (std::size_t j=0; j<src[i].size(); j++)
434 src[i][j] = global_counter++;
435 }
436
437 TestCommWorld->scatter(src, dest);
438
439 unsigned int start_value = (TestCommWorld->rank() * (TestCommWorld->rank() + 1)) / 2;
440 for (unsigned int i=0; i<=TestCommWorld->rank(); i++)
441 CPPUNIT_ASSERT_EQUAL( start_value + i, dest[i] );
442 }
443 }
444
445
446
448 {
449 LOG_UNIT_TEST;
450
451 TestCommWorld->barrier();
452 }
453
454
455
456 void testMin ()
457 {
458 LOG_UNIT_TEST;
459
460 unsigned int min = TestCommWorld->rank();
461
462 TestCommWorld->min(min);
463
464 CPPUNIT_ASSERT_EQUAL (min, static_cast<unsigned int>(0));
465 }
466
467
468
469 void testMax ()
470 {
471 LOG_UNIT_TEST;
472
473 processor_id_type max = TestCommWorld->rank();
474
475 TestCommWorld->max(max);
476
477 CPPUNIT_ASSERT_EQUAL (cast_int<processor_id_type>(max+1),
478 cast_int<processor_id_type>(TestCommWorld->size()));
479 }
480
481
482
484 {
485 LOG_UNIT_TEST;
486
487 int min = (TestCommWorld->rank() + 1) % TestCommWorld->size();
488 unsigned int minid = 0;
489
490 TestCommWorld->minloc(min, minid);
491
492 CPPUNIT_ASSERT_EQUAL (min, static_cast<int>(0));
493 CPPUNIT_ASSERT_EQUAL (minid, static_cast<unsigned int>(TestCommWorld->size()-1));
494 }
495
496
497
499 {
500 LOG_UNIT_TEST;
501
502 int max = TestCommWorld->rank();
503 unsigned int maxid = 0;
504
505 TestCommWorld->maxloc(max, maxid);
506
507 CPPUNIT_ASSERT_EQUAL (max+1,
508 cast_int<int>(TestCommWorld->size()));
509 CPPUNIT_ASSERT_EQUAL (maxid, static_cast<unsigned int>(TestCommWorld->size()-1));
510 }
511
512
513
515 {
516 LOG_UNIT_TEST;
517
518 Real min = (TestCommWorld->rank() + 1) % TestCommWorld->size();
519 unsigned int minid = 0;
520
521 TestCommWorld->minloc(min, minid);
522
523 CPPUNIT_ASSERT_EQUAL (min, Real(0));
524 CPPUNIT_ASSERT_EQUAL (minid, static_cast<unsigned int>(TestCommWorld->size()-1));
525 }
526
527
528
530 {
531 LOG_UNIT_TEST;
532
533 Real max = TestCommWorld->rank();
534 unsigned int maxid = 0;
535
536 TestCommWorld->maxloc(max, maxid);
537
538 // Hope nobody uses 1677216 procs with single precision
539 CPPUNIT_ASSERT_EQUAL (max+1, Real(TestCommWorld->size()));
540 CPPUNIT_ASSERT_EQUAL (maxid, static_cast<unsigned int>(TestCommWorld->size()-1));
541 }
542
543
544
546 {
547 LOG_UNIT_TEST;
548
549 double min = std::numeric_limits<double>::infinity();
550
551 TestCommWorld->min(min);
552
553 CPPUNIT_ASSERT_EQUAL (min, std::numeric_limits<double>::infinity());
554
555 min = -std::numeric_limits<double>::infinity();
556
557 TestCommWorld->min(min);
558
559 CPPUNIT_ASSERT_EQUAL (min, -std::numeric_limits<double>::infinity());
560 }
561
562
563
565 {
566 LOG_UNIT_TEST;
567
568 double max = std::numeric_limits<double>::infinity();
569
570 TestCommWorld->max(max);
571
572 CPPUNIT_ASSERT_EQUAL (max, std::numeric_limits<double>::infinity());
573
574 max = -std::numeric_limits<double>::infinity();
575
576 TestCommWorld->max(max);
577
578 CPPUNIT_ASSERT_EQUAL (max, -std::numeric_limits<double>::infinity());
579 }
580
581
582
584 {
585 LOG_UNIT_TEST;
586
587 unsigned int procup = (TestCommWorld->rank() + 1) %
588 TestCommWorld->size();
589 unsigned int procdown = (TestCommWorld->size() +
590 TestCommWorld->rank() - 1) %
591 TestCommWorld->size();
592
593 std::vector<unsigned int> src_val(3), recv_val(3);
594
595 src_val[0] = 0;
596 src_val[1] = 1;
597 src_val[2] = 2;
598
599 Parallel::Request request;
600
601 if (TestCommWorld->size() > 1)
602 {
603 // Default communication
605
606 TestCommWorld->send (procup,
607 src_val,
608 request);
609
610 TestCommWorld->receive (procdown,
611 recv_val);
612
613 Parallel::wait (request);
614
615 CPPUNIT_ASSERT_EQUAL ( src_val.size() , recv_val.size() );
616
617 for (std::size_t i=0; i<src_val.size(); i++)
618 CPPUNIT_ASSERT_EQUAL( src_val[i] , recv_val[i] );
619
620
621 // Synchronous communication
623 std::fill (recv_val.begin(), recv_val.end(), 0);
624
625 TestCommWorld->send (procup,
626 src_val,
627 request);
628
629 TestCommWorld->receive (procdown,
630 recv_val);
631
632 Parallel::wait (request);
633
634 CPPUNIT_ASSERT_EQUAL ( src_val.size() , recv_val.size() );
635
636 for (std::size_t i=0; i<src_val.size(); i++)
637 CPPUNIT_ASSERT_EQUAL( src_val[i] , recv_val[i] );
638
639 // Restore default communication
641 }
642 }
643
644
645
647 {
648 LOG_UNIT_TEST;
649
650 unsigned int procup = (TestCommWorld->rank() + 1) %
651 TestCommWorld->size();
652 unsigned int procdown = (TestCommWorld->size() +
653 TestCommWorld->rank() - 1) %
654 TestCommWorld->size();
655
656 std::vector<unsigned int> src_val(3), recv_val(3);
657
658 src_val[0] = 0;
659 src_val[1] = 1;
660 src_val[2] = 2;
661
662 Parallel::Request request;
663
664 if (TestCommWorld->size() > 1)
665 {
666 // Default communication
668
669 TestCommWorld->receive (procdown,
670 recv_val,
671 request);
672
673 TestCommWorld->send (procup,
674 src_val);
675
676 Parallel::wait (request);
677
678 CPPUNIT_ASSERT_EQUAL ( src_val.size() , recv_val.size() );
679
680 for (std::size_t i=0; i<src_val.size(); i++)
681 CPPUNIT_ASSERT_EQUAL( src_val[i] , recv_val[i] );
682
683 // Synchronous communication
685 std::fill (recv_val.begin(), recv_val.end(), 0);
686
687
688 TestCommWorld->receive (procdown,
689 recv_val,
690 request);
691
692 TestCommWorld->send (procup,
693 src_val);
694
695 Parallel::wait (request);
696
697 CPPUNIT_ASSERT_EQUAL ( src_val.size() , recv_val.size() );
698
699 for (std::size_t i=0; i<src_val.size(); i++)
700 CPPUNIT_ASSERT_EQUAL( src_val[i] , recv_val[i] );
701
702 // Restore default communication
704 }
705 }
706
707
709 {
710 LOG_UNIT_TEST;
711
712 unsigned int procup = (TestCommWorld->rank() + 1) %
713 TestCommWorld->size();
714 unsigned int procdown = (TestCommWorld->size() +
715 TestCommWorld->rank() - 1) %
716 TestCommWorld->size();
717
718 std::set<unsigned int> src_val, recv_val;
719
720 src_val.insert(4); // Chosen by fair dice roll
721 src_val.insert(42);
722 src_val.insert(1337);
723
724 Parallel::Request request;
725
726 if (TestCommWorld->size() > 1)
727 {
728 TestCommWorld->send (procup, src_val, request);
729
730 TestCommWorld->receive (procdown,
731 recv_val);
732
733 CPPUNIT_ASSERT_EQUAL ( src_val.size() , recv_val.size() );
734
735 for (std::set<unsigned int>::const_iterator
736 it = src_val.begin(), end = src_val.end(); it != end;
737 ++it)
738 CPPUNIT_ASSERT ( recv_val.count(*it) );
739
740 Parallel::wait (request);
741
742 recv_val.clear();
743 }
744 }
745
746
747
749 {
750 LOG_UNIT_TEST;
751
752 unsigned int procup = (TestCommWorld->rank() + 1) %
753 TestCommWorld->size();
754 unsigned int procdown = (TestCommWorld->size() +
755 TestCommWorld->rank() - 1) %
756 TestCommWorld->size();
757
758 std::vector<std::vector<unsigned int> > src_val(3), recv_val;
759
760 src_val[0].push_back(4); // Chosen by fair dice roll
761 src_val[2].push_back(procup);
762 src_val[2].push_back(TestCommWorld->rank());
763
764 Parallel::Request request;
765
766 if (TestCommWorld->size() > 1)
767 {
768 TestCommWorld->send (procup, src_val, request);
769
770 TestCommWorld->receive (procdown,
771 recv_val);
772
773 CPPUNIT_ASSERT_EQUAL ( src_val.size() , recv_val.size() );
774
775 for (std::size_t i = 0; i != 3; ++i)
776 CPPUNIT_ASSERT_EQUAL ( src_val[i].size(), recv_val[i].size() );
777
778 CPPUNIT_ASSERT_EQUAL ( recv_val[0][0], static_cast<unsigned int> (4) );
779 CPPUNIT_ASSERT_EQUAL ( recv_val[2][0], static_cast<unsigned int> (TestCommWorld->rank()) );
780 CPPUNIT_ASSERT_EQUAL ( recv_val[2][1], procdown );
781
782 Parallel::wait (request);
783
784 recv_val.clear();
785 }
786 }
787
788
790 {
791 LOG_UNIT_TEST;
792
793 unsigned int procup = (TestCommWorld->rank() + 1) %
794 TestCommWorld->size();
795 unsigned int procdown = (TestCommWorld->size() +
796 TestCommWorld->rank() - 1) %
797 TestCommWorld->size();
798
799 // Any odd processor out does nothing
800 if ((TestCommWorld->size() % 2) && procup == 0)
801 return;
802
803 std::vector<std::vector<unsigned int> > src_val(3), recv_val;
804
805 src_val[0].push_back(4); // Chosen by fair dice roll
806 src_val[2].push_back(procup);
807 src_val[2].push_back(TestCommWorld->rank());
808
809 // Other even numbered processors send
810 if (TestCommWorld->rank() % 2 == 0)
811 TestCommWorld->send (procup, src_val);
812 // Other odd numbered processors receive
813 else
814 {
815 TestCommWorld->receive (procdown,
816 recv_val);
817
818 CPPUNIT_ASSERT_EQUAL ( src_val.size() , recv_val.size() );
819
820 for (std::size_t i = 0; i != 3; ++i)
821 CPPUNIT_ASSERT_EQUAL ( src_val[i].size(), recv_val[i].size() );
822
823 CPPUNIT_ASSERT_EQUAL ( recv_val[0][0], static_cast<unsigned int> (4) );
824 CPPUNIT_ASSERT_EQUAL ( recv_val[2][0], static_cast<unsigned int> (TestCommWorld->rank()) );
825 CPPUNIT_ASSERT_EQUAL ( recv_val[2][1], procdown );
826
827 recv_val.clear();
828 }
829 }
830
831
832
834 {
835 LOG_UNIT_TEST;
836
837 double inf = std::numeric_limits<double>::infinity();
838
839 double *infptr = TestCommWorld->rank()%2 ? NULL : &inf;
840
841 CPPUNIT_ASSERT (TestCommWorld->semiverify(infptr));
842
843 inf = -std::numeric_limits<double>::infinity();
844
845 CPPUNIT_ASSERT (TestCommWorld->semiverify(infptr));
846 }
847
848
849 void testSplit ()
850 {
851 LOG_UNIT_TEST;
852
854 unsigned int rank = TestCommWorld->rank();
855 unsigned int color = rank % 2;
856 TestCommWorld->split(color, rank, subcomm);
857
858 CPPUNIT_ASSERT(subcomm.size() >= 1);
859 CPPUNIT_ASSERT(subcomm.size() >= TestCommWorld->size() / 2);
860 CPPUNIT_ASSERT(subcomm.size() <= TestCommWorld->size() / 2 + 1);
861 }
862
863
865 {
866 LOG_UNIT_TEST;
867
869 unsigned int rank = TestCommWorld->rank();
870 Parallel::info i = 0;
871 int type = 0;
872#ifdef LIBMESH_HAVE_MPI
873 type = MPI_COMM_TYPE_SHARED;
874 i = MPI_INFO_NULL;
875#endif
876 TestCommWorld->split_by_type(type, rank, i, subcomm);
877
878 CPPUNIT_ASSERT(subcomm.size() >= 1);
879 CPPUNIT_ASSERT(subcomm.size() <= TestCommWorld->size());
880 }
881
883 {
884 LOG_UNIT_TEST;
885
886 const unsigned int requested_threads =
887 (libMesh::n_threads() > 2) ? 2u : 1u;
888 std::vector<unsigned int> values(3);
889 std::iota(values.begin(), values.end(), 0u);
890 const TestRange range(values.cbegin(), values.cend(),
891 /* grainsize */ 1);
892 VisitTracker tracker;
893
894 Threads::parallel_for(range, ForBody(tracker), requested_threads);
895
896 assert_tracker_matches_values(tracker, values);
897
898#ifdef LIBMESH_HAVE_PTHREAD
899 CPPUNIT_ASSERT_EQUAL(requested_threads,
900 tracker.invocations.load(std::memory_order_relaxed));
901 CPPUNIT_ASSERT(tracker.unique_thread_count() <= requested_threads);
902#endif
903 }
904
906 {
907 LOG_UNIT_TEST;
908
909 const unsigned int requested_threads =
910 (libMesh::n_threads() > 2) ? 2u : 1u;
911 std::vector<unsigned int> values(3);
912 std::iota(values.begin(), values.end(), 0u);
913 const TestRange range(values.cbegin(), values.cend(),
914 /* grainsize */ 1);
915 auto tracker = std::make_shared<VisitTracker>();
916 ReduceBody body(tracker);
917
918 Threads::parallel_reduce(range, body, requested_threads);
919
920 assert_tracker_matches_values(*tracker, values);
921 CPPUNIT_ASSERT_EQUAL(static_cast<unsigned int>(values.size()), body.value_count);
922 CPPUNIT_ASSERT_EQUAL(tracker->value_sum.load(std::memory_order_relaxed), body.value_sum);
923 CPPUNIT_ASSERT_EQUAL(tracker->value_sum_sq.load(std::memory_order_relaxed), body.value_sum_sq);
924
925#ifdef LIBMESH_HAVE_PTHREAD
926 CPPUNIT_ASSERT_EQUAL(requested_threads,
927 tracker->invocations.load(std::memory_order_relaxed));
928 CPPUNIT_ASSERT(tracker->unique_thread_count() <= requested_threads);
929#endif
930 }
931
932#if defined(LIBMESH_ENABLE_EXCEPTIONS)
934 {
935 LOG_UNIT_TEST;
936
937 std::vector<unsigned int> values(3);
938 std::iota(values.begin(), values.end(), 0u);
939 const TestRange range(values.cbegin(), values.cend());
940 VisitTracker for_tracker;
941 auto reduce_tracker = std::make_shared<VisitTracker>();
942 ReduceBody reduce_body(reduce_tracker);
943
944 CPPUNIT_ASSERT_THROW(Threads::parallel_for(range,
945 ForBody(for_tracker),
946 libMesh::n_threads() + 1u),
948 CPPUNIT_ASSERT_THROW(Threads::parallel_reduce(range,
949 reduce_body,
950 libMesh::n_threads() + 1u),
952 }
953#endif
954};
955
void testAllGatherVectorString()
void testAllGatherEmptyVectorString()
CPPUNIT_TEST(testBroadcastNestedType)
CPPUNIT_TEST(testScatter)
CPPUNIT_TEST_SUITE_END()
CPPUNIT_TEST(testAllGather)
CPPUNIT_TEST(testMaxloc)
CPPUNIT_TEST(testMinlocReal)
CPPUNIT_TEST(testAllGatherVectorString)
void testAllGatherHalfEmptyVectorString()
CPPUNIT_TEST(testMinloc)
void testRecvIsendVecVecs()
void testInfinityMax()
CPPUNIT_TEST(testMin)
void testAllGatherString()
CPPUNIT_TEST(testInfinityMin)
void testGatherString()
CPPUNIT_TEST(testAllGatherHalfEmptyVectorString)
void testParallelReduceThreadSubset()
CPPUNIT_TEST(testSemiVerify)
void testMinlocReal()
void testParallelForThreadSubset()
CPPUNIT_TEST(testRecvIsendVecVecs)
CPPUNIT_TEST(testSendRecvVecVecs)
CPPUNIT_TEST(testMax)
void testBroadcastNestedType()
CPPUNIT_TEST(testGather)
CPPUNIT_TEST(testInfinityMax)
CPPUNIT_TEST(testIrecvSend)
CPPUNIT_TEST(testAllGatherEmptyVectorString)
CPPUNIT_TEST(testGatherString)
void testInfinityMin()
CPPUNIT_TEST(testRecvIsendSets)
void testSendRecvVecVecs()
CPPUNIT_TEST(testAllGatherString)
CPPUNIT_TEST(testIsendRecv)
CPPUNIT_TEST(testRequestedThreadCountExceedsGlobal)
void testSemiVerify()
CPPUNIT_TEST(testParallelForThreadSubset)
void testMaxlocReal()
CPPUNIT_TEST(testBroadcast)
std::vector< std::string > _number
void testIrecvSend()
void testRequestedThreadCountExceedsGlobal()
CPPUNIT_TEST(testParallelReduceThreadSubset)
void testSplitByType()
CPPUNIT_TEST(testMaxlocReal)
void testIsendRecv()
void testAllGather()
LIBMESH_CPPUNIT_TEST_SUITE(ParallelTest)
void testRecvIsendSets()
CPPUNIT_TEST(testSplit)
void testBroadcast()
CPPUNIT_TEST(testBarrier)
processor_id_type size() const
A class to represent the internal "this should never happen" errors, to be thrown by "libmesh_error()...
The StoredRange class defines a contiguous, divisible set of objects.
Dummy "splitting object" used to distinguish splitting constructors from copy constructors.
Communicator * TestCommWorld
MPI_Info info
void parallel_reduce(const Range &range, Body &body, unsigned int n_threads=libMesh::n_threads())
Execute the provided reduction operation in parallel on the specified range.
void parallel_for(const Range &range, const Body &body, unsigned int n_threads=libMesh::n_threads())
Execute the provided function object in parallel on the specified range.
The libMesh namespace provides an interface to certain functionality in the library.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
uint8_t processor_id_type
Definition id_types.h:104
unsigned int n_threads()
CPPUNIT_TEST_SUITE_REGISTRATION(ParallelTest)
static const bool value
Definition xdr_io.C:55