]>
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 scatter() and scatterv() collectives. | |
11fdf7f2 | 8 | #include <iterator> |
7c673cae FG |
9 | #include <boost/mpi/collectives/scatter.hpp> |
10 | #include <boost/mpi/collectives/scatterv.hpp> | |
11 | #include <boost/mpi/communicator.hpp> | |
12 | #include <boost/mpi/environment.hpp> | |
13 | #include <boost/test/minimal.hpp> | |
14 | #include "gps_position.hpp" | |
15 | #include <boost/serialization/string.hpp> | |
16 | #include <boost/serialization/list.hpp> | |
17 | #include <boost/iterator/counting_iterator.hpp> | |
18 | #include <boost/lexical_cast.hpp> | |
19 | ||
20 | using boost::mpi::communicator; | |
21 | ||
22 | template<typename Generator> | |
23 | void | |
24 | scatter_test(const communicator& comm, Generator generator, | |
25 | const char* kind, int root = -1) | |
26 | { | |
27 | typedef typename Generator::result_type value_type; | |
28 | ||
29 | if (root == -1) { | |
30 | for (root = 0; root < comm.size(); ++root) | |
31 | scatter_test(comm, generator, kind, root); | |
32 | } else { | |
33 | using boost::mpi::scatter; | |
34 | ||
35 | value_type value; | |
36 | ||
37 | if (comm.rank() == root) { | |
38 | std::vector<value_type> values; | |
39 | ||
40 | for (int p = 0; p < comm.size(); ++p) | |
41 | values.push_back(generator(p)); | |
42 | ||
43 | std::cout << "Scattering " << kind << " from root " | |
44 | << root << "..." << std::endl; | |
45 | ||
46 | scatter(comm, values, value, root); | |
47 | } else { | |
48 | scatter(comm, value, root); | |
49 | } | |
50 | ||
51 | BOOST_CHECK(value == generator(comm.rank())); | |
52 | } | |
53 | ||
54 | (comm.barrier)(); | |
55 | } | |
56 | ||
57 | ||
7c673cae FG |
58 | // |
59 | // Generators to test with scatter/scatterv | |
60 | // | |
61 | struct int_generator | |
62 | { | |
63 | typedef int result_type; | |
64 | ||
65 | int operator()(int p) const { return 17 + p; } | |
66 | }; | |
67 | ||
68 | struct gps_generator | |
69 | { | |
70 | typedef gps_position result_type; | |
71 | ||
72 | gps_position operator()(int p) const | |
73 | { | |
74 | return gps_position(39 + p, 16, 20.2799); | |
75 | } | |
76 | }; | |
77 | ||
78 | struct string_generator | |
79 | { | |
80 | typedef std::string result_type; | |
81 | ||
82 | std::string operator()(int p) const | |
83 | { | |
84 | std::string result = boost::lexical_cast<std::string>(p); | |
85 | result += " rosebud"; | |
86 | if (p != 1) result += 's'; | |
87 | return result; | |
88 | } | |
89 | }; | |
90 | ||
91 | struct string_list_generator | |
92 | { | |
93 | typedef std::list<std::string> result_type; | |
94 | ||
95 | std::list<std::string> operator()(int p) const | |
96 | { | |
97 | std::list<std::string> result; | |
98 | for (int i = 0; i <= p; ++i) { | |
99 | std::string value = boost::lexical_cast<std::string>(i); | |
100 | result.push_back(value); | |
101 | } | |
102 | return result; | |
103 | } | |
104 | }; | |
105 | ||
11fdf7f2 TL |
106 | std::ostream& |
107 | operator<<(std::ostream& out, std::list<std::string> const& l) { | |
108 | out << '['; | |
109 | std::copy(l.begin(), l.end(), std::ostream_iterator<std::string>(out, " ")); | |
110 | out << ']'; | |
111 | return out; | |
112 | } | |
113 | ||
114 | template<typename Generator> | |
115 | void | |
116 | scatterv_test(const communicator& comm, Generator generator, | |
117 | const char* kind, int root = -1) | |
118 | { | |
119 | typedef typename Generator::result_type value_type; | |
120 | ||
121 | if (root == -1) { | |
122 | for (root = 0; root < comm.size(); ++root) | |
123 | scatterv_test(comm, generator, kind, root); | |
124 | } else { | |
125 | using boost::mpi::scatterv; | |
126 | ||
127 | int mysize = comm.rank() + 1; | |
128 | std::vector<value_type> myvalues(mysize); | |
129 | ||
130 | if (comm.rank() == root) { | |
131 | std::vector<value_type> values; | |
132 | std::vector<int> sizes(comm.size()); | |
133 | ||
134 | // process p will receive p+1 identical generator(p) elements | |
135 | for (int p = 0; p < comm.size(); ++p) { | |
136 | for (int i = 0; i < p+1; ++i) | |
137 | values.push_back(generator(p)); | |
138 | sizes[p] = p + 1; | |
139 | } | |
140 | ||
141 | std::cout << "Scatteringv " << kind << " from root " | |
142 | << root << "..." << std::endl; | |
143 | assert(mysize == sizes[comm.rank()]); | |
144 | scatterv(comm, values, sizes, &(myvalues[0]), root); | |
145 | } else { | |
146 | scatterv(comm, &(myvalues[0]), mysize, root); | |
147 | } | |
148 | ||
149 | for (int i = 0; i < mysize; ++i) | |
150 | BOOST_CHECK(myvalues[i] == generator(comm.rank())); | |
151 | } | |
152 | ||
153 | (comm.barrier)(); | |
154 | } | |
155 | ||
156 | ||
7c673cae FG |
157 | int test_main(int argc, char* argv[]) |
158 | { | |
159 | boost::mpi::environment env(argc, argv); | |
160 | ||
161 | communicator comm; | |
162 | ||
163 | scatter_test(comm, int_generator(), "integers"); | |
164 | scatter_test(comm, gps_generator(), "GPS positions"); | |
165 | scatter_test(comm, string_generator(), "string"); | |
166 | scatter_test(comm, string_list_generator(), "list of strings"); | |
167 | ||
168 | scatterv_test(comm, int_generator(), "integers"); | |
169 | scatterv_test(comm, gps_generator(), "GPS positions"); | |
170 | scatterv_test(comm, string_generator(), "string"); | |
171 | scatterv_test(comm, string_list_generator(), "list of strings"); | |
172 | ||
173 | return 0; | |
174 | } |