MCKL
Monte Carlo Kernel Library
backend_base.hpp
Go to the documentation of this file.
1 //============================================================================
2 // MCKL/include/mckl/smp/backend_base.hpp
3 //----------------------------------------------------------------------------
4 // MCKL: Monte Carlo Kernel Library
5 //----------------------------------------------------------------------------
6 // Copyright (c) 2013-2018, 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 MCKL_SMP_BACKEND_BASE_HPP
33 #define MCKL_SMP_BACKEND_BASE_HPP
34 
35 #include <mckl/internal/common.hpp>
36 #include <mckl/core/particle.hpp>
37 
38 MCKL_PUSH_CLANG_WARNING("-Wweak-vtables")
39 
40 #ifndef MCKL_SMP_BACKEND
43 #if MCKL_HAS_TBB
44 #define MCKL_SMP_BACKEND ::mckl::BackendTBB
45 #elif MCKL_HAS_OMP
46 #define MCKL_SMP_BACKEND ::mckl::BackendOMP
47 #else
48 #define MCKL_SMP_BACKEND ::mckl::BackendSTD
49 #endif
50 #endif
51 
52 #define MCKL_DEFINE_SMP_BACKEND_BASE_SPECIAL(Name) \
53  Name##Base() = default; \
54  Name##Base(const Name##Base<T, Derived> &) = default; \
55  Name##Base<T, Derived> &operator=(const Name##Base<T, Derived> &) = \
56  default; \
57  Name##Base(Name##Base<T, Derived> &&) = default; \
58  Name##Base<T, Derived> &operator=(Name##Base<T, Derived> &&) = default;
59 
60 #define MCKL_DEFINE_SMP_BACKEND_BASE_SPECIAL_VIRTUAL(Name) \
61  Name##Base() = default; \
62  Name##Base(const Name##Base<T, Virtual> &) = default; \
63  Name##Base<T, Virtual> &operator=(const Name##Base<T, Virtual> &) = \
64  default; \
65  Name##Base(Name##Base<T, Virtual> &&) = default; \
66  Name##Base<T, Virtual> &operator=(Name##Base<T, Virtual> &&) = default; \
67  virtual ~Name##Base() = default;
68 
69 #define MCKL_DEFINE_SMP_BACKEND_SPECIAL(Impl, Name) \
70  Name##SMP() = default; \
71  Name##SMP(const Name##SMP<T, Derived, Backend##Impl> &) = default; \
72  Name##SMP<T, Derived, Backend##Impl> &operator=( \
73  const Name##SMP<T, Derived, Backend##Impl> &) = default; \
74  Name##SMP(Name##SMP<T, Derived, Backend##Impl> &&) = default; \
75  Name##SMP<T, Derived, Backend##Impl> &operator=( \
76  Name##SMP<T, Derived, Backend##Impl> &&) = default;
77 
78 namespace mckl {
79 
82 class BackendSEQ;
83 
86 class BackendSTD;
87 
90 class BackendOMP;
91 
94 class BackendTBB;
95 
99 
102 template <typename T, typename = Virtual, typename = BackendSMP>
104 
107 template <typename T, typename = Virtual, typename = BackendSMP>
109 
112 template <typename T, typename Derived>
114 {
115  protected:
117 
118  void eval_each(std::size_t iter, ParticleIndex<T> idx)
119  {
120  eval_dispatch(iter, idx, &Derived::eval_each);
121  }
122 
123  void eval_range(std::size_t iter, const ParticleRange<T> &range)
124  {
125  eval_range_dispatch(iter, range, &Derived::eval_range);
126  }
127 
128  void eval_first(std::size_t iter, Particle<T> &particle)
129  {
130  eval_first_dispatch(iter, particle, &Derived::eval_first);
131  }
132 
133  void eval_last(std::size_t iter, Particle<T> &particle)
134  {
135  eval_last_dispatch(iter, particle, &Derived::eval_last);
136  }
137 
138  private:
139  // non-static non-const
140 
141  template <typename D>
142  void eval_dispatch(std::size_t iter, ParticleIndex<T> idx,
143  void (D::*)(std::size_t, ParticleIndex<T>))
144  {
145  static_cast<Derived *>(this)->eval_each(iter, idx);
146  }
147 
148  template <typename D>
149  void eval_range_dispatch(std::size_t iter, const ParticleRange<T> &range,
150  void (D::*)(std::size_t, const ParticleRange<T> &))
151  {
152  static_cast<Derived *>(this)->eval_range(iter, range);
153  }
154 
155  template <typename D>
156  void eval_first_dispatch(std::size_t iter, Particle<T> &particle,
157  void (D::*)(std::size_t, Particle<T> &))
158  {
159  static_cast<Derived *>(this)->eval_first(iter, particle);
160  }
161 
162  template <typename D>
163  void eval_last_dispatch(std::size_t iter, Particle<T> &particle,
164  void (D::*)(std::size_t, Particle<T> &))
165  {
166  static_cast<Derived *>(this)->eval_last(iter, particle);
167  }
168 
169  // non-static const
170 
171  template <typename D>
172  void eval_dispatch(std::size_t iter, ParticleIndex<T> idx,
173  void (D::*)(std::size_t, ParticleIndex<T>) const)
174  {
175  static_cast<Derived *>(this)->eval_each(iter, idx);
176  }
177 
178  template <typename D>
179  void eval_range_dispatch(std::size_t iter, const ParticleRange<T> &range,
180  void (D::*)(std::size_t, const ParticleRange<T> &) const)
181  {
182  static_cast<Derived *>(this)->eval_range(iter, range);
183  }
184 
185  template <typename D>
186  void eval_first_dispatch(std::size_t iter, Particle<T> &particle,
187  void (D::*)(std::size_t, Particle<T> &) const)
188  {
189  static_cast<Derived *>(this)->eval_first(iter, particle);
190  }
191 
192  template <typename D>
193  void eval_last_dispatch(std::size_t iter, Particle<T> &particle,
194  void (D::*)(std::size_t, Particle<T> &) const)
195  {
196  static_cast<Derived *>(this)->eval_last(iter, particle);
197  }
198 
199  // static
200 
201  void eval_dispatch(std::size_t iter, ParticleIndex<T> idx,
202  void (*)(std::size_t, ParticleIndex<T>))
203  {
204  Derived::eval_each(iter, idx);
205  }
206 
207  void eval_range_dispatch(std::size_t iter, const ParticleRange<T> &range,
208  void (*)(std::size_t, const ParticleRange<T> &))
209  {
210  Derived::eval_range(iter, range);
211  }
212 
213  void eval_first_dispatch(std::size_t iter, Particle<T> &particle,
214  void (*)(std::size_t, Particle<T> &))
215  {
216  Derived::eval_first(iter, particle);
217  }
218 
219  void eval_last_dispatch(std::size_t iter, Particle<T> &particle,
220  void (*)(std::size_t, Particle<T> &))
221  {
222  Derived::eval_last(iter, particle);
223  }
224 
225  // base
226 
227  void eval_dispatch(std::size_t, ParticleIndex<T>,
228  void (SMCSamplerEvalBase::*)(std::size_t, ParticleIndex<T>))
229  {
230  }
231 
232  void eval_range_dispatch(std::size_t iter, const ParticleRange<T> &range,
233  void (SMCSamplerEvalBase::*)(std::size_t, const ParticleRange<T> &))
234  {
235  for (auto idx : range) {
236  eval_each(iter, idx);
237  }
238  }
239 
240  void eval_first_dispatch(std::size_t, Particle<T> &,
241  void (SMCSamplerEvalBase::*)(std::size_t, Particle<T> &))
242  {
243  }
244 
245  void eval_last_dispatch(std::size_t, Particle<T> &,
246  void (SMCSamplerEvalBase::*)(std::size_t, Particle<T> &))
247  {
248  }
249 }; // class SMCSamplerEvalBase
250 
253 template <typename T>
254 class SMCSamplerEvalBase<T, Virtual>
255 {
256  protected:
258 
259  virtual void eval_each(std::size_t, ParticleIndex<T>) {}
260 
261  virtual void eval_range(std::size_t iter, const ParticleRange<T> &range)
262  {
263  for (auto idx : range) {
264  eval_each(iter, idx);
265  }
266  }
267 
268  virtual void eval_first(std::size_t, Particle<T> &) {}
269 
270  virtual void eval_last(std::size_t, Particle<T> &) {}
271 }; // class SMCSamplerEvalBase<T, Virtual>
272 
275 template <typename T, typename Derived>
277 {
278  protected:
279  MCKL_DEFINE_SMP_BACKEND_BASE_SPECIAL(SMCEstimatorEval)
280 
281  void eval_each(
282  std::size_t iter, std::size_t dim, ParticleIndex<T> idx, double *r)
283  {
284  eval_dispatch(iter, dim, idx, r, &Derived::eval_each);
285  }
286 
287  void eval_range(std::size_t iter, std::size_t dim,
288  const ParticleRange<T> &range, double *r)
289  {
290  eval_range_dispatch(iter, dim, range, r, &Derived::eval_range);
291  }
292 
293  void eval_first(std::size_t iter, Particle<T> &particle)
294  {
295  eval_first_dispatch(iter, particle, &Derived::eval_first);
296  }
297 
298  void eval_last(std::size_t iter, Particle<T> &particle)
299  {
300  eval_last_dispatch(iter, particle, &Derived::eval_last);
301  }
302 
303  private:
304  // non-static non-const
305 
306  template <typename D>
307  void eval_dispatch(std::size_t iter, std::size_t dim, ParticleIndex<T> idx,
308  double *r,
309  void (D::*)(std::size_t, std::size_t, ParticleIndex<T>, double *))
310  {
311  static_cast<Derived *>(this)->eval_each(iter, dim, idx, r);
312  }
313 
314  template <typename D>
315  void eval_range_dispatch(std::size_t iter, std::size_t dim,
316  const ParticleRange<T> &range, double *r,
317  void (D::*)(
318  std::size_t, std::size_t, const ParticleRange<T> &, double *))
319  {
320  static_cast<Derived *>(this)->eval_range(iter, dim, range, r);
321  }
322 
323  template <typename D>
324  void eval_first_dispatch(std::size_t iter, Particle<T> &particle,
325  void (D::*)(std::size_t, Particle<T> &))
326  {
327  static_cast<Derived *>(this)->eval_first(iter, particle);
328  }
329 
330  template <typename D>
331  void eval_last_dispatch(std::size_t iter, Particle<T> &particle,
332  void (D::*)(std::size_t, Particle<T> &))
333  {
334  static_cast<Derived *>(this)->eval_last(iter, particle);
335  }
336 
337  // non-static const
338 
339  template <typename D>
340  void eval_dispatch(std::size_t iter, std::size_t dim, ParticleIndex<T> idx,
341  double *r,
342  void (D::*)(std::size_t, std::size_t, ParticleIndex<T>, double *)
343  const)
344  {
345  static_cast<Derived *>(this)->eval_each(iter, dim, idx, r);
346  }
347 
348  template <typename D>
349  void eval_range_dispatch(std::size_t iter, std::size_t dim,
350  const ParticleRange<T> &range, double *r,
351  void (D::*)(std::size_t, std::size_t, const ParticleRange<T> &,
352  double *) const)
353  {
354  static_cast<Derived *>(this)->eval_range(iter, dim, range, r);
355  }
356 
357  template <typename D>
358  void eval_first_dispatch(std::size_t iter, Particle<T> &particle,
359  void (D::*)(std::size_t, Particle<T> &) const)
360  {
361  static_cast<Derived *>(this)->eval_first(iter, particle);
362  }
363 
364  template <typename D>
365  void eval_last_dispatch(std::size_t iter, Particle<T> &particle,
366  void (D::*)(std::size_t, Particle<T> &) const)
367  {
368  static_cast<Derived *>(this)->eval_last(iter, particle);
369  }
370 
371  // static
372 
373  void eval_dispatch(std::size_t iter, std::size_t dim, ParticleIndex<T> idx,
374  double *r,
375  void (*)(std::size_t, std::size_t, ParticleIndex<T>, double *))
376  {
377  Derived::eval_each(iter, dim, idx, r);
378  }
379 
380  void eval_range_dispatch(std::size_t iter, std::size_t dim,
381  const ParticleRange<T> &range, double *r,
382  void (*)(std::size_t, std::size_t, const ParticleRange<T> &, double *))
383  {
384  Derived::eval_range(iter, dim, range, r);
385  }
386 
387  void eval_first_dispatch(std::size_t iter, Particle<T> &particle,
388  void (*)(std::size_t, Particle<T> &))
389  {
390  Derived::eval_first(iter, particle);
391  }
392 
393  void eval_last_dispatch(std::size_t iter, Particle<T> &particle,
394  void (*)(std::size_t, Particle<T> &))
395  {
396  Derived::eval_last(iter, particle);
397  }
398 
399  // base
400 
401  void eval_dispatch(std::size_t, std::size_t, ParticleIndex<T>, double *,
402  void (SMCEstimatorEvalBase::*)(
403  std::size_t, std::size_t, ParticleIndex<T>, double *))
404  {
405  }
406 
407  void eval_range_dispatch(std::size_t iter, std::size_t dim,
408  const ParticleRange<T> &range, double *r,
409  void (SMCEstimatorEvalBase::*)(
410  std::size_t, std::size_t, const ParticleRange<T> &, double *))
411  {
412  for (auto idx : range) {
413  eval_each(iter, dim, idx, r);
414  r += dim;
415  }
416  }
417 
418  void eval_first_dispatch(std::size_t, Particle<T> &,
419  void (SMCEstimatorEvalBase::*)(std::size_t, Particle<T> &))
420  {
421  }
422 
423  void eval_last_dispatch(std::size_t, Particle<T> &,
424  void (SMCEstimatorEvalBase::*)(std::size_t, Particle<T> &))
425  {
426  }
427 }; // class SMCEstimatorBase
428 
431 template <typename T>
432 class SMCEstimatorEvalBase<T, Virtual>
433 {
434  protected:
436 
437  virtual void eval_each(
438  std::size_t, std::size_t, ParticleIndex<T>, double *)
439  {
440  }
441 
442  virtual void eval_range(std::size_t iter, std::size_t dim,
443  const ParticleRange<T> &range, double *r)
444  {
445  for (auto idx : range) {
446  eval_each(iter, dim, idx, r);
447  r += dim;
448  }
449  }
450 
451  virtual void eval_first(std::size_t, Particle<T> &) {}
452 
453  virtual void eval_last(std::size_t, Particle<T> &) {}
454 }; // class SMCEstimatorEvalBase<T, Virtual>
455 
456 } // namespace mckl
457 
459 
460 #endif // MCKL_SMP_BACKEND_BASE_HPP
virtual void eval_range(std::size_t iter, const ParticleRange< T > &range)
SMCSampler evaluation base dispatch class.
void eval_range(std::size_t iter, std::size_t dim, const ParticleRange< T > &range, double *r)
virtual void eval_last(std::size_t, Particle< T > &)
#define MCKL_PUSH_CLANG_WARNING(warning)
Definition: compiler.h:63
STL namespace.
#define MCKL_DEFINE_SMP_BACKEND_BASE_SPECIAL_VIRTUAL(Name)
virtual void eval_first(std::size_t, Particle< T > &)
Range of ParticleIndex.
Definition: particle.hpp:251
virtual void eval_last(std::size_t, Particle< T > &)
SMCSMCSampler<T>::eval_type.
void eval_first(std::size_t iter, Particle< T > &particle)
#define MCKL_SMP_BACKEND
Default SMP backend.
virtual void eval_first(std::size_t, Particle< T > &)
void eval_last(std::size_t iter, Particle< T > &particle)
void eval_each(std::size_t iter, ParticleIndex< T > idx)
::mckl::BackendTBB BackendSMP
SMP default implementation ID.
#define MCKL_DEFINE_SMP_BACKEND_BASE_SPECIAL(Name)
SMCEstimator<T>::eval_type.
Definition: mcmc.hpp:40
#define MCKL_POP_CLANG_WARNING
Definition: compiler.h:66
SMCEstimator evalution base dispatch class.
A thin wrapper over a complete Particle.
Definition: particle.hpp:86
void eval_last(std::size_t iter, Particle< T > &particle)
virtual void eval_range(std::size_t iter, std::size_t dim, const ParticleRange< T > &range, double *r)
Particle system.
Definition: particle.hpp:45
void eval_first(std::size_t iter, Particle< T > &particle)
void eval_range(std::size_t iter, const ParticleRange< T > &range)