libMesh
parallel_test.C
Go to the documentation of this file.
1 // Ignore unused parameter warnings coming from cppunit headers
2 #include <libmesh/ignore_warnings.h>
3 #include <cppunit/extensions/HelperMacros.h>
4 #include <cppunit/TestCase.h>
5 #include <libmesh/restore_warnings.h>
6 
7 #include <libmesh/parallel.h>
8 
9 #include "test_comm.h"
10 
11 // THE CPPUNIT_TEST_SUITE_END macro expands to code that involves
12 // std::auto_ptr, which in turn produces -Wdeprecated-declarations
13 // warnings. These can be ignored in GCC as long as we wrap the
14 // offending code in appropriate pragmas. We can't get away with a
15 // single ignore_warnings.h inclusion at the beginning of this file,
16 // since the libmesh headers pull in a restore_warnings.h at some
17 // point. We also don't bother restoring warnings at the end of this
18 // file since it's not a header.
19 #include <libmesh/ignore_warnings.h>
20 
21 using namespace libMesh;
22 
23 class ParallelTest : public CppUnit::TestCase {
24 public:
25  CPPUNIT_TEST_SUITE( ParallelTest );
26 
27  CPPUNIT_TEST( testGather );
28  CPPUNIT_TEST( testAllGather );
29  CPPUNIT_TEST( testGatherString );
30  CPPUNIT_TEST( testAllGatherString );
31  CPPUNIT_TEST( testAllGatherVectorString );
32  CPPUNIT_TEST( testAllGatherEmptyVectorString );
33  CPPUNIT_TEST( testAllGatherHalfEmptyVectorString );
34  CPPUNIT_TEST( testBroadcast );
35  CPPUNIT_TEST( testScatter );
36  CPPUNIT_TEST( testBarrier );
37  CPPUNIT_TEST( testMin );
38  CPPUNIT_TEST( testMax );
39  CPPUNIT_TEST( testInfinityMin );
40  CPPUNIT_TEST( testInfinityMax );
41  CPPUNIT_TEST( testIsendRecv );
42  CPPUNIT_TEST( testIrecvSend );
43  CPPUNIT_TEST( testRecvIsendSets );
44  CPPUNIT_TEST( testSemiVerify );
45  CPPUNIT_TEST( testSplit );
46 
47  CPPUNIT_TEST_SUITE_END();
48 
49 private:
50  std::vector<std::string> _number;
51 
52 public:
53  void setUp()
54  {
55  _number.resize(10);
56  _number[0] = "Zero";
57  _number[1] = "One";
58  _number[2] = "Two";
59  _number[3] = "Three";
60  _number[4] = "Four";
61  _number[5] = "Five";
62  _number[6] = "Six";
63  _number[7] = "Seven";
64  _number[8] = "Eight";
65  _number[9] = "Nine";
66  }
67 
68  void tearDown()
69  {}
70 
71 
72 
73  void testGather()
74  {
75  std::vector<processor_id_type> vals;
76  TestCommWorld->gather(0,cast_int<processor_id_type>(TestCommWorld->rank()),vals);
77 
78  if (TestCommWorld->rank() == 0)
79  for (processor_id_type i=0; i<vals.size(); i++)
80  CPPUNIT_ASSERT_EQUAL( i , vals[i] );
81  }
82 
83 
84 
86  {
87  std::vector<std::string> vals;
88  TestCommWorld->gather(0, "Processor" + _number[TestCommWorld->rank() % 10], vals);
89 
90  if (TestCommWorld->rank() == 0)
91  for (processor_id_type i=0; i<vals.size(); i++)
92  CPPUNIT_ASSERT_EQUAL( "Processor" + _number[i % 10] , vals[i] );
93  }
94 
95 
96 
98  {
99  std::vector<processor_id_type> vals;
100  TestCommWorld->allgather(cast_int<processor_id_type>(TestCommWorld->rank()),vals);
101 
102  for (processor_id_type i=0; i<vals.size(); i++)
103  CPPUNIT_ASSERT_EQUAL( i , vals[i] );
104  }
105 
106 
107 
109  {
110  std::vector<std::string> vals;
111  TestCommWorld->gather(0, "Processor" + _number[TestCommWorld->rank() % 10], vals);
112 
113  for (processor_id_type i=0; i<vals.size(); i++)
114  CPPUNIT_ASSERT_EQUAL( "Processor" + _number[i % 10] , vals[i] );
115  }
116 
117 
118 
120  {
121  std::vector<std::string> vals;
122  vals.push_back("Processor" + _number[TestCommWorld->rank() % 10] + "A");
123  vals.push_back("Processor" + _number[TestCommWorld->rank() % 10] + "B");
124  TestCommWorld->allgather(vals);
125 
126  for (processor_id_type i=0; i<(vals.size()/2); i++)
127  {
128  CPPUNIT_ASSERT_EQUAL( "Processor" + _number[i % 10] + "A" , vals[2*i] );
129  CPPUNIT_ASSERT_EQUAL( "Processor" + _number[i % 10] + "B" , vals[2*i+1] );
130  }
131  }
132 
133 
134 
136  {
137  std::vector<std::string> vals;
138  TestCommWorld->allgather(vals);
139 
140  CPPUNIT_ASSERT( vals.empty() );
141  }
142 
143 
144 
146  {
147  std::vector<std::string> vals;
148 
149  if (!TestCommWorld->rank())
150  vals.push_back("Proc 0 only");
151 
152  TestCommWorld->allgather(vals);
153 
154  CPPUNIT_ASSERT_EQUAL( vals[0], std::string("Proc 0 only") );
155  }
156 
157 
158 
160  {
161  std::vector<unsigned int> src(3), dest(3);
162 
163  src[0]=0;
164  src[1]=1;
165  src[2]=2;
166 
167  if (TestCommWorld->rank() == 0)
168  dest = src;
169 
170  TestCommWorld->broadcast(dest);
171 
172  for (std::size_t i=0; i<src.size(); i++)
173  CPPUNIT_ASSERT_EQUAL( src[i] , dest[i] );
174  }
175 
176 
177 
178  void testScatter()
179  {
180  // Test Scalar scatter
181  {
182  std::vector<unsigned int> src;
183  unsigned int dest;
184 
185  if (TestCommWorld->rank() == 0)
186  {
187  src.resize(TestCommWorld->size());
188  for (std::size_t i=0; i<src.size(); i++)
189  src[i] = i;
190  }
191 
192  TestCommWorld->scatter(src, dest);
193 
194  CPPUNIT_ASSERT_EQUAL( TestCommWorld->rank(), dest );
195  }
196 
197  // Test Vector Scatter (equal-sized chunks)
198  {
199  std::vector<unsigned int> src;
200  std::vector<unsigned int> dest;
201  static const unsigned int CHUNK_SIZE = 3;
202 
203  if (TestCommWorld->rank() == 0)
204  {
205  src.resize(TestCommWorld->size() * CHUNK_SIZE);
206  for (std::size_t i=0; i<src.size(); i++)
207  src[i] = i;
208  }
209 
210  TestCommWorld->scatter(src, dest);
211 
212  for (unsigned int i=0; i<CHUNK_SIZE; i++)
213  CPPUNIT_ASSERT_EQUAL( TestCommWorld->rank() * CHUNK_SIZE + i, dest[i] );
214  }
215 
216  // Test Vector Scatter (jagged chunks)
217  {
218  std::vector<unsigned int> src;
219  std::vector<unsigned int> dest;
220  std::vector<int> counts;
221 
222  if (TestCommWorld->rank() == 0)
223  {
224  // Give each processor "rank" number of items ( Sum i=1..n == (n * (n + 1))/2 )
225  src.resize((TestCommWorld->size() * (TestCommWorld->size() + 1)) / 2);
226  counts.resize(TestCommWorld->size());
227 
228  for (std::size_t i=0; i<src.size(); i++)
229  src[i] = i;
230  for (unsigned int i=0; i<TestCommWorld->size(); i++)
231  counts[i] = static_cast<int>(i+1);
232  }
233 
234  TestCommWorld->scatter(src, counts, dest);
235 
236  unsigned int start_value = (TestCommWorld->rank() * (TestCommWorld->rank() + 1)) / 2;
237  for (unsigned int i=0; i<=TestCommWorld->rank(); i++)
238  CPPUNIT_ASSERT_EQUAL( start_value + i, dest[i] );
239  }
240 
241  // Test Vector of Vector Scatter
242  {
243  std::vector<std::vector<unsigned int>> src;
244  std::vector<unsigned int> dest;
245 
246  if (TestCommWorld->rank() == 0)
247  {
248  // Give each processor "rank" number of items ( Sum i=1..n == (n * (n + 1))/2 )
249  src.resize(TestCommWorld->size());
250  for (std::size_t i=0; i<src.size(); ++i)
251  src[i].resize(i+1);
252 
253  unsigned int global_counter = 0;
254  for (std::size_t i=0; i<src.size(); i++)
255  for (std::size_t j=0; j<src[i].size(); j++)
256  src[i][j] = global_counter++;
257  }
258 
259  TestCommWorld->scatter(src, dest);
260 
261  unsigned int start_value = (TestCommWorld->rank() * (TestCommWorld->rank() + 1)) / 2;
262  for (unsigned int i=0; i<=TestCommWorld->rank(); i++)
263  CPPUNIT_ASSERT_EQUAL( start_value + i, dest[i] );
264  }
265  }
266 
267 
268 
269  void testBarrier()
270  {
272  }
273 
274 
275 
276  void testMin ()
277  {
278  unsigned int min = TestCommWorld->rank();
279 
280  TestCommWorld->min(min);
281 
282  CPPUNIT_ASSERT_EQUAL (min, static_cast<unsigned int>(0));
283  }
284 
285 
286 
287  void testMax ()
288  {
290 
291  TestCommWorld->max(max);
292 
293  CPPUNIT_ASSERT_EQUAL (cast_int<processor_id_type>(max+1),
294  cast_int<processor_id_type>(TestCommWorld->size()));
295  }
296 
297 
298 
300  {
301  double min = std::numeric_limits<double>::infinity();
302 
303  TestCommWorld->min(min);
304 
305  CPPUNIT_ASSERT_EQUAL (min, std::numeric_limits<double>::infinity());
306 
307  min = -std::numeric_limits<double>::infinity();
308 
309  TestCommWorld->min(min);
310 
311  CPPUNIT_ASSERT_EQUAL (min, -std::numeric_limits<double>::infinity());
312  }
313 
314 
315 
317  {
318  double max = std::numeric_limits<double>::infinity();
319 
320  TestCommWorld->max(max);
321 
322  CPPUNIT_ASSERT_EQUAL (max, std::numeric_limits<double>::infinity());
323 
324  max = -std::numeric_limits<double>::infinity();
325 
326  TestCommWorld->max(max);
327 
328  CPPUNIT_ASSERT_EQUAL (max, -std::numeric_limits<double>::infinity());
329  }
330 
331 
332 
334  {
335  unsigned int procup = (TestCommWorld->rank() + 1) %
336  TestCommWorld->size();
337  unsigned int procdown = (TestCommWorld->size() +
338  TestCommWorld->rank() - 1) %
339  TestCommWorld->size();
340 
341  std::vector<unsigned int> src_val(3), recv_val(3);
342 
343  src_val[0] = 0;
344  src_val[1] = 1;
345  src_val[2] = 2;
346 
348 
349  if (TestCommWorld->size() > 1)
350  {
351  // Default communication
353 
354  TestCommWorld->send (procup,
355  src_val,
356  request);
357 
358  TestCommWorld->receive (procdown,
359  recv_val);
360 
361  Parallel::wait (request);
362 
363  CPPUNIT_ASSERT_EQUAL ( src_val.size() , recv_val.size() );
364 
365  for (std::size_t i=0; i<src_val.size(); i++)
366  CPPUNIT_ASSERT_EQUAL( src_val[i] , recv_val[i] );
367 
368 
369  // Synchronous communication
371  std::fill (recv_val.begin(), recv_val.end(), 0);
372 
373  TestCommWorld->send (procup,
374  src_val,
375  request);
376 
377  TestCommWorld->receive (procdown,
378  recv_val);
379 
380  Parallel::wait (request);
381 
382  CPPUNIT_ASSERT_EQUAL ( src_val.size() , recv_val.size() );
383 
384  for (std::size_t i=0; i<src_val.size(); i++)
385  CPPUNIT_ASSERT_EQUAL( src_val[i] , recv_val[i] );
386 
387  // Restore default communication
389  }
390  }
391 
392 
393 
395  {
396  unsigned int procup = (TestCommWorld->rank() + 1) %
397  TestCommWorld->size();
398  unsigned int procdown = (TestCommWorld->size() +
399  TestCommWorld->rank() - 1) %
400  TestCommWorld->size();
401 
402  std::vector<unsigned int> src_val(3), recv_val(3);
403 
404  src_val[0] = 0;
405  src_val[1] = 1;
406  src_val[2] = 2;
407 
409 
410  if (TestCommWorld->size() > 1)
411  {
412  // Default communication
414 
415  TestCommWorld->receive (procdown,
416  recv_val,
417  request);
418 
419  TestCommWorld->send (procup,
420  src_val);
421 
422  Parallel::wait (request);
423 
424  CPPUNIT_ASSERT_EQUAL ( src_val.size() , recv_val.size() );
425 
426  for (std::size_t i=0; i<src_val.size(); i++)
427  CPPUNIT_ASSERT_EQUAL( src_val[i] , recv_val[i] );
428 
429  // Synchronous communication
431  std::fill (recv_val.begin(), recv_val.end(), 0);
432 
433 
434  TestCommWorld->receive (procdown,
435  recv_val,
436  request);
437 
438  TestCommWorld->send (procup,
439  src_val);
440 
441  Parallel::wait (request);
442 
443  CPPUNIT_ASSERT_EQUAL ( src_val.size() , recv_val.size() );
444 
445  for (std::size_t i=0; i<src_val.size(); i++)
446  CPPUNIT_ASSERT_EQUAL( src_val[i] , recv_val[i] );
447 
448  // Restore default communication
450  }
451  }
452 
453 
455  {
456  unsigned int procup = (TestCommWorld->rank() + 1) %
457  TestCommWorld->size();
458  unsigned int procdown = (TestCommWorld->size() +
459  TestCommWorld->rank() - 1) %
460  TestCommWorld->size();
461 
462  std::set<unsigned int> src_val, recv_val;
463 
464  src_val.insert(4); // Chosen by fair dice roll
465  src_val.insert(42);
466  src_val.insert(1337);
467 
469 
470  if (TestCommWorld->size() > 1)
471  {
472  TestCommWorld->send (procup, src_val, request);
473 
474  TestCommWorld->receive (procdown,
475  recv_val);
476 
477  CPPUNIT_ASSERT_EQUAL ( src_val.size() , recv_val.size() );
478 
479  for (std::set<unsigned int>::const_iterator
480  it = src_val.begin(), end = src_val.end(); it != end;
481  ++it)
482  CPPUNIT_ASSERT ( recv_val.count(*it) );
483 
484  Parallel::wait (request);
485 
486  recv_val.clear();
487  }
488  }
489 
490 
491 
493  {
494  double inf = std::numeric_limits<double>::infinity();
495 
496  double *infptr = TestCommWorld->rank()%2 ? NULL : &inf;
497 
498  CPPUNIT_ASSERT (TestCommWorld->semiverify(infptr));
499 
500  inf = -std::numeric_limits<double>::infinity();
501 
502  CPPUNIT_ASSERT (TestCommWorld->semiverify(infptr));
503  }
504 
505 
506  void testSplit ()
507  {
508  Parallel::Communicator subcomm;
509  unsigned int rank = TestCommWorld->rank();
510  unsigned int color = rank % 2;
511  TestCommWorld->split(color, rank, subcomm);
512  }
513 
514 
515 };
516 
void scatter(const std::vector< T > &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 testAllGatherHalfEmptyVectorString()
Status wait(Request &r)
Wait for a non-blocking send or receive to finish.
Definition: parallel.h:565
void testIsendRecv()
void testAllGatherEmptyVectorString()
void testBarrier()
Encapsulates the MPI_Comm object.
Definition: parallel.h:657
bool semiverify(const T *r) const
Verify that a local pointer points to the same value on all processors where it is not NULL...
unsigned int size() const
Definition: parallel.h:726
void max(T &r) const
Take a local variable and replace it with the maximum of it&#39;s values on all processors.
libMesh::Parallel::Communicator * TestCommWorld
Definition: driver.C:28
void min(T &r) const
Take a local variable and replace it with the minimum of it&#39;s values on all processors.
void tearDown()
Definition: parallel_test.C:68
uint8_t processor_id_type
Definition: id_types.h:99
MPI_Request request
Request object for non-blocking I/O.
Definition: parallel.h:171
IterBase * end
Also have a polymorphic pointer to the end object, this prevents iterating past the end...
void send_mode(const SendMode sm)
Explicitly sets the SendMode type used for send operations.
Definition: parallel.h:761
The libMesh namespace provides an interface to certain functionality in the library.
void testBroadcast()
long double max(long double a, double b)
void testIrecvSend()
void testSplit()
void testAllGatherString()
void testGatherString()
Definition: parallel_test.C:85
void testScatter()
void testAllGatherVectorString()
void testGather()
Definition: parallel_test.C:73
void barrier() const
Pause execution until all processors reach a certain point.
void testRecvIsendSets()
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 broadcast(T &data, const unsigned int root_id=0) const
Take a local value and broadcast it to all processors.
void testSemiVerify()
void split(int color, int key, Communicator &target) const
void testInfinityMax()
Encapsulates the MPI_Request.
Definition: parallel.h:517
void gather(const unsigned int root_id, const T &send, std::vector< T > &recv) const
Take a vector of length comm.size(), and on processor root_id fill in recv[processor_id] = the value ...
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.
unsigned int rank() const
Definition: parallel.h:724
CPPUNIT_TEST_SUITE_REGISTRATION(ParallelTest)
void testInfinityMin()
long double min(long double a, double b)
void testAllGather()
Definition: parallel_test.C:97
std::vector< std::string > _number
Definition: parallel_test.C:50
void allgather(const T &send, std::vector< T > &recv) const
Take a vector of length this->size(), and fill in recv[processor_id] = the value of send on that proc...