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