]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/graph_parallel/test/distributed_property_map_test.cpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / graph_parallel / test / distributed_property_map_test.cpp
1 // Copyright (C) 2004-2008 The Trustees of Indiana University.
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 // Authors: Douglas Gregor
8 // Andrew Lumsdaine
9 #include <boost/graph/use_mpi.hpp>
10 #include <boost/config.hpp>
11 #include <boost/throw_exception.hpp>
12 #include <boost/graph/distributed/mpi_process_group.hpp>
13 #include <boost/property_map/property_map.hpp>
14 #include <boost/test/minimal.hpp>
15 #include <vector>
16 #include <string>
17 #include <boost/serialization/vector.hpp>
18 #include <boost/serialization/string.hpp>
19 #include <boost/serialization/utility.hpp>
20 #include <boost/lexical_cast.hpp>
21 #include <boost/graph/parallel/basic_reduce.hpp>
22
23 #ifdef BOOST_NO_EXCEPTIONS
24 void
25 boost::throw_exception(std::exception const& ex)
26 {
27 std::cout << ex.what() << std::endl;
28 abort();
29 }
30 #endif
31
32 using namespace boost;
33 using boost::graph::distributed::mpi_process_group;
34
35 enum color_t { red, blue };
36
37 struct remote_key
38 {
39 remote_key(int p = -1, std::size_t l = 0) : processor(p), local_key(l) {}
40
41 int processor;
42 std::size_t local_key;
43
44 template<typename Archiver>
45 void serialize(Archiver& ar, const unsigned int /*version*/)
46 {
47 ar & processor & local_key;
48 }
49 };
50
51 namespace boost { namespace mpi {
52 template<> struct is_mpi_datatype<remote_key> : mpl::true_ { };
53 } }
54 BOOST_IS_BITWISE_SERIALIZABLE(remote_key)
55 BOOST_CLASS_IMPLEMENTATION(remote_key,object_serializable)
56 BOOST_CLASS_TRACKING(remote_key,track_never)
57
58 namespace boost {
59
60 template<>
61 struct hash<remote_key>
62 {
63 std::size_t operator()(const remote_key& key) const
64 {
65 std::size_t hash = hash_value(key.processor);
66 hash_combine(hash, key.local_key);
67 return hash;
68 }
69 };
70 }
71
72 inline bool operator==(const remote_key& x, const remote_key& y)
73 { return x.processor == y.processor && x.local_key == y.local_key; }
74
75 struct remote_key_to_global
76 {
77 typedef readable_property_map_tag category;
78 typedef remote_key key_type;
79 typedef std::pair<int, std::size_t> value_type;
80 typedef value_type reference;
81 };
82
83 inline std::pair<int, std::size_t>
84 get(remote_key_to_global, const remote_key& key)
85 {
86 return std::make_pair(key.processor, key.local_key);
87 }
88
89 template<typename T>
90 struct my_reduce : boost::parallel::basic_reduce<T> {
91 BOOST_STATIC_CONSTANT(bool, non_default_resolver = true);
92 };
93
94 void colored_test()
95 {
96 mpi_process_group pg;
97 const int n = 500;
98
99 color_t my_start_color = process_id(pg) % 2 == 0? ::red : ::blue;
100 int next_processor = (process_id(pg) + 1) % num_processes(pg);
101 color_t next_start_color = next_processor % 2 == 0? ::red : ::blue;
102
103 // Initial color map: even-numbered processes are all red,
104 // odd-numbered processes are all blue.
105 std::vector<color_t> color_vec(n, my_start_color);
106
107 typedef iterator_property_map<std::vector<color_t>::iterator,
108 identity_property_map> LocalPropertyMap;
109 LocalPropertyMap local_colors(color_vec.begin(), identity_property_map());
110
111 synchronize(pg);
112
113 // Create the distributed property map
114 typedef boost::parallel::distributed_property_map<mpi_process_group,
115 remote_key_to_global,
116 LocalPropertyMap> ColorMap;
117 ColorMap colors(pg, remote_key_to_global(), local_colors);
118 colors.set_reduce(my_reduce<color_t>());
119
120 if (process_id(pg) == 0) std::cerr << "Checking local colors...";
121 // check local processor colors
122 for (int i = 0; i < n; ++i) {
123 remote_key k(process_id(pg), i);
124 BOOST_CHECK(get(colors, k) == my_start_color);
125 }
126
127 colors.set_consistency_model(boost::parallel::cm_bidirectional);
128 if (process_id(pg) == 0) std::cerr << "OK.\nChecking next processor's default colors...";
129 // check next processor's colors
130 for (int i = 0; i < n; ++i) {
131 remote_key k(next_processor, i);
132 BOOST_CHECK(get(colors, k) == color_t());
133 }
134
135 if (process_id(pg) == 0) std::cerr << "OK.\nSynchronizing...";
136 synchronize(pg);
137
138 if (process_id(pg) == 0) std::cerr << "OK.\nChecking next processor's colors...";
139 // check next processor's colors
140 for (int i = 0; i < n; ++i) {
141 remote_key k(next_processor, i);
142 BOOST_CHECK(get(colors, k) == next_start_color);
143 }
144
145 if (process_id(pg) == 0) std::cerr << "OK.\nSynchronizing...";
146 synchronize(pg);
147
148 if (process_id(pg) == 0) std::cerr << "OK.\nChanging next processor's colors...";
149 // change the next processor's colors
150 color_t next_finish_color = next_processor % 2 == 0? ::blue : ::red;
151 for (int i = 0; i < n; ++i) {
152 remote_key k(next_processor, i);
153 put(colors, k, next_finish_color);
154 }
155
156 if (process_id(pg) == 0) std::cerr << "OK.\nSynchronizing...";
157 synchronize(pg);
158
159 if (process_id(pg) == 0) std::cerr << "OK.\nChecking changed colors...";
160 // check our own colors
161 color_t my_finish_color = process_id(pg) % 2 == 0? ::blue : ::red;
162 for (int i = 0; i < n; ++i) {
163 remote_key k(process_id(pg), i);
164 BOOST_CHECK(get(colors, k) == my_finish_color);
165 }
166
167 // check our neighbor's colors
168 if (process_id(pg) == 0) std::cerr << "OK.\nChecking changed colors on neighbor...";
169 for (int i = 0; i < n; ++i) {
170 remote_key k(next_processor, i);
171 BOOST_CHECK(get(colors, k) == next_finish_color);
172 }
173
174 synchronize(pg);
175
176 if (process_id(pg) == 0) std::cerr << "OK.\n";
177 }
178
179 void bool_test()
180 {
181 mpi_process_group pg;
182 const int n = 500;
183
184 bool my_start_value = process_id(pg) % 2;
185 int next_processor = (process_id(pg) + 1) % num_processes(pg);
186 bool next_start_value = ((process_id(pg) + 1) % num_processes(pg)) % 2;
187
188 // Initial color map: even-numbered processes are false,
189 // odd-numbered processes are true
190 std::vector<bool> bool_vec(n, my_start_value);
191
192 typedef iterator_property_map<std::vector<bool>::iterator,
193 identity_property_map> LocalPropertyMap;
194 LocalPropertyMap local_values(bool_vec.begin(), identity_property_map());
195
196 synchronize(pg);
197
198 // Create the distributed property map
199 typedef boost::parallel::distributed_property_map<mpi_process_group,
200 remote_key_to_global,
201 LocalPropertyMap> ValueMap;
202 ValueMap values(pg, remote_key_to_global(), local_values);
203 values.set_reduce(my_reduce<bool>());
204
205 if (process_id(pg) == 0) std::cerr << "Checking local values...";
206 // check local processor values
207 for (int i = 0; i < n; ++i) {
208 remote_key k(process_id(pg), i);
209 BOOST_CHECK(get(values, k) == my_start_value);
210 }
211
212 values.set_consistency_model(boost::parallel::cm_bidirectional);
213 if (process_id(pg) == 0) std::cerr << "OK.\nChecking next processor's default values...";
214 // check next processor's values
215 for (int i = 0; i < n; ++i) {
216 remote_key k(next_processor, i);
217 BOOST_CHECK(get(values, k) == false);
218 }
219
220 if (process_id(pg) == 0) std::cerr << "OK.\nSynchronizing...";
221 synchronize(pg);
222
223 if (process_id(pg) == 0) std::cerr << "OK.\nChecking next processor's values...";
224 // check next processor's values
225 for (int i = 0; i < n; ++i) {
226 remote_key k(next_processor, i);
227 BOOST_CHECK(get(values, k) == next_start_value);
228 }
229
230 if (process_id(pg) == 0) std::cerr << "OK.\nSynchronizing...";
231 synchronize(pg);
232
233 if (process_id(pg) == 0) std::cerr << "OK.\nChanging next processor's values...";
234 // change the next processor's values
235 bool next_finish_value = next_processor % 2 == 0;
236 for (int i = 0; i < n; ++i) {
237 remote_key k(next_processor, i);
238 put(values, k, next_finish_value);
239 }
240
241 if (process_id(pg) == 0) std::cerr << "OK.\nSynchronizing...";
242 synchronize(pg);
243
244 if (process_id(pg) == 0) std::cerr << "OK.\nChecking changed values...";
245 // check our own values
246 bool my_finish_value = process_id(pg) % 2 == 0;
247 for (int i = 0; i < n; ++i) {
248 remote_key k(process_id(pg), i);
249 BOOST_CHECK(get(values, k) == my_finish_value);
250 }
251
252 // check our neighbor's values
253 if (process_id(pg) == 0) std::cerr << "OK.\nChecking changed values on neighbor...";
254 for (int i = 0; i < n; ++i) {
255 remote_key k(next_processor, i);
256 BOOST_CHECK(get(values, k) == next_finish_value);
257 }
258
259 synchronize(pg);
260
261 if (process_id(pg) == 0) std::cerr << "OK.\n";
262 }
263
264 void string_test()
265 {
266 mpi_process_group pg;
267 const int n = 500;
268
269 std::string my_start_string = lexical_cast<std::string>(process_id(pg));
270 int next_processor = (process_id(pg) + 1) % num_processes(pg);
271 std::string next_start_string = lexical_cast<std::string>(next_processor);
272
273 // Initial color map: even-numbered processes are false,
274 // odd-numbered processes are true
275 std::vector<std::string> string_vec(n, my_start_string);
276
277 typedef iterator_property_map<std::vector<std::string>::iterator,
278 identity_property_map> LocalPropertyMap;
279 LocalPropertyMap local_strings(string_vec.begin(), identity_property_map());
280
281 synchronize(pg);
282
283 // Create the distributed property map
284 typedef boost::parallel::distributed_property_map<mpi_process_group,
285 remote_key_to_global,
286 LocalPropertyMap> StringMap;
287 StringMap strings(pg, remote_key_to_global(), local_strings);
288 strings.set_reduce(my_reduce<std::string>());
289
290 if (process_id(pg) == 0) std::cerr << "Checking local strings...";
291 // check local processor strings
292 for (int i = 0; i < n; ++i) {
293 remote_key k(process_id(pg), i);
294 BOOST_CHECK(get(strings, k) == my_start_string);
295 }
296
297 strings.set_consistency_model(boost::parallel::cm_bidirectional);
298 if (process_id(pg) == 0) std::cerr << "OK.\nChecking next processor's default strings...";
299 // check next processor's strings
300 for (int i = 0; i < n; ++i) {
301 remote_key k(next_processor, i);
302 BOOST_CHECK(get(strings, k) == (num_processes(pg) == 1 ? my_start_string : std::string()));
303 }
304
305 if (process_id(pg) == 0) std::cerr << "OK.\nSynchronizing...";
306 synchronize(pg);
307
308 if (process_id(pg) == 0) std::cerr << "OK.\nChecking next processor's strings...";
309 // check next processor's strings
310 for (int i = 0; i < n; ++i) {
311 remote_key k(next_processor, i);
312 BOOST_CHECK(get(strings, k) == next_start_string);
313 }
314
315 if (process_id(pg) == 0) std::cerr << "OK.\nSynchronizing...";
316 synchronize(pg);
317
318 if (process_id(pg) == 0) std::cerr << "OK.\nChanging next processor's strings...";
319 // change the next processor's strings
320 std::string next_finish_string = next_start_string + next_start_string;
321 for (int i = 0; i < n; ++i) {
322 remote_key k(next_processor, i);
323 put(strings, k, next_finish_string);
324 }
325
326 if (process_id(pg) == 0) std::cerr << "OK.\nSynchronizing...";
327 synchronize(pg);
328
329 if (process_id(pg) == 0) std::cerr << "OK.\nChecking changed strings...";
330 // check our own strings
331 std::string my_finish_string = my_start_string + my_start_string;
332 for (int i = 0; i < n; ++i) {
333 remote_key k(process_id(pg), i);
334 BOOST_CHECK(get(strings, k) == my_finish_string);
335 }
336
337 // check our neighbor's strings
338 if (process_id(pg) == 0) std::cerr << "OK.\nChecking changed strings on neighbor...";
339 for (int i = 0; i < n; ++i) {
340 remote_key k(next_processor, i);
341 BOOST_CHECK(get(strings, k) == next_finish_string);
342 }
343
344 synchronize(pg);
345
346 if (process_id(pg) == 0) std::cerr << "OK.\n";
347 }
348
349 int test_main(int argc, char** argv)
350 {
351 boost::mpi::environment env(argc, argv);
352 colored_test();
353 bool_test();
354 string_test();
355 return 0;
356 }