random_content.cpp 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. // Copyright (C) 2006 Douglas Gregor <doug.gregor@gmail.com>
  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. // An example using Boost.MPI's skeletons and content to optimize
  6. // communication.
  7. #include <boost/mpi.hpp>
  8. #include <boost/serialization/list.hpp>
  9. #include <algorithm>
  10. #include <functional>
  11. #include <numeric>
  12. #include <iostream>
  13. #include <stdlib.h>
  14. namespace mpi = boost::mpi;
  15. int main(int argc, char* argv[])
  16. {
  17. mpi::environment env(argc, argv);
  18. mpi::communicator world;
  19. if (world.size() < 2 || world.size() > 4) {
  20. if (world.rank() == 0)
  21. std::cerr << "error: please execute this program with 2-4 processes.\n";
  22. world.abort(-1);
  23. }
  24. if (world.rank() == 0) {
  25. int list_len = 50;
  26. int iterations = 10;
  27. if (argc > 1) list_len = atoi(argv[1]);
  28. if (argc > 2) iterations = atoi(argv[2]);
  29. if (list_len <= 0) {
  30. std::cerr << "error: please specific a list length greater than zero.\n";
  31. world.abort(-1);
  32. }
  33. // Generate the list and broadcast its structure
  34. std::list<int> l(list_len);
  35. broadcast(world, mpi::skeleton(l), 0);
  36. // Generate content several times and broadcast out that content
  37. mpi::content c = mpi::get_content(l);
  38. for (int i = 0; i < iterations; ++i) {
  39. do {
  40. std::generate(l.begin(), l.end(), &random);
  41. } while (std::find_if(l.begin(), l.end(),
  42. std::bind1st(std::not_equal_to<int>(), 0))
  43. == l.end());
  44. std::cout << "Iteration #" << i << ": sending content"
  45. << " (min = " << *std::min_element(l.begin(), l.end())
  46. << ", max = " << *std::max_element(l.begin(), l.end())
  47. << ", avg = "
  48. << std::accumulate(l.begin(), l.end(), 0)/l.size()
  49. << ").\n";
  50. broadcast(world, c, 0);
  51. }
  52. // Notify the slaves that we're done by sending all zeroes
  53. std::fill(l.begin(), l.end(), 0);
  54. broadcast(world, c, 0);
  55. } else {
  56. // Receive the content and build up our own list
  57. std::list<int> l;
  58. broadcast(world, mpi::skeleton(l), 0);
  59. mpi::content c = mpi::get_content(l);
  60. int i = 0;
  61. do {
  62. broadcast(world, c, 0);
  63. if (std::find_if(l.begin(), l.end(),
  64. std::bind1st(std::not_equal_to<int>(), 0)) == l.end())
  65. break;
  66. if (world.rank() == 1)
  67. std::cout << "Iteration #" << i << ": max value = "
  68. << *std::max_element(l.begin(), l.end()) << ".\n";
  69. else if (world.rank() == 2)
  70. std::cout << "Iteration #" << i << ": min value = "
  71. << *std::min_element(l.begin(), l.end()) << ".\n";
  72. else if (world.rank() == 3)
  73. std::cout << "Iteration #" << i << ": avg value = "
  74. << std::accumulate(l.begin(), l.end(), 0)/l.size()
  75. << ".\n";
  76. ++i;
  77. } while (true);
  78. }
  79. return 0;
  80. }