• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (C) 2005, 2006 Douglas Gregor.
2 
3 // Use, modification and distribution is subject to the Boost Software
4 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
5 // http://www.boost.org/LICENSE_1_0.txt)
6 
7 // A test of the communicator that passes data around a ring and
8 // verifies that the same data makes it all the way. Should test all
9 // of the various kinds of data that can be sent (primitive types, POD
10 // types, serializable objects, etc.)
11 #include <boost/mpi/communicator.hpp>
12 #include <boost/mpi/environment.hpp>
13 #include <algorithm>
14 #include "gps_position.hpp"
15 #include <boost/serialization/string.hpp>
16 #include <boost/serialization/list.hpp>
17 //#include "debugger.cpp"
18 
19 #define BOOST_TEST_MODULE mpi_reduce_ring
20 #include <boost/test/included/unit_test.hpp>
21 
22 using boost::mpi::communicator;
23 using boost::mpi::status;
24 
25 template<typename T>
26 void
ring_test(const communicator & comm,const T & pass_value,const char * kind,int root=0)27 ring_test(const communicator& comm, const T& pass_value, const char* kind,
28           int root = 0)
29 {
30   T transferred_value;
31 
32   int rank = comm.rank();
33   int size = comm.size();
34 
35   if (rank == root) {
36     std::cout << "Passing " << kind << " around a ring from root " << root
37               << "...";
38     comm.send((rank + 1) % size, 0, pass_value);
39     comm.recv((rank + size - 1) % size, 0, transferred_value);
40     BOOST_CHECK(transferred_value == pass_value);
41     if (transferred_value == pass_value) std::cout << " OK." << std::endl;
42   } else {
43     comm.recv((rank + size - 1) % size, 0, transferred_value);
44     BOOST_CHECK(transferred_value == pass_value);
45     comm.send((rank + 1) % size, 0, transferred_value);
46   }
47 
48   (comm.barrier)();
49 }
50 
51 
52 template<typename T>
53 void
ring_array_test(const communicator & comm,const T * pass_values,int n,const char * kind,int root=0)54 ring_array_test(const communicator& comm, const T* pass_values,
55                 int n, const char* kind, int root = 0)
56 {
57   T* transferred_values = new T[n];
58   int rank = comm.rank();
59   int size = comm.size();
60 
61   if (rank == root) {
62 
63     std::cout << "Passing " << kind << " array around a ring from root "
64               << root  << "...";
65     comm.send((rank + 1) % size, 0, pass_values, n);
66     comm.recv((rank + size - 1) % size, 0, transferred_values, n);
67     bool okay = std::equal(pass_values, pass_values + n,
68                            transferred_values);
69     BOOST_CHECK(okay);
70     if (okay) std::cout << " OK." << std::endl;
71   } else {
72     status stat = comm.probe(boost::mpi::any_source, 0);
73     boost::optional<int> num_values = stat.template count<T>();
74     if (boost::mpi::is_mpi_datatype<T>())
75       BOOST_CHECK(num_values && *num_values == n);
76     else
77       BOOST_CHECK(!num_values || *num_values == n);
78     comm.recv(stat.source(), 0, transferred_values, n);
79     BOOST_CHECK(std::equal(pass_values, pass_values + n,
80                            transferred_values));
81     comm.send((rank + 1) % size, 0, transferred_values, n);
82   }
83   (comm.barrier)();
84   delete [] transferred_values;
85 }
86 
87 enum color_t {red, green, blue};
88 BOOST_IS_MPI_DATATYPE(color_t)
89 
BOOST_AUTO_TEST_CASE(ring)90 BOOST_AUTO_TEST_CASE(ring)
91 {
92   boost::mpi::environment env;
93   communicator comm;
94 
95   BOOST_TEST_REQUIRE(comm.size() > 1);
96 
97   // Check transfer of individual objects
98   ring_test(comm, 17, "integers", 0);
99   ring_test(comm, 17, "integers", 1);
100   ring_test(comm, red, "enums", 1);
101   ring_test(comm, red, "enums", 1);
102   ring_test(comm, gps_position(39,16,20.2799), "GPS positions", 0);
103   ring_test(comm, gps_position(26,25,30.0), "GPS positions", 1);
104   ring_test(comm, std::string("Rosie"), "string", 0);
105 
106   std::list<std::string> strings;
107   strings.push_back("Hello");
108   strings.push_back("MPI");
109   strings.push_back("World");
110   ring_test(comm, strings, "list of strings", 1);
111 
112   // Check transfer of arrays
113   int int_array[2] = { 17, 42 };
114   ring_array_test(comm, int_array, 2, "integer", 1);
115   gps_position gps_position_array[2] = {
116     gps_position(39,16,20.2799),
117     gps_position(26,25,30.0)
118   };
119   ring_array_test(comm, gps_position_array, 2, "GPS position", 1);
120 
121   std::string string_array[3] = { "Hello", "MPI", "World" };
122   ring_array_test(comm, string_array, 3, "string", 0);
123   ring_array_test(comm, string_array, 3, "string", 1);
124 }
125