OPAL (Object Oriented Parallel Accelerator Library)  2021.1.99
OPAL
MasterNode.h
Go to the documentation of this file.
1 //
2 // Class MasterNode
3 // Implements a node in the network of all pilots, exposing store and
4 // collect operations on a specific set of neighbors.
5 //
6 // Using the neighbor strategy a set of neighbors we collect solution state
7 // from (and they collect from us) is defined. Using this set of neighbors the
8 // solution states propagate throughout the network. The store and collect
9 // operations are implemented using one sided MPI communication methods
10 // (simulating shared memory).
11 // A revision number is used to prevent receiving previously collected
12 // solution states from neighbors.
13 //
14 // Copyright (c) 2010 - 2013, Yves Ineichen, ETH Zürich
15 // All rights reserved
16 //
17 // Implemented as part of the PhD thesis
18 // "Toward massively parallel multi-objective optimization with application to
19 // particle accelerators" (https://doi.org/10.3929/ethz-a-009792359)
20 //
21 // This file is part of OPAL.
22 //
23 // OPAL is free software: you can redistribute it and/or modify
24 // it under the terms of the GNU General Public License as published by
25 // the Free Software Foundation, either version 3 of the License, or
26 // (at your option) any later version.
27 //
28 // You should have received a copy of the GNU General Public License
29 // along with OPAL. If not, see <https://www.gnu.org/licenses/>.
30 //
31 #ifndef __MASTER_NODE__
32 #define __MASTER_NODE__
33 
34 #include <set>
35 #include <cmath>
36 #include <vector>
37 
38 #include <string>
39 #include <sstream>
40 
41 #include "mpi.h"
42 
43 #include <boost/archive/text_oarchive.hpp>
44 #include <boost/archive/text_iarchive.hpp>
45 #include <boost/serialization/vector.hpp>
46 #include <boost/serialization/utility.hpp>
47 
48 
49 //XXX: SolutionState_t must be serializable! (call
50 // SerializableSolutionState_t?)
51 template <
52  class SolutionState_t
53  , class NeighborStrategy_t
54 >
55 class MasterNode : public NeighborStrategy_t {
56 
57 
58 public:
59 
60  MasterNode(MPI_Comm master_comm, size_t buf_size_upper_bound, size_t dim,
61  int island_id)
62  : buf_size_upper_bound_(buf_size_upper_bound)
63  , master_comm_(master_comm) {
64 
65  int tmp = 0;
66  MPI_Comm_rank(master_comm, &tmp);
67  myID_ = static_cast<size_t>(tmp);
68 
69  MPI_Comm_size(master_comm, &tmp);
70  numMasters_ = static_cast<size_t>(tmp);
71  revision_state_.resize(numMasters_, 0);
72 
73  // better to use MPI-2 memory allocation methods
74  MPI_Alloc_mem(sizeof(char) * buf_size_upper_bound,
75  MPI_INFO_NULL, &serialized_best_values_);
76 
77  // expose our shared memory holding our best values
78  MPI_Win_create(serialized_best_values_, buf_size_upper_bound,
79  sizeof(char), MPI_INFO_NULL, master_comm, &win_);
80 
81  MPI_Win_create(&revision_, 1, sizeof(size_t), MPI_INFO_NULL,
82  master_comm, &win_rev_);
83 
84 
85  // execute neighbor strategy to learn which neighbors have to be
86  // updated with our solution state (and we collect from)
87  collectFrom_ = this->execute(numMasters_, dim, myID_, island_id);
88  }
89 
91  MPI_Win_free(&win_);
92  MPI_Free_mem(serialized_best_values_);
93  MPI_Win_free(&win_rev_);
94  }
95 
96 
98  void store(char *local_state, size_t buffer_size) {
99 
100  revision_++;
101  MPI_Win_fence(MPI_MODE_NOPUT, win_rev_);
102 
103  size_t buf_size = buffer_size;
104  if(buf_size > buf_size_upper_bound_)
105  std::cout << "windows too small: " << buffer_size << " / "
107 
108  memcpy(serialized_best_values_, local_state, buf_size);
109  MPI_Win_fence(MPI_MODE_NOPUT, win_);
110  //MPI_Win_fence((MPI_MODE_NOPUT | MPI_MODE_NOPRECEDE), win_);
111  }
112 
113 
115  void collect(std::ostringstream &states) {
116 
117  char *buffer;
118  MPI_Alloc_mem(buf_size_upper_bound_, MPI_INFO_NULL, &buffer);
119  SolutionState_t tmp_states;
120 
121 
122  for(size_t i=0; i < numMasters_; i++) {
123  // ignore all except for selected master PIDs
124  if(i == myID_) continue;
125  if(collectFrom_.count(i) == 0) continue;
126 
127  // only continue if new values are available on master i
128  size_t revision = 0;
129  MPI_Get(&revision, 1, MPI_UNSIGNED_LONG, i, 0, 1, MPI_UNSIGNED_LONG, win_rev_);
130  MPI_Win_fence(0, win_rev_);
131 
132  if(revision <= revision_state_[i]) continue;
133  revision_state_[i] = revision;
134 
135  MPI_Get(buffer, buf_size_upper_bound_, MPI_CHAR, i, 0,
136  buf_size_upper_bound_, MPI_CHAR, win_);
137  MPI_Win_fence(0, win_);
138 
139  std::istringstream is(buffer);
140  boost::archive::text_iarchive ia(is);
141 
142  //XXX: ugly that we have to know the SolutionState_t here
143  SolutionState_t state;
144  ia >> state;
145  tmp_states.insert(tmp_states.end(), state.begin(), state.end());
146  }
147 
148  boost::archive::text_oarchive oa(states);
149  oa << tmp_states;
150 
151  MPI_Free_mem(buffer);
152  }
153 
154 
155 private:
156 
159 
162  size_t numMasters_;
163  MPI_Comm master_comm_;
164 
165  // windows for storing revision and solution state
166  MPI_Win win_;
167  MPI_Win win_rev_;
168 
169  size_t myID_;
170 
172  std::set<size_t> collectFrom_;
174  size_t revision_;
176  std::vector<size_t> revision_state_;
177 };
178 
179 #endif
Inform & endl(Inform &inf)
Definition: Inform.cpp:42
void collect(std::ostringstream &states)
collect all best values from all other masters
Definition: MasterNode.h:115
char * serialized_best_values_
pointer to MPI window holding current best solution state
Definition: MasterNode.h:158
std::vector< size_t > revision_state_
revision numbers of my neighbors
Definition: MasterNode.h:176
void store(char *local_state, size_t buffer_size)
store my best values
Definition: MasterNode.h:98
MPI_Win win_
Definition: MasterNode.h:166
MPI_Comm master_comm_
Definition: MasterNode.h:163
MasterNode(MPI_Comm master_comm, size_t buf_size_upper_bound, size_t dim, int island_id)
Definition: MasterNode.h:60
size_t myID_
Definition: MasterNode.h:169
size_t revision_
my solution state revision number
Definition: MasterNode.h:174
MPI_Win win_rev_
Definition: MasterNode.h:167
size_t buf_size_upper_bound_
and upper bound on the allocated memory in the MPI window
Definition: MasterNode.h:161
std::set< size_t > collectFrom_
neighbors we collect solution states from
Definition: MasterNode.h:172
size_t numMasters_
Definition: MasterNode.h:162