1 // Copyright (C) 2006 Douglas Gregor.
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)
7 // A test of the nonblocking point-to-point operations.
8 #include <boost/mpi/nonblocking.hpp>
9 #include <boost/mpi/communicator.hpp>
10 #include <boost/mpi/environment.hpp>
11 #include <boost/test/minimal.hpp>
12 #include "gps_position.hpp"
13 #include <boost/lexical_cast.hpp>
14 #include <boost/serialization/string.hpp>
15 #include <boost/serialization/list.hpp>
19 using boost::mpi::communicator;
20 using boost::mpi::request;
21 using boost::mpi::status;
24 mk_wait_any, mk_test_any, mk_wait_all, mk_wait_all_keep,
25 mk_test_all, mk_test_all_keep, mk_wait_some, mk_wait_some_keep,
26 mk_test_some, mk_test_some_keep,
27 mk_all, // use to run all of the different methods
28 mk_all_except_test_all // use for serialized types
31 static const char* method_kind_names[mk_all] = {
35 "wait_all (keep results)",
37 "test_all (keep results)",
39 "wait_some (keep results)",
41 "test_some (keep results)"
47 nonblocking_test(const communicator& comm, const T* values, int num_values,
48 const char* kind, method_kind method = mk_all)
50 using boost::mpi::wait_any;
51 using boost::mpi::test_any;
52 using boost::mpi::wait_all;
53 using boost::mpi::test_all;
54 using boost::mpi::wait_some;
55 using boost::mpi::test_some;
57 if (method == mk_all || method == mk_all_except_test_all) {
58 nonblocking_test(comm, values, num_values, kind, mk_wait_any);
59 nonblocking_test(comm, values, num_values, kind, mk_test_any);
60 nonblocking_test(comm, values, num_values, kind, mk_wait_all);
61 nonblocking_test(comm, values, num_values, kind, mk_wait_all_keep);
62 if (method == mk_all) {
63 nonblocking_test(comm, values, num_values, kind, mk_test_all);
64 nonblocking_test(comm, values, num_values, kind, mk_test_all_keep);
66 nonblocking_test(comm, values, num_values, kind, mk_wait_some);
67 nonblocking_test(comm, values, num_values, kind, mk_wait_some_keep);
68 nonblocking_test(comm, values, num_values, kind, mk_test_some);
69 nonblocking_test(comm, values, num_values, kind, mk_test_some_keep);
71 if (comm.rank() == 0) {
72 std::cout << "Testing " << method_kind_names[method]
73 << " with " << kind << "...";
77 typedef std::pair<status, std::vector<request>::iterator>
81 std::vector<T> incoming_values(num_values);
83 std::vector<request> reqs;
84 // Send/receive the first value
85 reqs.push_back(comm.isend((comm.rank() + 1) % comm.size(), 0, values[0]));
86 reqs.push_back(comm.irecv((comm.rank() + comm.size() - 1) % comm.size(),
89 if (method != mk_wait_any && method != mk_test_any) {
91 // We've run into problems here (with 0-length messages) with
92 // LAM/MPI on Mac OS X and x86-86 Linux. Will investigate
93 // further at a later time, but the problem only seems to occur
94 // when using shared memory, not TCP.
96 // Send/receive an empty message
97 reqs.push_back(comm.isend((comm.rank() + 1) % comm.size(), 1));
98 reqs.push_back(comm.irecv((comm.rank() + comm.size() - 1) % comm.size(),
102 // Send/receive an array
103 reqs.push_back(comm.isend((comm.rank() + 1) % comm.size(), 2, values,
105 reqs.push_back(comm.irecv((comm.rank() + comm.size() - 1) % comm.size(),
106 2, &incoming_values.front(), num_values));
111 if (wait_any(reqs.begin(), reqs.end()).second == reqs.begin())
119 boost::optional<status_iterator_pair> result;
121 result = test_any(reqs.begin(), reqs.end());
123 if (result->second == reqs.begin())
131 wait_all(reqs.begin(), reqs.end());
134 case mk_wait_all_keep:
136 std::vector<status> stats;
137 wait_all(reqs.begin(), reqs.end(), std::back_inserter(stats));
142 while (!test_all(reqs.begin(), reqs.end())) { /* Busy wait */ }
145 case mk_test_all_keep:
147 std::vector<status> stats;
148 while (!test_all(reqs.begin(), reqs.end(), std::back_inserter(stats)))
155 std::vector<request>::iterator pos = reqs.end();
157 pos = wait_some(reqs.begin(), pos);
158 } while (pos != reqs.begin());
162 case mk_wait_some_keep:
164 std::vector<status> stats;
165 std::vector<request>::iterator pos = reqs.end();
167 pos = wait_some(reqs.begin(), pos, std::back_inserter(stats)).second;
168 } while (pos != reqs.begin());
174 std::vector<request>::iterator pos = reqs.end();
176 pos = test_some(reqs.begin(), pos);
177 } while (pos != reqs.begin());
181 case mk_test_some_keep:
183 std::vector<status> stats;
184 std::vector<request>::iterator pos = reqs.end();
186 pos = test_some(reqs.begin(), pos, std::back_inserter(stats)).second;
187 } while (pos != reqs.begin());
195 if (comm.rank() == 0) {
198 if (!((incoming_value == values[0])))
201 if (method != mk_wait_any && method != mk_test_any
202 && !std::equal(incoming_values.begin(), incoming_values.end(),
207 std::cout << "OK." << std::endl;
209 std::cerr << "ERROR!" << std::endl;
212 BOOST_CHECK(incoming_value == values[0]);
214 if (method != mk_wait_any && method != mk_test_any)
215 BOOST_CHECK(std::equal(incoming_values.begin(), incoming_values.end(),
220 int test_main(int argc, char* argv[])
222 boost::mpi::environment env(argc, argv);
226 int int_array[3] = {17, 42, 256};
227 nonblocking_test(comm, int_array, 3, "integers");
229 gps_position gps_array[2] = {
230 gps_position(17, 42, .06),
231 gps_position(42, 17, .06)
233 nonblocking_test(comm, gps_array, 2, "gps positions");
235 std::string string_array[2] = { "Hello", "World" };
236 nonblocking_test(comm, string_array, 2, "strings",
237 mk_all_except_test_all);
239 std::list<std::string> lst_of_strings;
240 for (int i = 0; i < comm.size(); ++i)
241 lst_of_strings.push_back(boost::lexical_cast<std::string>(i));
243 nonblocking_test(comm, &lst_of_strings, 1, "list of strings",
244 mk_all_except_test_all);