reduce_performance_test.cpp 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. // Copyright (C) 2006 Trustees of Indiana University
  2. //
  3. // Authors: Douglas Gregor
  4. // Andrew Lumsdaine
  5. // Use, modification and distribution is subject to the Boost Software
  6. // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  7. // http://www.boost.org/LICENSE_1_0.txt)
  8. // Performance test of the reduce() collective
  9. #include <boost/mpi.hpp>
  10. #include <boost/lexical_cast.hpp>
  11. namespace mpi = boost::mpi;
  12. struct add_int {
  13. int operator()(int x, int y) const { return x + y; }
  14. };
  15. struct wrapped_int
  16. {
  17. wrapped_int() : value(0) { }
  18. wrapped_int(int value) : value(value) { }
  19. template<typename Archiver>
  20. void serialize(Archiver& ar, const unsigned int /*version*/) {
  21. ar & value;
  22. }
  23. int value;
  24. };
  25. inline wrapped_int operator+(wrapped_int x, wrapped_int y)
  26. {
  27. return wrapped_int(x.value + y.value);
  28. }
  29. namespace boost { namespace mpi {
  30. template<> struct is_mpi_datatype<wrapped_int> : mpl::true_ { };
  31. } }
  32. struct serialized_int
  33. {
  34. serialized_int() : value(0) { }
  35. serialized_int(int value) : value(value) { }
  36. template<typename Archiver>
  37. void serialize(Archiver& ar, const unsigned int /*version*/) {
  38. ar & value;
  39. }
  40. int value;
  41. };
  42. inline serialized_int operator+(serialized_int x, serialized_int y)
  43. {
  44. return serialized_int(x.value + y.value);
  45. }
  46. int main(int argc, char* argv[])
  47. {
  48. mpi::environment env(argc, argv);
  49. mpi::communicator world;
  50. int repeat_count = 100;
  51. int outer_repeat_count = 2;
  52. if (argc > 1) repeat_count = boost::lexical_cast<int>(argv[1]);
  53. if (argc > 2) outer_repeat_count = boost::lexical_cast<int>(argv[2]);
  54. if (world.rank() == 0)
  55. std::cout << "# of processors: " << world.size() << std::endl
  56. << "# of iterations: " << repeat_count << std::endl;
  57. int value = world.rank();
  58. int result;
  59. wrapped_int wi_value = world.rank();
  60. wrapped_int wi_result;
  61. serialized_int si_value = world.rank();
  62. serialized_int si_result;
  63. // Spin for a while...
  64. for (int i = 0; i < repeat_count/10; ++i) {
  65. reduce(world, value, result, std::plus<int>(), 0);
  66. reduce(world, value, result, add_int(), 0);
  67. reduce(world, wi_value, wi_result, std::plus<wrapped_int>(), 0);
  68. reduce(world, si_value, si_result, std::plus<serialized_int>(), 0);
  69. }
  70. for (int outer = 0; outer < outer_repeat_count; ++outer) {
  71. // Raw MPI
  72. mpi::timer time;
  73. for (int i = 0; i < repeat_count; ++i) {
  74. MPI_Reduce(&value, &result, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD);
  75. }
  76. double reduce_raw_mpi_total_time = time.elapsed();
  77. // MPI_INT/MPI_SUM case
  78. time.restart();
  79. for (int i = 0; i < repeat_count; ++i) {
  80. reduce(world, value, result, std::plus<int>(), 0);
  81. }
  82. double reduce_int_sum_total_time = time.elapsed();
  83. // MPI_INT/MPI_Op case
  84. time.restart();
  85. for (int i = 0; i < repeat_count; ++i) {
  86. reduce(world, value, result, add_int(), 0);
  87. }
  88. double reduce_int_op_total_time = time.elapsed();
  89. // MPI_Datatype/MPI_Op case
  90. time.restart();
  91. for (int i = 0; i < repeat_count; ++i) {
  92. reduce(world, wi_value, wi_result, std::plus<wrapped_int>(), 0);
  93. }
  94. double reduce_type_op_total_time = time.elapsed();
  95. // Serialized/MPI_Op case
  96. time.restart();
  97. for (int i = 0; i < repeat_count; ++i) {
  98. reduce(world, si_value, si_result, std::plus<serialized_int>(), 0);
  99. }
  100. double reduce_ser_op_total_time = time.elapsed();
  101. if (world.rank() == 0)
  102. std::cout << "\nInvocation\tElapsed Time (seconds)"
  103. << "\nRaw MPI\t\t\t" << reduce_raw_mpi_total_time
  104. << "\nMPI_INT/MPI_SUM\t\t" << reduce_int_sum_total_time
  105. << "\nMPI_INT/MPI_Op\t\t" << reduce_int_op_total_time
  106. << "\nMPI_Datatype/MPI_Op\t" << reduce_type_op_total_time
  107. << "\nSerialized/MPI_Op\t" << reduce_ser_op_total_time
  108. << std::endl;
  109. }
  110. return 0;
  111. }