Imported Upstream version 1.72.0
[platform/upstream/boost.git] / libs / mpi / test / broadcast_test.cpp
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 broadcast() collective.
8 #include <boost/mpi/collectives/broadcast.hpp>
9 #include <boost/mpi/communicator.hpp>
10 #include <boost/mpi/environment.hpp>
11 #include <algorithm>
12 #include "gps_position.hpp"
13 #include <boost/serialization/string.hpp>
14 #include <boost/serialization/list.hpp>
15 #include <boost/mpi/skeleton_and_content.hpp>
16 #include <boost/iterator/counting_iterator.hpp>
17 //#include "debugger.hpp"
18
19 #define BOOST_TEST_MODULE mpi_broadcast
20 #include <boost/test/included/unit_test.hpp>
21
22 using boost::mpi::communicator;
23
24 using boost::mpi::packed_skeleton_iarchive;
25 using boost::mpi::packed_skeleton_oarchive;
26
27 template<typename T>
28 void
29 broadcast_test(const communicator& comm, const T& bc_value,
30                const char* kind, int root = -1)
31 {
32   if (root == -1) {
33     for (root = 0; root < comm.size(); ++root)
34       broadcast_test(comm, bc_value, kind, root);
35   } else {
36     using boost::mpi::broadcast;
37
38     T value;
39     if (comm.rank() == root) {
40       value = bc_value;
41       std::cout << "Broadcasting " << kind << " from root " << root << "...";
42       std::cout.flush();
43     }
44
45     broadcast(comm, value, root);
46     BOOST_CHECK(value == bc_value);
47     if (comm.rank() == root && value == bc_value)
48       std::cout << "OK." << std::endl;
49   }
50
51   (comm.barrier)();
52 }
53
54 void
55 test_skeleton_and_content(const communicator& comm, int root = 0)
56 {
57   using boost::mpi::content;
58   using boost::mpi::get_content;
59   using boost::make_counting_iterator;
60   using boost::mpi::broadcast;
61
62   int list_size = comm.size() + 7;
63   if (comm.rank() == root) {
64     // Fill in the seed data
65     std::list<int> original_list;
66     for (int i = 0; i < list_size; ++i)
67       original_list.push_back(i);
68
69     // Build up the skeleton
70     packed_skeleton_oarchive oa(comm);
71     oa << original_list;
72
73     // Broadcast the skeleton
74     std::cout << "Broadcasting integer list skeleton from root " << root
75               << "..." << std::flush;
76     broadcast(comm, oa, root);
77     std::cout << "OK." << std::endl;
78
79     // Broadcast the content
80     std::cout << "Broadcasting integer list content from root " << root
81               << "..." << std::flush;
82     {
83       content c = get_content(original_list);
84       broadcast(comm, c, root);
85     }
86     std::cout << "OK." << std::endl;
87
88     // Reverse the list, broadcast the content again
89     std::reverse(original_list.begin(), original_list.end());
90     std::cout << "Broadcasting reversed integer list content from root "
91               << root << "..." << std::flush;
92     {
93       content c = get_content(original_list);
94       broadcast(comm, c, root);
95     }
96     std::cout << "OK." << std::endl;
97
98   } else {
99     // Allocate some useless data, to try to get the addresses of the
100     // list<int>'s used later to be different across processes.
101     std::list<int> junk_list(comm.rank() * 3 + 1, 17);
102
103     // Receive the skeleton
104     packed_skeleton_iarchive ia(comm);
105     broadcast(comm, ia, root);
106
107     // Build up a list to match the skeleton, and make sure it has the
108     // right structure (we have no idea what the data will be).
109     std::list<int> transferred_list;
110     ia >> transferred_list;
111     BOOST_CHECK((int)transferred_list.size() == list_size);
112
113     // Receive the content and check it
114     broadcast(comm, get_content(transferred_list), root);
115     bool list_content_ok = std::equal(make_counting_iterator(0),
116                                       make_counting_iterator(list_size),
117                                       transferred_list.begin());
118     BOOST_CHECK(list_content_ok);
119
120     // Receive the reversed content and check it
121     broadcast(comm, get_content(transferred_list), root);
122     bool rlist_content_ok = std::equal(make_counting_iterator(0),
123                                        make_counting_iterator(list_size),
124                                        transferred_list.rbegin());
125     BOOST_CHECK(rlist_content_ok);
126     if (!(list_content_ok && rlist_content_ok)) {
127       if (comm.rank() == 1) {
128         std::cout
129           << "\n##### You might want to check for BOOST_MPI_BCAST_BOTTOM_WORKS_FINE "
130           << "in boost/mpi/config.hpp.\n\n";
131       }
132     }
133   }
134
135   (comm.barrier)();
136 }
137
138 BOOST_AUTO_TEST_CASE(broadcast_check)
139 {
140   boost::mpi::environment env;
141   communicator comm;
142
143   BOOST_TEST_REQUIRE(comm.size() > 1);
144
145   // Check transfer of individual objects
146   broadcast_test(comm, 17, "integers");
147   broadcast_test(comm, gps_position(39,16,20.2799), "GPS positions");
148   broadcast_test(comm, gps_position(26,25,30.0), "GPS positions");
149   broadcast_test(comm, std::string("Rosie"), "string");
150
151   std::list<std::string> strings;
152   strings.push_back("Hello");
153   strings.push_back("MPI");
154   strings.push_back("World");
155   broadcast_test(comm, strings, "list of strings");
156
157   test_skeleton_and_content(comm, 0);
158   test_skeleton_and_content(comm, 1);
159 }