]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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> | |
7c673cae FG |
13 | #include <algorithm> |
14 | #include "gps_position.hpp" | |
15 | #include <boost/serialization/string.hpp> | |
16 | #include <boost/serialization/list.hpp> | |
92f5a8d4 TL |
17 | //#include "debugger.cpp" |
18 | ||
19 | #define BOOST_TEST_MODULE mpi_reduce_ring | |
20 | #include <boost/test/included/unit_test.hpp> | |
7c673cae FG |
21 | |
22 | using boost::mpi::communicator; | |
23 | using boost::mpi::status; | |
24 | ||
25 | template<typename T> | |
26 | void | |
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 | |
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 | ||
92f5a8d4 | 90 | BOOST_AUTO_TEST_CASE(ring) |
7c673cae | 91 | { |
92f5a8d4 | 92 | boost::mpi::environment env; |
7c673cae | 93 | communicator comm; |
92f5a8d4 TL |
94 | |
95 | BOOST_TEST_REQUIRE(comm.size() > 1); | |
7c673cae FG |
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); | |
7c673cae | 124 | } |