• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (C) 2004-2006 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/serialization/vector.hpp>
13 #include <boost/graph/distributed/queue.hpp>
14 #include <boost/test/minimal.hpp>
15 #include <boost/graph/distributed/mpi_process_group.hpp>
16 #include <boost/pending/queue.hpp>
17 #include <boost/property_map/property_map.hpp>
18 #include <utility>
19 #include <iostream>
20 
21 #ifdef BOOST_NO_EXCEPTIONS
22 void
throw_exception(std::exception const & ex)23 boost::throw_exception(std::exception const& ex)
24 {
25     std::cout << ex.what() << std::endl;
26     abort();
27 }
28 #endif
29 
30 using boost::graph::distributed::mpi_process_group;
31 
32 struct global_value
33 {
global_valueglobal_value34   global_value(int p = -1, std::size_t l = 0) : processor(p), value(l) {}
35 
36   int processor;
37   std::size_t value;
38 
39   template<typename Archiver>
serializeglobal_value40   void serialize(Archiver& ar, const unsigned int /*version*/)
41   {
42     ar & processor & value;
43   }
44 };
45 
46 namespace boost { namespace mpi {
47     template<> struct is_mpi_datatype<global_value> : mpl::true_ { };
48 } } // end namespace boost::mpi
49 
50 BOOST_IS_BITWISE_SERIALIZABLE(global_value)
51 BOOST_CLASS_IMPLEMENTATION(global_value,object_serializable)
52 BOOST_CLASS_TRACKING(global_value,track_never)
53 
54 inline bool operator==(const global_value& x, const global_value& y)
55 { return x.processor == y.processor && x.value == y.value; }
56 
57 struct global_value_owner_map
58 {
59   typedef int value_type;
60   typedef value_type reference;
61   typedef global_value key_type;
62   typedef boost::readable_property_map_tag category;
63 };
64 
get(global_value_owner_map,global_value k)65 int get(global_value_owner_map, global_value k)
66 {
67   return k.processor;
68 }
69 
test_distributed_queue()70 void test_distributed_queue()
71 {
72   mpi_process_group process_group;
73 
74   typedef boost::queue<global_value> local_queue_type;
75 
76   typedef boost::graph::distributed::distributed_queue<mpi_process_group,
77                                              global_value_owner_map,
78                                              local_queue_type> dist_queue_type;
79 
80   dist_queue_type Q(process_group, global_value_owner_map());
81 
82   mpi_process_group::process_id_type id = process_id(process_group),
83     n = num_processes(process_group);
84   global_value v(0, 0);
85 
86   if (id == 0) {
87     std::cerr << "Should print level of each processor in a binary tree:\n";
88   }
89   synchronize(process_group);
90 
91   if (id == n-1) Q.push(v);
92   while (!Q.empty()) {
93     v = Q.top(); Q.pop();
94 
95     std::cerr << "#" << id << ": level = " << v.value << std::endl;
96 
97     int level_begin = 1;
98     for (std::size_t i = 0; i < v.value; ++i) level_begin *= 2;
99     int level_end = level_begin * 2;
100     BOOST_CHECK(level_begin <= (id + 1));
101     BOOST_CHECK((id + 1) <= level_end);
102 
103     ++v.value;
104     v.processor = v.processor * 2 + 1;
105     if (v.processor < n) Q.push(v);
106     ++v.processor;
107     if (v.processor < n) Q.push(v);
108   }
109 }
110 
test_main(int argc,char ** argv)111 int test_main(int argc, char** argv)
112 {
113   boost::mpi::environment env(argc, argv);
114   test_distributed_queue();
115   return 0;
116 }
117