vSMC  v3.0.0
Scalable Monte Carlo
backend_std.hpp
Go to the documentation of this file.
1 //============================================================================
2 // vSMC/include/vsmc/smp/backend_std.hpp
3 //----------------------------------------------------------------------------
4 // vSMC: Scalable Monte Carlo
5 //----------------------------------------------------------------------------
6 // Copyright (c) 2013-2016, Yan Zhou
7 // All rights reserved.
8 //
9 // Redistribution and use in source and binary forms, with or without
10 // modification, are permitted provided that the following conditions are met:
11 //
12 // Redistributions of source code must retain the above copyright notice,
13 // this list of conditions and the following disclaimer.
14 //
15 // Redistributions in binary form must reproduce the above copyright notice,
16 // this list of conditions and the following disclaimer in the documentation
17 // and/or other materials provided with the distribution.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS
20 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 // POSSIBILITY OF SUCH DAMAGE.
30 //============================================================================
31 
32 #ifndef VSMC_SMP_BACKEND_STD_HPP
33 #define VSMC_SMP_BACKEND_STD_HPP
34 
36 
37 namespace vsmc
38 {
39 
40 namespace internal
41 {
42 
43 template <typename IntType>
44 inline void backend_std_range(
45  IntType N, vsmc::Vector<IntType> &begin, vsmc::Vector<IntType> &end)
46 {
47  begin.clear();
48  end.clear();
49  const IntType np = std::max(static_cast<IntType>(1),
50  static_cast<IntType>(std::thread::hardware_concurrency()));
51  if (np == 1) {
52  begin.push_back(0);
53  end.push_back(N);
54  return;
55  }
56 
57  const IntType m = N / np;
58  const IntType r = N % np;
59  for (IntType id = 0; id != np; ++id) {
60  const IntType n = m + (id < r ? 1 : 0);
61  begin.push_back(id < r ? n * id : (n + 1) * r + n * (id - r));
62  end.push_back(begin.back() + n);
63  }
64 }
65 
66 } // namespace internal
67 
70 template <typename T, typename Derived>
71 class SamplerEvalSMP<T, Derived, BackendSTD>
72  : public SamplerEvalBase<T, Derived>
73 {
74  public:
75  std::size_t operator()(std::size_t iter, Particle<T> &particle)
76  {
77  using size_type = typename Particle<T>::size_type;
78 
79  this->eval_pre(iter, particle);
82  internal::backend_std_range(particle.size(), begin, end);
84  for (std::size_t i = 0; i != begin.size(); ++i) {
85  const size_type b = begin[i];
86  const size_type e = end[i];
87  task_group.push_back(std::async(
88  std::launch::async, [this, iter, &particle, b, e]() {
89  return this->eval_range(iter, particle.range(b, e));
90  }));
91  }
92  std::size_t accept = 0;
93  for (auto &task : task_group)
94  accept += task.get();
95  this->eval_post(iter, particle);
96 
97  return accept;
98  }
99 
100  protected:
101  VSMC_DEFINE_SMP_BACKEND_SPECIAL(STD, SamplerEval)
102 }; // class SamplerEvalSMP
103 
106 template <typename T, typename Derived>
107 class MonitorEvalSMP<T, Derived, BackendSTD>
108  : public MonitorEvalBase<T, Derived>
109 {
110  public:
112  std::size_t iter, std::size_t dim, Particle<T> &particle, double *r)
113  {
114  using size_type = typename Particle<T>::size_type;
115 
116  this->eval_pre(iter, particle);
119  internal::backend_std_range(particle.size(), begin, end);
120  vsmc::Vector<std::future<void>> task_group;
121  for (std::size_t i = 0; i != begin.size(); ++i) {
122  const size_type b = begin[i];
123  const size_type e = end[i];
124  task_group.push_back(std::async(
125  std::launch::async, [this, iter, dim, &particle, r, b, e]() {
126  this->eval_range(iter, dim, particle.range(b, e),
127  r + static_cast<std::size_t>(b) * dim);
128  }));
129  }
130  for (auto &task : task_group)
131  task.wait();
132  this->eval_post(iter, particle);
133  }
134 
135  protected:
136  VSMC_DEFINE_SMP_BACKEND_SPECIAL(STD, MonitorEval)
137 }; // class MonitorEvalSMP
138 
141 template <typename T, typename Derived>
143 
146 template <typename T, typename Derived>
148 
149 } // namespace vsmc
150 
151 #endif // VSMC_SMP_BACKEND_STD_HPP
std::vector< T, Alloc > Vector
std::vector with Allocator as default allocator
range_type range(size_type begin, size_type end)
Get a ParticleRange<T> object.
Definition: particle.hpp:207
Definition: monitor.hpp:48
SizeType< T > size_type
Definition: particle.hpp:86
Particle class representing the whole particle set.
Definition: particle.hpp:83
Monitor<T>::eval_type.
Monitor evalution base dispatch class.
std::size_t operator()(std::size_t iter, Particle< T > &particle)
Definition: backend_std.hpp:75
#define VSMC_DEFINE_SMP_BACKEND_SPECIAL(Impl, Name)
Monitor<T>::eval_type subtype using the standard library.
void backend_std_range(IntType N, vsmc::Vector< IntType > &begin, vsmc::Vector< IntType > &end)
Definition: backend_std.hpp:44
Sampler evaluation base dispatch class.
Sampler<T>::eval_type.
Sampler<T>::eval_type subtype using the standard library.
Definition: backend_std.hpp:71
void operator()(std::size_t iter, std::size_t dim, Particle< T > &particle, double *r)
size_type size() const
Number of particles.
Definition: particle.hpp:120