scatter_test.cpp 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. // Copyright (C) 2005, 2006 Douglas Gregor.
  2. // Use, modification and distribution is subject to the Boost Software
  3. // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  4. // http://www.boost.org/LICENSE_1_0.txt)
  5. // A test of the scatter() and scatterv() collectives.
  6. #include <iterator>
  7. #include <boost/mpi/collectives/scatter.hpp>
  8. #include <boost/mpi/collectives/scatterv.hpp>
  9. #include <boost/mpi/communicator.hpp>
  10. #include <boost/mpi/environment.hpp>
  11. #include "gps_position.hpp"
  12. #include <boost/serialization/string.hpp>
  13. #include <boost/serialization/list.hpp>
  14. #include <boost/iterator/counting_iterator.hpp>
  15. #include <boost/lexical_cast.hpp>
  16. #define BOOST_TEST_MODULE mpi_scatter
  17. #include <boost/test/included/unit_test.hpp>
  18. using namespace boost::mpi;
  19. template<typename Generator>
  20. void
  21. scatter_test(const communicator& comm, Generator generator,
  22. const char* kind, int root = -1)
  23. {
  24. typedef typename Generator::result_type value_type;
  25. if (root == -1) {
  26. for (root = 0; root < comm.size(); ++root)
  27. scatter_test(comm, generator, kind, root);
  28. } else {
  29. using boost::mpi::scatter;
  30. value_type value;
  31. if (comm.rank() == root) {
  32. std::vector<value_type> values;
  33. for (int p = 0; p < comm.size(); ++p)
  34. values.push_back(generator(p));
  35. std::cout << "Scattering " << kind << " from root "
  36. << root << "..." << std::endl;
  37. scatter(comm, values, value, root);
  38. } else {
  39. scatter(comm, value, root);
  40. }
  41. BOOST_CHECK(value == generator(comm.rank()));
  42. }
  43. comm.barrier();
  44. }
  45. //
  46. // Generators to test with scatter/scatterv
  47. //
  48. struct int_generator
  49. {
  50. typedef int result_type;
  51. int operator()(int p) const { return 17 + p; }
  52. };
  53. struct gps_generator
  54. {
  55. typedef gps_position result_type;
  56. gps_position operator()(int p) const
  57. {
  58. return gps_position(39 + p, 16, 20.2799);
  59. }
  60. };
  61. struct string_generator
  62. {
  63. typedef std::string result_type;
  64. std::string operator()(int p) const
  65. {
  66. std::string result = boost::lexical_cast<std::string>(p);
  67. result += " rosebud";
  68. if (p != 1) result += 's';
  69. return result;
  70. }
  71. };
  72. struct string_list_generator
  73. {
  74. typedef std::list<std::string> result_type;
  75. std::list<std::string> operator()(int p) const
  76. {
  77. std::list<std::string> result;
  78. for (int i = 0; i <= p; ++i) {
  79. std::string value = boost::lexical_cast<std::string>(i);
  80. result.push_back(value);
  81. }
  82. return result;
  83. }
  84. };
  85. std::ostream&
  86. operator<<(std::ostream& out, std::list<std::string> const& l) {
  87. out << '[';
  88. std::copy(l.begin(), l.end(), std::ostream_iterator<std::string>(out, " "));
  89. out << ']';
  90. return out;
  91. }
  92. template<typename Generator>
  93. void
  94. scatterv_test(const communicator& comm, Generator generator,
  95. const char* kind, int root = -1)
  96. {
  97. typedef typename Generator::result_type value_type;
  98. if (root == -1) {
  99. for (root = 0; root < comm.size(); ++root)
  100. scatterv_test(comm, generator, kind, root);
  101. } else {
  102. using boost::mpi::scatterv;
  103. int mysize = comm.rank() + 1;
  104. std::vector<value_type> myvalues(mysize);
  105. if (comm.rank() == root) {
  106. std::vector<value_type> values;
  107. std::vector<int> sizes(comm.size());
  108. // process p will receive p+1 identical generator(p) elements
  109. for (int p = 0; p < comm.size(); ++p) {
  110. for (int i = 0; i < p+1; ++i)
  111. values.push_back(generator(p));
  112. sizes[p] = p + 1;
  113. }
  114. std::cout << "Scatteringv " << kind << " from root "
  115. << root << "..." << std::endl;
  116. assert(mysize == sizes[comm.rank()]);
  117. scatterv(comm, values, sizes, &(myvalues[0]), root);
  118. } else {
  119. scatterv(comm, &(myvalues[0]), mysize, root);
  120. }
  121. for (int i = 0; i < mysize; ++i)
  122. BOOST_CHECK(myvalues[i] == generator(comm.rank()));
  123. }
  124. comm.barrier();
  125. }
  126. template<typename Generator>
  127. void
  128. scatterd_test(const communicator& comm, Generator generator,
  129. const char* kind, int root = -1)
  130. {
  131. typedef typename Generator::result_type value_type;
  132. if (root == -1) {
  133. for (root = 0; root < comm.size(); ++root)
  134. scatterv_test(comm, generator, kind, root);
  135. } else {
  136. using boost::mpi::scatterv;
  137. int mysize = comm.rank() + 1;
  138. std::vector<value_type> myvalues(mysize);
  139. if (comm.rank() == root) {
  140. std::vector<value_type> values;
  141. std::vector<int> sizes(comm.size());
  142. std::vector<int> displs(comm.size());
  143. value_type noise = generator(comm.size()+1);
  144. // process p will receive a payload of p+1 identical generator(p) elements
  145. // root will insert pseudo random pading between each payload.
  146. int shift = 0; // the current position of next payload in source array
  147. for (int p = 0; p < comm.size(); ++p) {
  148. int size = p+1;
  149. int pad = p % 3;
  150. // padding
  151. for (int i = 0; i < pad; ++i) {
  152. values.push_back(noise);
  153. }
  154. // payload
  155. for (int i = 0; i < size; ++i)
  156. values.push_back(generator(p));
  157. shift += pad;
  158. displs[p] = shift;
  159. sizes[p] = size;
  160. shift += size;
  161. }
  162. std::cout << "Scatteringv " << kind << " from root "
  163. << root << "..." << std::endl;
  164. assert(mysize == sizes[comm.rank()]);
  165. scatterv(comm, values, sizes, displs, &(myvalues[0]), mysize, root);
  166. } else {
  167. scatterv(comm, &(myvalues[0]), mysize, root);
  168. }
  169. for (int i = 0; i < mysize; ++i)
  170. BOOST_CHECK(myvalues[i] == generator(comm.rank()));
  171. }
  172. comm.barrier();
  173. }
  174. BOOST_AUTO_TEST_CASE(simple_scatter)
  175. {
  176. environment env;
  177. communicator comm;
  178. scatter_test(comm, int_generator(), "integers");
  179. scatter_test(comm, gps_generator(), "GPS positions");
  180. scatter_test(comm, string_generator(), "string");
  181. scatter_test(comm, string_list_generator(), "list of strings");
  182. scatterv_test(comm, int_generator(), "integers");
  183. scatterv_test(comm, gps_generator(), "GPS positions");
  184. scatterv_test(comm, string_generator(), "string");
  185. scatterv_test(comm, string_list_generator(), "list of strings");
  186. scatterd_test(comm, int_generator(), "integers");
  187. scatterd_test(comm, gps_generator(), "GPS positions");
  188. scatterd_test(comm, string_generator(), "string");
  189. scatterd_test(comm, string_list_generator(), "list of strings");
  190. }