cartesian_topology_test.cpp 5.9 KB

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