]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/mpi/test/cartesian_topology_test.cpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / libs / mpi / test / cartesian_topology_test.cpp
1 // Copyright Alain Miniussi 2014.
2 // Distributed under the Boost Software License, Version 1.0.
3 // (See accompanying file LICENSE_1_0.txt or copy at
4 // http://www.boost.org/LICENSE_1_0.txt)
5
6 // Authors: Alain Miniussi
7
8 #include <vector>
9 #include <iostream>
10 #include <sstream>
11 #include <iterator>
12 #include <algorithm>
13 #include <functional>
14
15 #include <boost/mpi/communicator.hpp>
16 #include <boost/mpi/collectives.hpp>
17 #include <boost/mpi/environment.hpp>
18 #include <boost/mpi/cartesian_communicator.hpp>
19
20 #define BOOST_TEST_MODULE mpi_cartesian_topolohy
21 #include <boost/test/included/unit_test.hpp>
22
23 namespace mpi = boost::mpi;
24
25 struct topo_minimum {
26 mpi::cartesian_dimension
27 operator()(mpi::cartesian_dimension const& d1,
28 mpi::cartesian_dimension const& d2 ) const {
29 return mpi::cartesian_dimension(std::min(d1.size, d2.size),
30 d1.periodic && d2.periodic);
31 }
32 };
33
34 std::string topology_description( mpi::cartesian_topology const& topo ) {
35 std::ostringstream out;
36 std::copy(topo.begin(), topo.end(), std::ostream_iterator<mpi::cartesian_dimension>(out, " "));
37 out << std::flush;
38 return out.str();
39 }
40
41 // Check that everyone agrees on the coordinates
42 void test_coordinates_consistency( mpi::cartesian_communicator const& cc,
43 std::vector<int> const& coords )
44 {
45 cc.barrier(); // flush IOs for nice printing
46 bool master = cc.rank() == 0;
47 if (master) {
48 std::cout << "Test coordinates consistency.\n";
49 }
50 for(int p = 0; p < cc.size(); ++p) {
51 std::vector<int> min(cc.ndims());
52 std::vector<int> local(cc.coordinates(p));
53 mpi::reduce(cc, &local.front(), local.size(),
54 &(min[0]), mpi::minimum<int>(), p);
55 cc.barrier();
56 if (p == cc.rank()) {
57 BOOST_CHECK(std::equal(coords.begin(), coords.end(), min.begin()));
58 std::ostringstream out;
59 out << "proc " << p << " at (";
60 std::copy(min.begin(), min.end(), std::ostream_iterator<int>(out, " "));
61 out << ")\n";
62 std::cout << out.str();
63 }
64 }
65 }
66
67 void test_shifted_coords( mpi::cartesian_communicator const& cc, int pos, mpi::cartesian_dimension desc, int dim )
68 {
69 if (desc.periodic) {
70 for (int i = -(desc.size); i < desc.size; ++i) {
71 std::pair<int,int> rks = cc.shifted_ranks(dim, i);
72 int src = cc.coordinates(rks.first)[dim];
73 int dst = cc.coordinates(rks.second)[dim];
74 if (pos == (dim/2)) {
75 std::ostringstream out;
76 out << "Rank " << cc.rank() << ", dim. " << dim << ", pos " << pos << ", in " << desc << ' ';
77 out << "shifted pos: " << src << ", " << dst << '\n';
78 std::cout << out.str();
79 }
80 }
81 }
82 }
83
84 void test_shifted_coords( mpi::cartesian_communicator const& cc)
85 {
86 cc.barrier(); // flush IOs for nice printing
87 std::vector<int> coords;
88 mpi::cartesian_topology topo(cc.ndims());
89 cc.topology(topo, coords);
90 bool master = cc.rank() == 0;
91 if (master) {
92 std::cout << "Testing shifts with topology " << topo << '\n';
93 }
94 for(int i = 0; i < cc.ndims(); ++i) {
95 if (master) {
96 std::cout << " for dimension " << i << ": " << topo[i] << '\n';
97 }
98 test_shifted_coords( cc, coords[i], topo[i], i );
99 }
100 }
101
102 void test_topology_consistency( mpi::cartesian_communicator const& cc)
103 {
104 cc.barrier(); // flush IOs for nice printing
105 mpi::cartesian_topology itopo(cc.ndims());
106 mpi::cartesian_topology otopo(cc.ndims());
107 std::vector<int> coords(cc.ndims());
108 cc.topology(itopo, coords);
109 bool master = cc.rank() == 0;
110 if (master) {
111 std::cout << "Test topology consistency of" << itopo << "(on master)\n";
112 std::cout << "Check that everyone agrees on the dimensions.\n";
113 }
114 mpi::all_reduce(cc,
115 &(itopo[0]), itopo.size(), &(otopo[0]),
116 topo_minimum());
117 BOOST_CHECK(std::equal(itopo.begin(), itopo.end(), otopo.begin()));
118 if (master) {
119 std::cout << "We agree on " << topology_description(otopo) << '\n';
120 }
121 test_coordinates_consistency( cc, coords );
122 }
123
124 void test_cartesian_topology( mpi::cartesian_communicator const& cc)
125 {
126 BOOST_CHECK(cc.has_cartesian_topology());
127 for( int r = 0; r < cc.size(); ++r) {
128 cc.barrier();
129 if (r == cc.rank()) {
130 std::vector<int> coords = cc.coordinates(r);
131 std::cout << "Process of cartesian rank " << cc.rank()
132 << " has coordinates (";
133 std::copy(coords.begin(), coords.end(), std::ostream_iterator<int>(std::cout," "));
134 std::cout << ")\n";
135 }
136 }
137 test_topology_consistency(cc);
138 test_shifted_coords(cc);
139 std::vector<int> even;
140 for(int i = 0; i < cc.ndims(); i += 2) {
141 even.push_back(i);
142 }
143 cc.barrier();
144 mpi::cartesian_communicator cce(cc, even);
145 }
146
147 void test_cartesian_topology( mpi::communicator const& world, mpi::cartesian_topology const& topo)
148 {
149 mpi::cartesian_communicator cc(world, topo, true);
150 if (cc) {
151 BOOST_CHECK(cc.has_cartesian_topology());
152 BOOST_CHECK(cc.ndims() == int(topo.size()));
153 if (cc.rank() == 0) {
154 std::cout << "Asked topology " << topo << ", got " << cc.topology() << '\n';
155 }
156 test_cartesian_topology(cc);
157 } else {
158 std::ostringstream out;
159 out << world.rank() << " was left outside the cartesian grid\n";
160 std::cout << out.str();
161 }
162 }
163
164 BOOST_AUTO_TEST_CASE(cartesian_topology)
165 {
166 mpi::environment env;
167 mpi::communicator world;
168
169 int const ndim = world.size() >= 24 ? 3 : 2;
170 mpi::cartesian_topology topo(ndim);
171 typedef mpi::cartesian_dimension cd;
172 if (topo.size() == 3) {
173 topo[0] = cd(2,true);
174 topo[1] = cd(3,false);
175 topo[2] = cd(4, true);
176 } else {
177 if (world.size() >= 6) {
178 topo[0] = cd(2,true);
179 topo[1] = cd(3, false);
180 } else {
181 topo[0] = cd(1,true);
182 topo[1] = cd(1, false);
183 }
184 }
185 test_cartesian_topology( world, topo);
186 #if !defined(BOOST_NO_CXX11_DEFAULTED_MOVES)
187 world.barrier();
188 if (world.rank()==0) {
189 std::cout << "Testing move constructor.\n";
190 }
191 test_cartesian_topology( world, std::move(topo));
192 #endif
193 }