ALPSCore reference
mpiadapter.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1998-2018 ALPS Collaboration. See COPYRIGHT.TXT
3  * All rights reserved. Use is subject to license terms. See LICENSE.TXT
4  * For use in publications, see ACKNOWLEDGE.TXT
5  */
6 
7 #pragma once
8 
9 #include <boost/function.hpp>
10 #include <boost/utility/enable_if.hpp>
11 
12 #include <alps/config.hpp>
13 
14 #if defined(ALPS_HAVE_MPI)
15 
18 
19 namespace alps {
20 
21  namespace detail {
22 
24 
25  template<typename Base, typename ScheduleChecker> class mcmpiadapter_base : public Base {
26 
27  public:
28  typedef typename Base::parameters_type parameters_type;
29 
30  protected:
32 
44  mcmpiadapter_base(
45  parameters_type const & parameters
46  , alps::mpi::communicator const & comm
47  , ScheduleChecker const & check
48  , int rng_seed_step
49  , int rng_seed_base
50  )
51  : Base(parameters, comm.rank()*rng_seed_step + rng_seed_base)
52  , communicator(comm)
53  , schedule_checker(check)
54  , clone(comm.rank())
55  {}
56 
57  public:
58  double fraction_completed() const {
59  return fraction;
60  }
61 
62  bool run(boost::function<bool ()> const & stop_callback) {
63  bool done = false, stopped = false;
64  do {
65  this->update();
66  this->measure();
67  if (stopped || schedule_checker.pending()) {
68  stopped = stop_callback();
69  double local_fraction = stopped ? 1. : Base::fraction_completed();
70  schedule_checker.update(fraction = alps::mpi::all_reduce(communicator, local_fraction, std::plus<double>()));
71  done = fraction >= 1.;
72  }
73  } while(!done);
74  return !stopped;
75  }
76 
77  typename Base::results_type collect_results() const {
78  return collect_results(this->result_names());
79  }
80 
81  typename Base::results_type collect_results(typename Base::result_names_type const & names) const {
82  typename Base::results_type partial_results;
83  for(typename Base::result_names_type::const_iterator it = names.begin(); it != names.end(); ++it) {
84  size_t has_count=(this->measurements[*it].count() > 0);
85  const size_t sum_counts =
86  alps::mpi::all_reduce(communicator,
87  has_count,
88  std::plus<size_t>());
89  if (static_cast<int>(sum_counts) == communicator.size()) {
90  typename Base::observable_collection_type::value_type merged = this->measurements[*it];
91  merged.collective_merge(communicator, 0);
92  partial_results.insert(*it, merged.result());
93  } else if (sum_counts > 0 && static_cast<int>(sum_counts) < communicator.size()) {
94  throw std::runtime_error(*it + " was measured on only some of the MPI processes.");
95  }
96  }
97  return partial_results;
98  }
99 
100  protected:
101 
102  alps::mpi::communicator communicator;
103 
104  ScheduleChecker schedule_checker;
105  double fraction;
106  int clone;
107  };
108  } // detail::
109 
110 
112  template<typename Base, typename ScheduleChecker = alps::check_schedule> class mcmpiadapter : public detail::mcmpiadapter_base<Base,ScheduleChecker> {
113  private:
114  typedef detail::mcmpiadapter_base<Base,ScheduleChecker> base_type_;
115 
116  public:
117  typedef typename base_type_::parameters_type parameters_type;
118 
120 
138  // Just forwards to the base class constructor
139  mcmpiadapter(
140  parameters_type const & parameters
141  , alps::mpi::communicator const & comm
142  , ScheduleChecker const & check
143  , int rng_seed_step = 1
144  , int rng_seed_base = 0
145  )
146  : base_type_(parameters, comm, check, rng_seed_step, rng_seed_base)
147  {}
148  };
149 
151  // partial specialization
152  template<typename Base> class mcmpiadapter<Base,alps::check_schedule> : public detail::mcmpiadapter_base<Base,alps::check_schedule> {
153  private:
154  typedef alps::check_schedule ScheduleChecker;
155  typedef detail::mcmpiadapter_base<Base,ScheduleChecker> base_type_;
156 
157  public:
158  typedef typename base_type_::parameters_type parameters_type;
159 
161 
179  // Just forwards to the base class constructor
180  mcmpiadapter(
181  parameters_type const & parameters
182  , alps::mpi::communicator const & comm
183  , ScheduleChecker const & check
184  , int rng_seed_step = 1
185  , int rng_seed_base = 0
186  )
187  : base_type_(parameters, comm, check, rng_seed_step, rng_seed_base)
188  {}
189 
191 
208  // constructs the ScheduleChecker object and then forwards the ctor
209  mcmpiadapter(
210  parameters_type const & parameters
211  , alps::mpi::communicator const & comm
212  , int rng_seed_step = 1
213  , int rng_seed_base = 0
214  )
215  : base_type_(parameters, comm, ScheduleChecker(parameters["Tmin"], parameters["Tmax"]), rng_seed_step, rng_seed_base)
216  { }
217 
219  static parameters_type& define_parameters(parameters_type & parameters) {
220  base_type_::define_parameters(parameters);
221  if (parameters.is_restored()) return parameters;
222  parameters.template define<std::size_t>("Tmin", 1, "minimum time to check if simulation has finished");
223  parameters.template define<std::size_t>("Tmax", 600, "maximum time to check if simulation has finished");
224  return parameters;
225  }
226  };
227 
228 }
229 
230 #endif
void all_reduce(const alps::mpi::communicator &comm, const T *val, int n, T *out_val, const OP &)
Performs MPI_Allreduce for array of a primitive type, T[n].
Definition: mpi.hpp:366
Encapsulation of an MPI communicator and some communicator-related operations.
Definition: mpi.hpp:111
result_names_type< S >::type result_names(S const &s)
Definition: api.hpp:29
double fraction_completed(S const &s)
Definition: api.hpp:49
results_type< S >::type collect_results(S const &s)
Definition: api.hpp:37
detail::generic_check_schedule< detail::posix_wall_clock > check_schedule