vSMC
vSMC: Scalable Monte Carlo
backend_cl.hpp
Go to the documentation of this file.
1 //============================================================================
2 // vSMC/include/vsmc/opencl/backend_cl.hpp
3 //----------------------------------------------------------------------------
4 // vSMC: Scalable Monte Carlo
5 //----------------------------------------------------------------------------
6 // Copyright (c) 2013,2014, 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_OPENCL_BACKEND_CL_HPP
33 #define VSMC_OPENCL_BACKEND_CL_HPP
34 
35 #include <vsmc/internal/common.hpp>
38 #include <vsmc/opencl/cl_error.hpp>
40 #include <vsmc/opencl/cl_manip.hpp>
43 #include <vsmc/rng/seed.hpp>
44 #include <vsmc/utility/array.hpp>
45 
46 #define VSMC_STATIC_ASSERT_OPENCL_BACKEND_CL_DYNAMIC_STATE_SIZE_RESIZE(Dim) \
47  VSMC_STATIC_ASSERT((Dim == Dynamic), \
48  USE_METHOD_resize_state_WITH_A_FIXED_SIZE_StateCL_OBJECT)
49 
50 #define VSMC_STATIC_ASSERT_OPENCL_BACKEND_CL_STATE_CL_TYPE(derived, user) \
51  VSMC_STATIC_ASSERT((internal::IsDerivedFromStateCL<derived>::value), \
52  USE_##user##_WITH_A_STATE_TYPE_NOT_DERIVED_FROM_StateCL)
53 
54 #define VSMC_STATIC_ASSERT_OPENCL_BACKEND_CL_STATE_CL_FP_TYPE(type) \
55  VSMC_STATIC_ASSERT((cxx11::is_same<type, ::cl_float>::value \
56  || cxx11::is_same<type, ::cl_double>::value), \
57  USE_StateCL_WITH_A_FP_TYPE_OTHER_THAN_cl_float_AND_cl_double)
58 
59 #define VSMC_RUNTIME_ASSERT_OPENCL_BACKEND_CL_BUILD(func) \
60  VSMC_RUNTIME_ASSERT((build()), \
61  ("**StateCL::"#func"** CAN ONLY BE CALLED AFTER true " \
62  "**StateCL::build**"));
63 
64 #define VSMC_RUNTIME_ASSERT_OPENCL_BACKEND_CL_STATE_SIZE(state_size) \
65  VSMC_RUNTIME_ASSERT((state_size >= 1), ("STATE SIZE IS LESS THAN 1"))
66 
67 #define VSMC_RUNTIME_ASSERT_OPENCL_BACKEND_CL_COPY_SIZE_MISMATCH \
68  VSMC_RUNTIME_ASSERT((N == copy_.size()), \
69  ("**StateCL::copy** SIZE MISMATCH"))
70 
71 #define VSMC_RUNTIME_ASSERT_OPENCL_BACKEND_CL_UNPACK_SIZE(psize, dim) \
72  VSMC_RUNTIME_ASSERT((psize >= dim), \
73  ("**StateCL::state_unpack** INPUT PACK SIZE TOO SMALL"))
74 
75 #if VSMC_HAS_CXX11_DEFAULTED_FUNCTIONS
76 
77 #define VSMC_DEFINE_OPENCL_COPY(Name) \
78 Name () : build_id_(-1) {} \
79 Name (const Name<T, PlaceHolder> &) = default; \
80 Name<T, PlaceHolder> &operator= (const Name<T, PlaceHolder> &) = default; \
81 virtual ~Name () {}
82 
83 #if VSMC_HAS_CXX11_RVALUE_REFERENCES
84 #define VSMC_DEFINE_OPENCL_MOVE(Name) \
85 Name (Name<T, PlaceHolder> &&) = default; \
86 Name<T, PlaceHolder> &operator= (Name<T, PlaceHolder> &&) = default;
87 #else
88 #define VSMC_DEFINE_OPENCL_MOVE(Name)
89 #endif
90 
91 #else // VSMC_HAS_CXX11_DEFAULTED_FUNCTIONS
92 
93 #define VSMC_DEFINE_OPENCL_COPY(Name) \
94 Name () : build_id_(-1) {} \
95 Name (const Name<T, PlaceHolder> &other) : \
96  configure_(other.configure_), \
97  build_id_(other.build_id_), \
98  kernel_(other.kernel_), \
99  kernel_name_(other.kernel_name_) {} \
100 Name<T, PlaceHolder> &operator= (const Name<T, PlaceHolder> &other) \
101 { \
102  if (this != &other) { \
103  configure_ = other.configure_; \
104  build_id_ = other.build_id_; \
105  kernel_ = other.kernel_; \
106  kernel_name_ = other.kernel_name_; \
107  } \
108 } \
109 virtual ~Name () {}
110 
111 #if VSMC_HAS_CXX11_RVALUE_REFERENCES
112 #define VSMC_DEFINE_OPENCL_MOVE(Name) \
113 Name (Name<T, PlaceHolder> &&other) : \
114  configure_(cxx11::move(other.configure_)), \
115  build_id_(other.build_id_), \
116  kernel_(cxx11::move(other.kernel_)), \
117  kernel_name_(cxx11::move(other.kernel_name_)) {} \
118  \
119 Name<T, PlaceHolder> &operator= (Name<T, PlaceHolder> &&other) \
120 { \
121  if (this != &other) { \
122  configure_ = cxx11::move(other.configure_); \
123  build_id_ = other.build_id_; \
124  kernel_ = cxx11::move(other.kernel_); \
125  kernel_name_ = cxx11::move(other.kernel_name_); \
126  } \
127  \
128  return *this; \
129 }
130 #else
131 #define VSMC_DEFINE_OPENCL_MOVE(Name)
132 #endif
133 
134 #endif // VSMC_HAS_CXX11_DEFAULTED_FUNCTIONS
135 
136 #define VSMC_DEFINE_OPENCL_CONFIGURE_KERNEL \
137 CLConfigure &configure () {return configure_;} \
138 const CLConfigure &configure () const {return configure_;} \
139 ::cl::Kernel &kernel () {return kernel_;} \
140 const ::cl::Kernel &kernel () const {return kernel_;} \
141 const std::string &kernel_name () const {return kernel_name_;}
142 
143 #define VSMC_DEFINE_OPENCL_SET_KERNEL \
144 if (kname.empty()) { \
145  kernel_name_.clear(); \
146  return; \
147 } \
148 if (build_id_ != particle.value().build_id() || kernel_name_ != kname) { \
149  build_id_ = particle.value().build_id(); \
150  kernel_name_ = kname; \
151  kernel_ = particle.value().create_kernel(kernel_name_); \
152  configure_.local_size(particle.size(), \
153  kernel_, particle.value().manager().device()); \
154 } \
155 
156 #define VSMC_DEFINE_OPENCL_MEMBER_DATA \
157 CLConfigure configure_; \
158 int build_id_; \
159 ::cl::Kernel kernel_; \
160 std::string kernel_name_
161 
162 namespace vsmc {
163 
164 namespace internal {
165 
166 template <typename> void set_cl_fp_type (std::stringstream &);
167 
168 template <>
169 inline void set_cl_fp_type<cl_float> (std::stringstream &ss)
170 {
171  ss << "#ifndef FP_TYPE\n";
172  ss << "#define FP_TYPE float\n";
173  ss << "typedef float fp_type;\n";
174  ss << "#endif\n";
175 
176  ss << "#ifndef VSMC_HAS_OPENCL_DOUBLE\n";
177  ss << "#define VSMC_HAS_OPENCL_DOUBLE 0\n";
178  ss << "#endif\n";
179 }
180 
181 template <>
182 inline void set_cl_fp_type<cl_double> (std::stringstream &ss)
183 {
184  ss << "#if defined(cl_khr_fp64)\n";
185  ss << "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n";
186  ss << "#elif defined(cl_amd_fp64)\n";
187  ss << "#pragma OPENCL EXTENSION cl_amd_fp64 : enable\n";
188  ss << "#endif\n";
189 
190  ss << "#define FP_TYPE double\n";
191  ss << "typedef double fp_type;\n";
192  ss << "#endif\n";
193 
194  ss << "#ifndef VSMC_HAS_OPENCL_DOUBLE\n";
195  ss << "#define VSMC_HAS_OPENCL_DOUBLE 1\n";
196  ss << "#endif\n";
197 }
198 
199 template <typename FPType>
200 inline std::string cl_source_macros (
201  std::size_t size, std::size_t state_size, std::size_t seed)
202 {
203  std::stringstream ss;
204  set_cl_fp_type<FPType>(ss);
205 
206  ss << "#ifndef SIZE\n";
207  ss << "#define SIZE " << size << "UL\n";
208  ss << "#endif\n";
209 
210  ss << "#ifndef STATE_SIZE\n";
211  ss << "#define STATE_SIZE " << state_size << "UL\n";
212  ss << "#endif\n";
213 
214  ss << "#ifndef SEED\n";
215  ss << "#define SEED " << seed << "UL\n";
216  ss << "#endif\n";
217 
218  return ss.str();
219 }
220 
221 template <typename D>
223 {
224  private :
225 
226  struct char2 {char c1; char c2;};
227 
228  template <std::size_t Dim, typename T, typename ID>
229  static char test (const StateCL<Dim, T, ID> *);
230  static char2 test (...);
231 
232  public :
233 
234  enum {value = sizeof(test(static_cast<const D *>(0))) == sizeof(char)};
235 }; // struct IsDerivedFromStateImpl
236 
237 template <typename D>
239  public cxx11::integral_constant<bool, IsDerivedFromStateCLImpl<D>::value>{};
240 
241 } // namespace vsmc::internal
242 
245 template <std::size_t StateSize, typename FPType, typename ID>
246 class StateCL
247 {
248  public :
249 
250  typedef ::cl_ulong size_type;
251  typedef FPType fp_type;
252  typedef ID cl_id;
254  typedef typename cxx11::conditional<StateSize == Dynamic,
256 
257  explicit StateCL (size_type N) :
258  state_size_(StateSize == Dynamic ? 1 : StateSize),
259  size_(N), build_(false), build_id_(0),
260  state_buffer_(state_size_ * size_)
261  {
262 #if VSMC_OPENCL_VERSION >= 120
263  if (manager().opencl_version() >= 120) {
264  copy_from_buffer_.resize(size_,
265  CL_MEM_READ_ONLY|CL_MEM_HOST_WRITE_ONLY);
266  } else {
267  copy_from_buffer_.resize(size_, CL_MEM_READ_ONLY);
268  }
269 #else
270  copy_from_buffer_.resize(size_, CL_MEM_READ_ONLY);
271 #endif
272  }
273 
274  size_type size () const {return size_;}
275 
276  std::size_t state_size () const {return state_size_;}
277 
279  void resize_state (std::size_t state_size)
280  {
282  StateSize);
284 
285  state_size_ = state_size;
286  state_buffer_.resize(state_size_ * size_);
287  }
288 
291  {state_buffer_.resize(state_size_ * size_, flag);}
292 
294  void update_state (::cl_mem_flags flag, void *host_ptr)
295  {state_buffer_.resize(state_size_ * size_, flag, host_ptr);}
296 
299  static manager_type &manager () {return manager_type::instance();}
300 
302  const CLBuffer<char, ID> &state_buffer () const {return state_buffer_;}
303 
305  const ::cl::Program &program () const {return program_;}
306 
344  template <typename CharT, typename Traits>
345  void build (const std::string &source,
346  const std::string &flags, std::basic_ostream<CharT, Traits> &os)
347  {
349 
350  std::string src(internal::cl_source_macros<fp_type>(
351  size_, state_size_, Seed::instance().get()) + source);
352  Seed::instance().skip(static_cast<Seed::skip_type>(size_));
353  program_ = manager().create_program(src);
354  build_program(flags, os);
355  }
356 
357  void build (const std::string &source,
358  const std::string &flags = std::string())
359  {build(source, flags, std::cout);}
360 
362  template <typename CharT, typename Traits>
363  void build (const ::cl::Program &program,
364  const std::string &flags, std::basic_ostream<CharT, Traits> &os)
365  {
366  program_ = program;
367  build_program(flags, os);
368  }
369 
370  void build (const ::cl::Program &program,
371  const std::string &flags = std::string())
372  {build(program, flags, std::cout);}
373 
375  bool build () const {return build_;}
376 
381  int build_id () const {return build_id_;}
382 
387  ::cl::Kernel create_kernel (const std::string &name) const
388  {
390 
391  return ::cl::Kernel(program_, name.c_str());
392  }
393 
394  template <typename IntType>
395  void copy (std::size_t N, const IntType *copy_from)
396  {
398 
399  manager().template write_buffer<size_type>(
400  copy_from_buffer_.data(), N, copy_from);
401  copy_(copy_from_buffer_.data(), state_buffer_.data());
402  }
403 
405  {
406  state_idx_host_.resize(size_);
407 #if VSMC_OPENCL_VERSION >= 120
408  if (manager().opencl_version() >= 120) {
409  state_idx_buffer_.resize(size_,
410  CL_MEM_READ_ONLY|CL_MEM_HOST_WRITE_ONLY|
411  CL_MEM_USE_HOST_PTR, &state_idx_host_[0]);
412  } else {
413  state_idx_buffer_.resize(size_,
414  CL_MEM_READ_ONLY|CL_MEM_USE_HOST_PTR, &state_idx_host_[0]);
415  }
416 #else
417  state_idx_buffer_.resize(size_,
418  CL_MEM_READ_ONLY|CL_MEM_USE_HOST_PTR, &state_idx_host_[0]);
419 #endif
420 
421  state_tmp_host_.resize(size_ * state_size_);
422  state_tmp_buffer_.resize(size_ * state_size_,
423  CL_MEM_READ_ONLY|CL_MEM_USE_HOST_PTR, &state_tmp_host_[0]);
424 
425  std::memset(&state_idx_host_[0], 0, size_);
426  manager().read_buffer(state_tmp_buffer_.data(), size_ * state_size_,
427  &state_tmp_host_[0]);
428  }
429 
431  {
432  manager().write_buffer(state_idx_buffer_.data(), size_,
433  &state_idx_host_[0]);
434  manager().write_buffer(state_tmp_buffer_.data(), size_ * state_size_,
435  &state_tmp_host_[0]);
436  copy_(state_idx_buffer_.data(), state_tmp_buffer_.data(),
437  state_buffer_.data());
438  }
439 
440  state_pack_type state_pack (size_type id) const
441  {
442  state_pack_type pack(create_pack());
443  std::memcpy(&pack[0], &state_tmp_host_[id * state_size_], state_size_);
444 
445  return pack;
446  }
447 
448  void state_unpack (size_type id, const state_pack_type &pack)
449  {
451  pack.size(), state_size_);
452 
453  state_idx_host_[id] = 1;
454  std::memcpy(&state_tmp_host_[id * state_size_], &pack[0], state_size_);
455  }
456 
457  CLConfigure &copy_configure () {return copy_.configure();}
458 
459  const CLConfigure &copy_configure () const {return copy_.configure();}
460 
461  ::cl::Kernel &copy_kernel () {return copy_.kernel();}
462 
463  const ::cl::Kernel &copy_kernel () const {return copy_.kernel();}
464 
465  private :
466 
467  std::size_t state_size_;
468  size_type size_;
469 
470  ::cl::Program program_;
471 
472  bool build_;
473  int build_id_;
474 
475  CLBuffer<char, ID> state_buffer_;
476  CLBuffer<size_type, ID> copy_from_buffer_;
477  internal::CLCopy<ID> copy_;
478 
479  CLBuffer<char, ID> state_idx_buffer_;
480  CLBuffer<char, ID> state_tmp_buffer_;
481  std::vector<char, AlignedAllocator<char> > state_idx_host_;
482  std::vector<char, AlignedAllocator<char> > state_tmp_host_;
483 
484  template <typename CharT, typename Traits>
485  void build_program (const std::string flags,
486  std::basic_ostream<CharT, Traits> &os)
487  {
488  ++build_id_;
489 
490  build_ = false;
491  try {
492  program_.build(manager().device_vec(), flags.c_str());
493  copy_.build(size_, state_size_);
494  build_ = true;
495  } catch (const ::cl::Error &err) {
496  CLQuery::program_build_log(program_, os);
497  CLQuery::program_build_log(copy_.program(), os);
498  throw CLError(err);
499  }
500  }
501 
502  state_pack_type create_pack () const
503  {
504  return create_pack_dispatch(
505  cxx11::integral_constant<bool, StateSize == Dynamic>());
506  }
507 
508  std::vector<char> create_pack_dispatch (cxx11::true_type) const
509  {return std::vector<char>(this->state_size());}
510 
511  Array<char, StateSize> create_pack_dispatch (cxx11::false_type) const
512  {return Array<char, StateSize>();}
513 }; // class StateCL
514 
542 template <typename T, typename PlaceHolder = NullType>
544 {
545  public :
546 
552  static VSMC_CONSTEXPR ::cl_uint kernel_args_offset () {return 2;}
553 
554  std::size_t operator() (Particle<T> &particle, void *param)
555  {
557 
558  set_kernel(particle);
559  if (kernel_name_.empty())
560  return 0;
561 
562  set_kernel_args(particle);
563  initialize_param(particle, param);
564  pre_processor(particle);
565  particle.value().manager().run_kernel(
566  kernel_, particle.size(), configure_.local_size());
567  post_processor(particle);
568 
569  return accept_count(particle, accept_buffer_.data());
570  }
571 
572  virtual void initialize_param (Particle<T> &, void *) {}
573  virtual void initialize_state (std::string &) {}
574  virtual void pre_processor (Particle<T> &) {}
575  virtual void post_processor (Particle<T> &) {}
576 
577  virtual std::size_t accept_count (Particle<T> &particle,
578  const ::cl::Buffer &accept_buffer)
579  {
580  particle.value().manager().read_buffer(
581  accept_buffer, particle.size(), &accept_host_[0]);
582 
583  return static_cast<std::size_t>(std::accumulate(
584  accept_host_.begin(), accept_host_.end(),
585  static_cast< ::cl_ulong>(0)));
586  }
587 
588  virtual void set_kernel (const Particle<T> &particle)
589  {
590  std::string kname;
591  initialize_state(kname);
593  }
594 
595  virtual void set_kernel_args (const Particle<T> &particle)
596  {
597  accept_host_.resize(particle.size());
598 #if VSMC_OPENCL_VERSION >= 120
599  if (particle.value().manager().opencl_version() >= 120) {
600  accept_buffer_.resize(particle.size(),
601  CL_MEM_READ_WRITE|CL_MEM_HOST_READ_ONLY|
602  CL_MEM_USE_HOST_PTR, &accept_host_[0]);
603  } else {
604  accept_buffer_.resize(particle.size(),
605  CL_MEM_READ_WRITE|CL_MEM_USE_HOST_PTR, &accept_host_[0]);
606  }
607 #else
608  accept_buffer_.resize(particle.size(),
609  CL_MEM_READ_WRITE|CL_MEM_USE_HOST_PTR, &accept_host_[0]);
610 #endif
611  cl_set_kernel_args(kernel_, 0,
612  particle.value().state_buffer().data(), accept_buffer_.data());
613  }
614 
616 
617  protected :
618 
621 
622  private :
623 
625  CLBuffer< ::cl_ulong, typename T::cl_id> accept_buffer_;
626  std::vector< ::cl_ulong> accept_host_;
627 }; // class InitializeCL
628 
638 template <typename T, typename PlaceHolder = NullType>
639 class MoveCL
640 {
641  public :
642 
648  static VSMC_CONSTEXPR ::cl_uint kernel_args_offset () {return 3;}
649 
650  std::size_t operator() (std::size_t iter, Particle<T> &particle)
651  {
653 
654  set_kernel(iter, particle);
655  if (kernel_name_.empty())
656  return 0;
657 
658  set_kernel_args(iter, particle);
659  pre_processor(iter, particle);
660  particle.value().manager().run_kernel(
661  kernel_, particle.size(), configure_.local_size());
662  post_processor(iter, particle);
663 
664  return accept_count(particle, accept_buffer_.data());
665  }
666 
667  virtual void move_state (std::size_t, std::string &) {}
668  virtual void pre_processor (std::size_t, Particle<T> &) {}
669  virtual void post_processor (std::size_t, Particle<T> &) {}
670 
671  virtual std::size_t accept_count (Particle<T> &particle,
672  const ::cl::Buffer &accept_buffer)
673  {
674  particle.value().manager().read_buffer(
675  accept_buffer, particle.size(), &accept_host_[0]);
676 
677  return static_cast<std::size_t>(std::accumulate(
678  accept_host_.begin(), accept_host_.end(),
679  static_cast< ::cl_ulong>(0)));
680  }
681 
682  virtual void set_kernel (std::size_t iter, const Particle<T> &particle)
683  {
684  std::string kname;
685  move_state(iter, kname);
687  }
688 
689  virtual void set_kernel_args (std::size_t iter,
690  const Particle<T> &particle)
691  {
692  accept_host_.resize(particle.size());
693 #if VSMC_OPENCL_VERSION >= 120
694  if (particle.value().manager().opencl_version() >= 120) {
695  accept_buffer_.resize(particle.size(),
696  CL_MEM_READ_WRITE|CL_MEM_HOST_READ_ONLY|
697  CL_MEM_USE_HOST_PTR, &accept_host_[0]);
698  } else {
699  accept_buffer_.resize(particle.size(),
700  CL_MEM_READ_WRITE|CL_MEM_USE_HOST_PTR, &accept_host_[0]);
701  }
702 #else
703  accept_buffer_.resize(particle.size(),
704  CL_MEM_READ_WRITE|CL_MEM_USE_HOST_PTR, &accept_host_[0]);
705 #endif
706  cl_set_kernel_args(kernel_, 0, static_cast< ::cl_ulong>(iter),
707  particle.value().state_buffer().data(), accept_buffer_.data());
708  }
709 
711 
712  protected :
713 
716 
717  private :
718 
719  VSMC_DEFINE_OPENCL_MEMBER_DATA;
720  CLBuffer< ::cl_ulong, typename T::cl_id> accept_buffer_;
721  std::vector< ::cl_ulong> accept_host_;
722 }; // class MoveCL
723 
734 template <typename T, typename PlaceHolder = NullType>
736 {
737  public :
738 
744  static VSMC_CONSTEXPR ::cl_uint kernel_args_offset () {return 4;}
745 
746  void operator() (std::size_t iter, std::size_t dim,
747  const Particle<T> &particle, double *res)
748  {
750 
751  set_kernel(iter, dim, particle);
752  if (kernel_name_.empty())
753  return;
754 
755  set_kernel_args(iter, dim, particle);
756  pre_processor(iter, particle);
757  particle.value().manager().run_kernel(
758  kernel_, particle.size(), configure_.local_size());
759  particle.value().manager().template
760  read_buffer<typename T::fp_type>(
761  buffer_.data(), particle.value().size() * dim, res);
762  post_processor(iter, particle);
763  }
764 
765  virtual void monitor_state (std::size_t, std::string &) {}
766  virtual void pre_processor (std::size_t, const Particle<T> &) {}
767  virtual void post_processor (std::size_t, const Particle<T> &) {}
768 
769  virtual void set_kernel (std::size_t iter, std::size_t,
770  const Particle<T> &particle)
771  {
772  std::string kname;
773  monitor_state(iter, kname);
775  }
776 
777  virtual void set_kernel_args (std::size_t iter, std::size_t dim,
778  const Particle<T> &particle)
779  {
780 #if VSMC_OPENCL_VERSION >= 120
781  if (particle.value().manager().opencl_version() >= 120) {
782  buffer_.resize(particle.size() * dim,
783  CL_MEM_READ_WRITE|CL_MEM_HOST_READ_ONLY);
784  } else {
785  buffer_.resize(particle.size() * dim);
786  }
787 #else
788  buffer_.resize(particle.size() * dim);
789 #endif
790  cl_set_kernel_args(kernel_, 0, static_cast< ::cl_ulong>(iter),
791  static_cast< ::cl_ulong>(dim),
792  particle.value().state_buffer().data(), buffer_.data());
793  }
794 
796 
797  protected :
798 
799  VSMC_DEFINE_OPENCL_COPY(MonitorEvalCL)
800  VSMC_DEFINE_OPENCL_MOVE(MonitorEvalCL)
801 
802  private :
803 
804  VSMC_DEFINE_OPENCL_MEMBER_DATA;
805  CLBuffer<typename T::fp_type, typename T::cl_id> buffer_;
806 }; // class MonitorEvalCL
807 
818 template <typename T, typename PlaceHolder = NullType>
820 {
821  public :
822 
828  static VSMC_CONSTEXPR ::cl_uint kernel_args_offset () {return 3;}
829 
830  double operator() (std::size_t iter, const Particle<T> &particle,
831  double *res)
832  {
834 
835  set_kernel(iter, particle);
836  if (kernel_name_.empty())
837  return 0;
838 
839  set_kernel_args(iter, particle);
840  pre_processor(iter, particle);
841  particle.value().manager().run_kernel(
842  kernel_, particle.size(), configure_.local_size());
843  particle.value().manager().template
844  read_buffer<typename T::fp_type>(
845  buffer_.data(), particle.value().size(), res);
846  post_processor(iter, particle);
847 
848  return this->path_grid(iter, particle);
849  }
850 
851  virtual void path_state (std::size_t, std::string &) {}
852  virtual double path_grid (std::size_t, const Particle<T> &) {return 0;}
853  virtual void pre_processor (std::size_t, const Particle<T> &) {}
854  virtual void post_processor (std::size_t, const Particle<T> &) {}
855 
856  virtual void set_kernel (std::size_t iter, const Particle<T> &particle)
857  {
858  std::string kname;
859  path_state(iter, kname);
861  }
862 
863  virtual void set_kernel_args (std::size_t iter,
864  const Particle<T> &particle)
865  {
866 #if VSMC_OPENCL_VERSION >= 120
867  if (particle.value().manager().opencl_version() >= 120) {
868  buffer_.resize(particle.size(),
869  CL_MEM_READ_WRITE|CL_MEM_HOST_READ_ONLY);
870  } else {
871  buffer_.resize(particle.size());
872  }
873 #else
874  buffer_.resize(particle.size());
875 #endif
876  cl_set_kernel_args(kernel_, 0, static_cast< ::cl_ulong>(iter),
877  particle.value().state_buffer().data(), buffer_.data());
878  }
879 
881 
882  protected :
883 
885  VSMC_DEFINE_OPENCL_MOVE(PathEvalCL)
886 
887  private :
888 
889  VSMC_DEFINE_OPENCL_MEMBER_DATA;
890  CLBuffer<typename T::fp_type, typename T::cl_id> buffer_;
891 }; // class PathEvalCL
892 
893 } // namespace vsmc
894 
895 #endif // VSMC_OPENCL_BACKEND_CL_HPP
#define VSMC_STATIC_ASSERT_OPENCL_BACKEND_CL_STATE_CL_TYPE(derived, user)
Definition: backend_cl.hpp:50
void copy_post_processor()
Definition: backend_cl.hpp:430
static SeedGenerator< ID, ResultType > & instance()
Definition: seed.hpp:94
Definition: adapter.hpp:37
Particle class representing the whole particle set.
Definition: particle.hpp:48
#define VSMC_DEFINE_OPENCL_CONFIGURE_KERNEL
Definition: backend_cl.hpp:136
void copy_pre_processor()
Definition: backend_cl.hpp:404
#define VSMC_RUNTIME_ASSERT_OPENCL_BACKEND_CL_BUILD(func)
Definition: backend_cl.hpp:59
const CLBuffer< char, ID > & state_buffer() const
The OpenCL buffer that stores the state values.
Definition: backend_cl.hpp:302
void build(const ::cl::Program &program, const std::string &flags=std::string())
Definition: backend_cl.hpp:370
StateCL(size_type N)
Definition: backend_cl.hpp:257
#define VSMC_DEFINE_OPENCL_COPY(Name)
Definition: backend_cl.hpp:77
virtual void pre_processor(std::size_t, const Particle< T > &)
Definition: backend_cl.hpp:853
void build(std::size_t size, std::size_t state_size)
Definition: cl_copy.hpp:67
void read_buffer(const ::cl::Buffer &buf, std::size_t num, OutputIter first, std::size_t offset=0, const std::vector< ::cl::Event > *events=nullptr,::cl::Event *event=nullptr, bool block=true) const
Read an OpenCL buffer of a given type and number of elements into an iterator.
Definition: cl_manager.hpp:221
bool build() const
Whether the last attempted building success.
Definition: backend_cl.hpp:375
::cl::Kernel & copy_kernel()
Definition: backend_cl.hpp:461
void state_unpack(size_type id, const state_pack_type &pack)
Definition: backend_cl.hpp:448
#define VSMC_STATIC_ASSERT_OPENCL_BACKEND_CL_DYNAMIC_STATE_SIZE_RESIZE(Dim)
Definition: backend_cl.hpp:46
void set_cl_fp_type< cl_double >(std::stringstream &ss)
Definition: backend_cl.hpp:182
virtual void set_kernel_args(std::size_t iter, std::size_t dim, const Particle< T > &particle)
Definition: backend_cl.hpp:777
virtual void set_kernel(std::size_t iter, const Particle< T > &particle)
Definition: backend_cl.hpp:856
value_type & value()
Read and write access to the value collection object.
Definition: particle.hpp:149
#define VSMC_RUNTIME_ASSERT_OPENCL_BACKEND_CL_COPY_SIZE_MISMATCH
Definition: backend_cl.hpp:67
STL namespace.
::cl::Kernel create_kernel(const std::string &name) const
Create kernel with the current program.
Definition: backend_cl.hpp:387
static constexpr::cl_uint kernel_args_offset()
The index offset of additional kernel arguments set by the user.
Definition: backend_cl.hpp:828
void build(const ::cl::Program &program, const std::string &flags, std::basic_ostream< CharT, Traits > &os)
Build from an existing program.
Definition: backend_cl.hpp:363
static std::vector< std::pair< ::cl_build_status, std::string > > program_build_log(const ::cl::Program &program)
Program build log and status.
Definition: cl_query.hpp:171
void update_state(::cl_mem_flags flag, void *host_ptr)
Change state buffer flag and host pointer (cause reallocation)
Definition: backend_cl.hpp:294
void build(const std::string &source, const std::string &flags, std::basic_ostream< CharT, Traits > &os)
Build the OpenCL program from source.
Definition: backend_cl.hpp:345
state_pack_type state_pack(size_type id) const
Definition: backend_cl.hpp:440
void build(const std::string &source, const std::string &flags=std::string())
Definition: backend_cl.hpp:357
virtual void initialize_state(std::string &)
Definition: backend_cl.hpp:573
virtual void set_kernel(std::size_t iter, const Particle< T > &particle)
Definition: backend_cl.hpp:682
virtual std::size_t accept_count(Particle< T > &particle, const ::cl::Buffer &accept_buffer)
Definition: backend_cl.hpp:671
virtual void pre_processor(std::size_t, Particle< T > &)
Definition: backend_cl.hpp:668
void update_state(::cl_mem_flags flag)
Change state buffer flag (cause reallocation)
Definition: backend_cl.hpp:290
Monitor::eval_type subtype using OpenCL.
Definition: backend_cl.hpp:735
CLManager< ID > manager_type
Definition: backend_cl.hpp:253
::cl::Program & program()
Definition: cl_copy.hpp:103
void write_buffer(const ::cl::Buffer &buf, std::size_t num, InputIter first, std::size_t offset=0, const std::vector< ::cl::Event > *events=nullptr,::cl::Event *event=nullptr, bool block=true) const
Write an OpenCL buffer of a given type and number of elements from an iterator.
Definition: cl_manager.hpp:257
integral_constant< bool, false > false_type
void * memset(void *dst, int ch, std::size_t n)
SIMD optimized memset with non-temporal store for large buffers.
Definition: cstring.hpp:906
const ::cl::Program & program() const
The OpenCL program associated with this value collection.
Definition: backend_cl.hpp:305
virtual void pre_processor(std::size_t, const Particle< T > &)
Definition: backend_cl.hpp:766
Sampler::move_type subtype using OpenCL.
Definition: backend_cl.hpp:639
#define VSMC_RUNTIME_ASSERT_OPENCL_BACKEND_CL_UNPACK_SIZE(psize, dim)
Definition: backend_cl.hpp:71
virtual std::size_t accept_count(Particle< T > &particle, const ::cl::Buffer &accept_buffer)
Definition: backend_cl.hpp:577
size_type size() const
Definition: backend_cl.hpp:274
const ::cl::Buffer & data() const
Read only access to the raw cl::Buffer object.
Definition: cl_buffer.hpp:141
void set_cl_fp_type< cl_float >(std::stringstream &ss)
Definition: backend_cl.hpp:169
virtual void path_state(std::size_t, std::string &)
Definition: backend_cl.hpp:851
static constexpr::cl_uint kernel_args_offset()
The index offset of additional kernel arguments set by the user.
Definition: backend_cl.hpp:648
Used to specify a dimension template parameter is dynamic.
Definition: defines.hpp:97
static constexpr::cl_uint kernel_args_offset()
The index offset of additional kernel arguments set by the user.
Definition: backend_cl.hpp:744
void resize(size_type N)
Definition: cl_buffer.hpp:143
#define VSMC_RUNTIME_ASSERT_OPENCL_BACKEND_CL_STATE_SIZE(state_size)
Definition: backend_cl.hpp:64
std::size_t operator()(Particle< T > &particle, void *param)
Definition: backend_cl.hpp:554
void copy(std::size_t N, const IntType *copy_from)
Definition: backend_cl.hpp:395
virtual void set_kernel(std::size_t iter, std::size_t, const Particle< T > &particle)
Definition: backend_cl.hpp:769
Path::eval_type subtype using OpenCL.
Definition: backend_cl.hpp:819
virtual void monitor_state(std::size_t, std::string &)
Definition: backend_cl.hpp:765
void cl_set_kernel_args(::cl::Kernel &,::cl_uint)
Definition: cl_manip.hpp:129
void resize_state(std::size_t state_size)
Change state size.
Definition: backend_cl.hpp:279
virtual double path_grid(std::size_t, const Particle< T > &)
Definition: backend_cl.hpp:852
virtual void post_processor(std::size_t, Particle< T > &)
Definition: backend_cl.hpp:669
#define VSMC_DEFINE_OPENCL_MEMBER_DATA
Definition: backend_cl.hpp:156
cxx11::conditional< StateSize==Dynamic, std::vector< char >, Array< char, StateSize > >::type state_pack_type
Definition: backend_cl.hpp:255
#define VSMC_DEFINE_OPENCL_SET_KERNEL
Definition: backend_cl.hpp:143
virtual void pre_processor(Particle< T > &)
Definition: backend_cl.hpp:574
#define VSMC_DEFINE_OPENCL_MOVE(Name)
Definition: backend_cl.hpp:84
integral_constant< bool, true > true_type
const ::cl::Kernel & copy_kernel() const
Definition: backend_cl.hpp:463
Sampler::init_type subtype using OpenCL.
Definition: backend_cl.hpp:543
void * memcpy(void *dst, const void *src, std::size_t n)
SIMD optimized memcpy with non-temporal store for large buffers.
Definition: cstring.hpp:923
int build_id() const
The build id of the last attempted of building.
Definition: backend_cl.hpp:381
#define VSMC_STATIC_ASSERT_OPENCL_BACKEND_CL_STATE_CL_FP_TYPE(type)
Definition: backend_cl.hpp:54
const CLConfigure & copy_configure() const
Definition: backend_cl.hpp:459
virtual void post_processor(std::size_t, const Particle< T > &)
Definition: backend_cl.hpp:854
virtual void initialize_param(Particle< T > &, void *)
Definition: backend_cl.hpp:572
CLConfigure & copy_configure()
Definition: backend_cl.hpp:457
std::size_t local_size() const
virtual void set_kernel(const Particle< T > &particle)
Definition: backend_cl.hpp:588
std::string cl_source_macros(std::size_t size, std::size_t state_size, std::size_t seed)
Definition: backend_cl.hpp:200
virtual void post_processor(std::size_t, const Particle< T > &)
Definition: backend_cl.hpp:767
Configure OpenCL runtime behavior (used by MoveCL etc)
virtual void set_kernel_args(std::size_t iter, const Particle< T > &particle)
Definition: backend_cl.hpp:863
size_type size() const
Number of particles.
Definition: particle.hpp:146
::cl_ulong size_type
Definition: backend_cl.hpp:250
Static array.
Definition: array.hpp:79
OpenCL Manager.
Definition: cl_manager.hpp:129
Particle::value_type subtype using OpenCL.
Definition: forward.hpp:76
static constexpr::cl_uint kernel_args_offset()
The index offset of additional kernel arguments set by the user.
Definition: backend_cl.hpp:552
::cl::Program create_program(const std::string &source) const
Create a program given the source within the current context.
Definition: cl_manager.hpp:448
virtual void set_kernel_args(const Particle< T > &particle)
Definition: backend_cl.hpp:595
static CLManager< ID > & instance()
Get an instance of the manager singleton.
Definition: cl_manager.hpp:136
virtual void set_kernel_args(std::size_t iter, const Particle< T > &particle)
Definition: backend_cl.hpp:689
virtual void move_state(std::size_t, std::string &)
Definition: backend_cl.hpp:667
static constexpr size_type size()
Definition: array.hpp:161
static manager_type & manager()
The instance of the CLManager signleton associated with this value collcection.
Definition: backend_cl.hpp:299
std::size_t state_size() const
Definition: backend_cl.hpp:276
void set_cl_fp_type(std::stringstream &)
virtual void post_processor(Particle< T > &)
Definition: backend_cl.hpp:575