vSMC  v3.0.0
Scalable Monte Carlo
backend_base.hpp
Go to the documentation of this file.
1 //============================================================================
2 // vSMC/include/vsmc/smp/backend_base.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_BASE_HPP
33 #define VSMC_SMP_BACKEND_BASE_HPP
34 
35 #include <vsmc/internal/common.hpp>
36 
37 #ifdef VSMC_CLANG
38 #pragma clang diagnostic push
39 #pragma clang diagnostic ignored "-Wweak-vtables"
40 #endif
41 
44 #ifndef VSMC_SMP_BACKEND
45 #if VSMC_HAS_OMP
46 #define VSMC_SMP_BACKEND ::vsmc::BackendOMP
47 #elif VSMC_HAS_TBB
48 #define VSMC_SMP_BACKEND ::vsmc::BackendTBB
49 #else
50 #define VSMC_SMP_BACKEND ::vsmc::BackendSTD
51 #endif
52 #endif
53 
54 #define VSMC_DEFINE_SMP_BACKEND_BASE_SPECIAL(Name) \
55  Name##Base() = default; \
56  Name##Base(const Name##Base<T, Derived> &) = default; \
57  Name##Base<T, Derived> &operator=(const Name##Base<T, Derived> &) = \
58  default; \
59  Name##Base(Name##Base<T, Derived> &&) = default; \
60  Name##Base<T, Derived> &operator=(Name##Base<T, Derived> &&) = default;
61 
62 #define VSMC_DEFINE_SMP_BACKEND_BASE_SPECIAL_VIRTUAL(Name) \
63  Name##Base() = default; \
64  Name##Base(const Name##Base<T, Virtual> &) = default; \
65  Name##Base<T, Virtual> &operator=(const Name##Base<T, Virtual> &) = \
66  default; \
67  Name##Base(Name##Base<T, Virtual> &&) = default; \
68  Name##Base<T, Virtual> &operator=(Name##Base<T, Virtual> &&) = default; \
69  virtual ~Name##Base() {}
70 
71 #define VSMC_DEFINE_SMP_BACKEND_SPECIAL(Impl, Name) \
72  Name##SMP() = default; \
73  Name##SMP(const Name##SMP<T, Derived, Backend##Impl> &) = default; \
74  Name##SMP<T, Derived, Backend##Impl> &operator=( \
75  Name##SMP<T, Derived, Backend##Impl> &) = default; \
76  Name##SMP(Name##SMP<T, Derived, Backend##Impl> &&) = default; \
77  Name##SMP<T, Derived, Backend##Impl> &operator=( \
78  Name##SMP<T, Derived, Backend##Impl> &&) = default;
79 
80 namespace vsmc
81 {
82 
85 class BackendSEQ;
86 
89 class BackendSTD;
90 
93 class BackendOMP;
94 
97 class BackendTBB;
98 
102 class Virtual;
103 
106 template <typename T, typename = Virtual, typename = VSMC_SMP_BACKEND>
108 
111 template <typename T, typename = Virtual, typename = VSMC_SMP_BACKEND>
113 
116 template <typename T, typename Derived>
118 {
119  public:
120  std::size_t eval_sp(std::size_t iter, SingleParticle<T> sp)
121  {
122  return eval_sp_dispatch(iter, sp, &Derived::eval_sp);
123  }
124 
125  std::size_t eval_range(std::size_t iter, ParticleRange<T> range)
126  {
127  return eval_range_dispatch(iter, range, &Derived::eval_range);
128  }
129 
130  void eval_pre(std::size_t iter, Particle<T> &particle)
131  {
132  eval_pre_dispatch(iter, particle, &Derived::eval_pre);
133  }
134 
135  void eval_post(std::size_t iter, Particle<T> &particle)
136  {
137  eval_post_dispatch(iter, particle, &Derived::eval_post);
138  }
139 
140  protected:
142 
143  private:
144  // non-static non-const
145 
146  template <typename D>
147  std::size_t eval_sp_dispatch(std::size_t iter, SingleParticle<T> sp,
148  std::size_t (D::*)(std::size_t, SingleParticle<T>))
149  {
150  return static_cast<Derived *>(this)->eval_sp(iter, sp);
151  }
152 
153  template <typename D>
154  std::size_t eval_range_dispatch(std::size_t iter, ParticleRange<T> range,
155  std::size_t (D::*)(std::size_t, ParticleRange<T>))
156  {
157  return static_cast<Derived *>(this)->eval_range(iter, range);
158  }
159 
160  template <typename D>
161  void eval_pre_dispatch(std::size_t iter, Particle<T> &particle,
162  void (D::*)(std::size_t, Particle<T> &))
163  {
164  static_cast<Derived *>(this)->eval_pre(iter, particle);
165  }
166 
167  template <typename D>
168  void eval_post_dispatch(std::size_t iter, Particle<T> &particle,
169  void (D::*)(std::size_t, Particle<T> &))
170  {
171  static_cast<Derived *>(this)->eval_post(iter, particle);
172  }
173 
174  // non-static const
175 
176  template <typename D>
177  std::size_t eval_sp_dispatch(std::size_t iter, SingleParticle<T> sp,
178  std::size_t (D::*)(std::size_t, SingleParticle<T>) const)
179  {
180  return static_cast<Derived *>(this)->eval_sp(iter, sp);
181  }
182 
183  template <typename D>
184  std::size_t eval_range_dispatch(std::size_t iter, ParticleRange<T> range,
185  std::size_t (D::*)(std::size_t, ParticleRange<T>) const)
186  {
187  return static_cast<Derived *>(this)->eval_range(iter, range);
188  }
189 
190  template <typename D>
191  void eval_pre_dispatch(std::size_t iter, Particle<T> &particle,
192  void (D::*)(std::size_t, Particle<T> &) const)
193  {
194  static_cast<Derived *>(this)->eval_pre(iter, particle);
195  }
196 
197  template <typename D>
198  void eval_post_dispatch(std::size_t iter, Particle<T> &particle,
199  void (D::*)(std::size_t, Particle<T> &) const)
200  {
201  static_cast<Derived *>(this)->eval_post(iter, particle);
202  }
203 
204  // static
205 
206  std::size_t eval_sp_dispatch(std::size_t iter, SingleParticle<T> sp,
207  std::size_t (*)(std::size_t, SingleParticle<T>))
208  {
209  return Derived::eval_sp(iter, sp);
210  }
211 
212  std::size_t eval_range_dispatch(std::size_t iter, ParticleRange<T> range,
213  std::size_t (*)(std::size_t, ParticleRange<T>))
214  {
215  return Derived::eval_range(iter, range);
216  }
217 
218  void eval_pre_dispatch(std::size_t iter, Particle<T> &particle,
219  void (*)(std::size_t, Particle<T> &))
220  {
221  Derived::eval_pre(iter, particle);
222  }
223 
224  void eval_post_dispatch(std::size_t iter, Particle<T> &particle,
225  void (*)(std::size_t, Particle<T> &))
226  {
227  Derived::eval_post(iter, particle);
228  }
229 
230  // base
231 
232  std::size_t eval_sp_dispatch(std::size_t, SingleParticle<T>,
233  std::size_t (SamplerEvalBase::*)(std::size_t, SingleParticle<T>))
234  {
235  return 0;
236  }
237 
238  std::size_t eval_range_dispatch(std::size_t iter, ParticleRange<T> range,
239  std::size_t (SamplerEvalBase::*)(std::size_t, ParticleRange<T>))
240  {
241  using size_type = typename Particle<T>::size_type;
242 
243  std::size_t accept = 0;
244  for (size_type i = range.begin(); i != range.end(); ++i)
245  accept += eval_sp(iter, range.particle().sp(i));
246 
247  return accept;
248  }
249 
250  void eval_pre_dispatch(std::size_t, Particle<T> &,
251  void (SamplerEvalBase::*)(std::size_t, Particle<T> &))
252  {
253  }
254 
255  void eval_post_dispatch(std::size_t, Particle<T> &,
256  void (SamplerEvalBase::*)(std::size_t, Particle<T> &))
257  {
258  }
259 }; // class SamplerEvalBase
260 
263 template <typename T>
264 class SamplerEvalBase<T, Virtual>
265 {
266  public:
267  virtual std::size_t eval_sp(std::size_t, SingleParticle<T>) { return 0; }
268 
269  virtual std::size_t eval_range(std::size_t iter, ParticleRange<T> range)
270  {
271  using size_type = typename Particle<T>::size_type;
272 
273  std::size_t accept = 0;
274  for (size_type i = range.begin(); i != range.end(); ++i)
275  accept += eval_sp(iter, range.particle().sp(i));
276 
277  return accept;
278  }
279 
280  virtual void eval_pre(std::size_t, Particle<T> &) {}
281 
282  virtual void eval_post(std::size_t, Particle<T> &) {}
283 
284  protected:
286 }; // class SamplerEvalBase<T, Virtual>
287 
290 template <typename T, typename Derived>
292 {
293  public:
294  void eval_sp(
295  std::size_t iter, std::size_t dim, SingleParticle<T> sp, double *r)
296  {
297  eval_sp_dispatch(iter, dim, sp, r, &Derived::eval_sp);
298  }
299 
301  std::size_t iter, std::size_t dim, ParticleRange<T> range, double *r)
302  {
303  eval_range_dispatch(iter, dim, range, r, &Derived::eval_range);
304  }
305 
306  void eval_pre(std::size_t iter, Particle<T> &particle)
307  {
308  eval_pre_dispatch(iter, particle, &Derived::eval_pre);
309  }
310 
311  void eval_post(std::size_t iter, Particle<T> &particle)
312  {
313  eval_post_dispatch(iter, particle, &Derived::eval_post);
314  }
315 
316  protected:
318 
319  private:
320  // non-static non-const
321 
322  template <typename D>
323  void eval_sp_dispatch(std::size_t iter, std::size_t dim,
324  SingleParticle<T> sp, double *r,
325  void (D::*)(std::size_t, std::size_t, SingleParticle<T>, double *))
326  {
327  static_cast<Derived *>(this)->eval_sp(iter, dim, sp, r);
328  }
329 
330  template <typename D>
331  void eval_range_dispatch(std::size_t iter, std::size_t dim,
332  ParticleRange<T> range, double *r,
333  void (D::*)(std::size_t, std::size_t, ParticleRange<T>, double *))
334  {
335  static_cast<Derived *>(this)->eval_range(iter, dim, range, r);
336  }
337 
338  template <typename D>
339  void eval_pre_dispatch(std::size_t iter, Particle<T> &particle,
340  void (D::*)(std::size_t, Particle<T> &))
341  {
342  static_cast<Derived *>(this)->eval_pre(iter, particle);
343  }
344 
345  template <typename D>
346  void eval_post_dispatch(std::size_t iter, Particle<T> &particle,
347  void (D::*)(std::size_t, Particle<T> &))
348  {
349  static_cast<Derived *>(this)->eval_post(iter, particle);
350  }
351 
352  // non-static const
353 
354  template <typename D>
355  void eval_sp_dispatch(std::size_t iter, std::size_t dim,
356  SingleParticle<T> sp, double *r,
357  void (D::*)(std::size_t, std::size_t, SingleParticle<T>, double *)
358  const)
359  {
360  static_cast<Derived *>(this)->eval_sp(iter, dim, sp, r);
361  }
362 
363  template <typename D>
364  void eval_range_dispatch(std::size_t iter, std::size_t dim,
365  ParticleRange<T> range, double *r,
366  void (D::*)(std::size_t, std::size_t, ParticleRange<T>, double *)
367  const)
368  {
369  static_cast<Derived *>(this)->eval_range(iter, dim, range, r);
370  }
371 
372  template <typename D>
373  void eval_pre_dispatch(std::size_t iter, Particle<T> &particle,
374  void (D::*)(std::size_t, Particle<T> &) const)
375  {
376  static_cast<Derived *>(this)->eval_pre(iter, particle);
377  }
378 
379  template <typename D>
380  void eval_post_dispatch(std::size_t iter, Particle<T> &particle,
381  void (D::*)(std::size_t, Particle<T> &) const)
382  {
383  static_cast<Derived *>(this)->eval_post(iter, particle);
384  }
385 
386  // static
387 
388  void eval_sp_dispatch(std::size_t iter, std::size_t dim,
389  SingleParticle<T> sp, double *r,
390  void (*)(std::size_t, std::size_t, SingleParticle<T>, double *))
391  {
392  Derived::eval_sp(iter, dim, sp, r);
393  }
394 
395  void eval_range_dispatch(std::size_t iter, std::size_t dim,
396  ParticleRange<T> range, double *r,
397  void (*)(std::size_t, std::size_t, ParticleRange<T>, double *))
398  {
399  Derived::eval_range(iter, dim, range, r);
400  }
401 
402  void eval_pre_dispatch(std::size_t iter, Particle<T> &particle,
403  void (*)(std::size_t, Particle<T> &))
404  {
405  Derived::eval_pre(iter, particle);
406  }
407 
408  void eval_post_dispatch(std::size_t iter, Particle<T> &particle,
409  void (*)(std::size_t, Particle<T> &))
410  {
411  Derived::eval_post(iter, particle);
412  }
413 
414  // base
415 
416  void eval_sp_dispatch(std::size_t, std::size_t, SingleParticle<T>,
417  double *, void (MonitorEvalBase::*)(std::size_t, std::size_t,
418  SingleParticle<T>, double *))
419  {
420  }
421 
422  void eval_range_dispatch(std::size_t iter, std::size_t dim,
423  ParticleRange<T> range, double *r,
424  void (MonitorEvalBase::*)(std::size_t, std::size_t, ParticleRange<T>,
425  double *))
426  {
427  using size_type = typename Particle<T>::size_type;
428 
429  for (size_type i = range.begin(); i != range.end(); ++i, r += dim)
430  eval_sp(iter, dim, range.particle().sp(i), r);
431  }
432 
433  void eval_pre_dispatch(std::size_t, Particle<T> &,
434  void (MonitorEvalBase::*)(std::size_t, Particle<T> &))
435  {
436  }
437 
438  void eval_post_dispatch(std::size_t, Particle<T> &,
439  void (MonitorEvalBase::*)(std::size_t, Particle<T> &))
440  {
441  }
442 }; // class MonitorBase
443 
446 template <typename T>
447 class MonitorEvalBase<T, Virtual>
448 {
449  public:
450  virtual void eval_sp(std::size_t, std::size_t, SingleParticle<T>, double *)
451  {
452  }
453 
454  virtual void eval_range(
455  std::size_t iter, std::size_t dim, ParticleRange<T> range, double *r)
456  {
457  using size_type = typename Particle<T>::size_type;
458 
459  for (size_type i = range.begin(); i != range.end(); ++i, r += dim)
460  eval_sp(iter, dim, range.particle().sp(i), r);
461  }
462 
463  virtual void eval_pre(std::size_t, Particle<T> &) {}
464 
465  virtual void eval_post(std::size_t, Particle<T> &) {}
466 
467  protected:
469 }; // class MonitorEvalBase<T, Virtual>
470 
471 } // namespace vsmc
472 
473 #ifdef VSMC_CLANG
474 #pragma clang diagnostic pop
475 #endif
476 
477 #endif // VSMC_SMP_BACKEND_BASE_HPP
Definition: monitor.hpp:48
SizeType< T > size_type
Definition: particle.hpp:86
Particle class representing the whole particle set.
Definition: particle.hpp:83
#define VSMC_DEFINE_SMP_BACKEND_BASE_SPECIAL(Name)
Monitor<T>::eval_type.
virtual void eval_post(std::size_t, Particle< T > &)
Monitor evalution base dispatch class.
void eval_sp(std::size_t iter, std::size_t dim, SingleParticle< T > sp, double *r)
std::size_t eval_sp(std::size_t iter, SingleParticle< T > sp)
void eval_post(std::size_t iter, Particle< T > &particle)
virtual std::size_t eval_sp(std::size_t, SingleParticle< T >)
void eval_range(std::size_t iter, std::size_t dim, ParticleRange< T > range, double *r)
A subset of particles.
Definition: particle.hpp:53
void eval_pre(std::size_t iter, Particle< T > &particle)
std::size_t eval_range(std::size_t iter, ParticleRange< T > range)
Sampler evaluation base dispatch class.
virtual void eval_pre(std::size_t, Particle< T > &)
Sampler<T>::eval_type.
void eval_post(std::size_t iter, Particle< T > &particle)
#define VSMC_DEFINE_SMP_BACKEND_BASE_SPECIAL_VIRTUAL(Name)
virtual std::size_t eval_range(std::size_t iter, ParticleRange< T > range)
virtual void eval_post(std::size_t, Particle< T > &)
virtual void eval_pre(std::size_t, Particle< T > &)
Particle< T > & particle() const
Definition: particle.hpp:62
Particle< T >::size_type begin() const
Definition: particle.hpp:68
A thin wrapper over a complete Particle.
virtual void eval_range(std::size_t iter, std::size_t dim, ParticleRange< T > range, double *r)
virtual void eval_sp(std::size_t, std::size_t, SingleParticle< T >, double *)
void eval_pre(std::size_t iter, Particle< T > &particle)
Particle< T >::size_type end() const
Definition: particle.hpp:70