ring_test.cpp 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  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 communicator that passes data around a ring and
  6. // verifies that the same data makes it all the way. Should test all
  7. // of the various kinds of data that can be sent (primitive types, POD
  8. // types, serializable objects, etc.)
  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 "debugger.cpp"
  16. #define BOOST_TEST_MODULE mpi_reduce_ring
  17. #include <boost/test/included/unit_test.hpp>
  18. using boost::mpi::communicator;
  19. using boost::mpi::status;
  20. template<typename T>
  21. void
  22. ring_test(const communicator& comm, const T& pass_value, const char* kind,
  23. int root = 0)
  24. {
  25. T transferred_value;
  26. int rank = comm.rank();
  27. int size = comm.size();
  28. if (rank == root) {
  29. std::cout << "Passing " << kind << " around a ring from root " << root
  30. << "...";
  31. comm.send((rank + 1) % size, 0, pass_value);
  32. comm.recv((rank + size - 1) % size, 0, transferred_value);
  33. BOOST_CHECK(transferred_value == pass_value);
  34. if (transferred_value == pass_value) std::cout << " OK." << std::endl;
  35. } else {
  36. comm.recv((rank + size - 1) % size, 0, transferred_value);
  37. BOOST_CHECK(transferred_value == pass_value);
  38. comm.send((rank + 1) % size, 0, transferred_value);
  39. }
  40. (comm.barrier)();
  41. }
  42. template<typename T>
  43. void
  44. ring_array_test(const communicator& comm, const T* pass_values,
  45. int n, const char* kind, int root = 0)
  46. {
  47. T* transferred_values = new T[n];
  48. int rank = comm.rank();
  49. int size = comm.size();
  50. if (rank == root) {
  51. std::cout << "Passing " << kind << " array around a ring from root "
  52. << root << "...";
  53. comm.send((rank + 1) % size, 0, pass_values, n);
  54. comm.recv((rank + size - 1) % size, 0, transferred_values, n);
  55. bool okay = std::equal(pass_values, pass_values + n,
  56. transferred_values);
  57. BOOST_CHECK(okay);
  58. if (okay) std::cout << " OK." << std::endl;
  59. } else {
  60. status stat = comm.probe(boost::mpi::any_source, 0);
  61. boost::optional<int> num_values = stat.template count<T>();
  62. if (boost::mpi::is_mpi_datatype<T>())
  63. BOOST_CHECK(num_values && *num_values == n);
  64. else
  65. BOOST_CHECK(!num_values || *num_values == n);
  66. comm.recv(stat.source(), 0, transferred_values, n);
  67. BOOST_CHECK(std::equal(pass_values, pass_values + n,
  68. transferred_values));
  69. comm.send((rank + 1) % size, 0, transferred_values, n);
  70. }
  71. (comm.barrier)();
  72. delete [] transferred_values;
  73. }
  74. enum color_t {red, green, blue};
  75. BOOST_IS_MPI_DATATYPE(color_t)
  76. BOOST_AUTO_TEST_CASE(ring)
  77. {
  78. boost::mpi::environment env;
  79. communicator comm;
  80. BOOST_TEST_REQUIRE(comm.size() > 1);
  81. // Check transfer of individual objects
  82. ring_test(comm, 17, "integers", 0);
  83. ring_test(comm, 17, "integers", 1);
  84. ring_test(comm, red, "enums", 1);
  85. ring_test(comm, red, "enums", 1);
  86. ring_test(comm, gps_position(39,16,20.2799), "GPS positions", 0);
  87. ring_test(comm, gps_position(26,25,30.0), "GPS positions", 1);
  88. ring_test(comm, std::string("Rosie"), "string", 0);
  89. std::list<std::string> strings;
  90. strings.push_back("Hello");
  91. strings.push_back("MPI");
  92. strings.push_back("World");
  93. ring_test(comm, strings, "list of strings", 1);
  94. // Check transfer of arrays
  95. int int_array[2] = { 17, 42 };
  96. ring_array_test(comm, int_array, 2, "integer", 1);
  97. gps_position gps_position_array[2] = {
  98. gps_position(39,16,20.2799),
  99. gps_position(26,25,30.0)
  100. };
  101. ring_array_test(comm, gps_position_array, 2, "GPS position", 1);
  102. std::string string_array[3] = { "Hello", "MPI", "World" };
  103. ring_array_test(comm, string_array, 3, "string", 0);
  104. ring_array_test(comm, string_array, 3, "string", 1);
  105. }