Automatic Differentiation
 
Loading...
Searching...
No Matches
check_cl.hpp
Go to the documentation of this file.
1#ifndef STAN_MATH_OPENCL_KERNEL_GENERATOR_CHECK_CL_HPP
2#define STAN_MATH_OPENCL_KERNEL_GENERATOR_CHECK_CL_HPP
3#ifdef STAN_OPENCL
4
12#include <map>
13
14namespace stan {
15namespace math {
16
27template <typename T>
28class check_cl_ : public operation_cl_lhs<check_cl_<T>, bool> {
29 public:
30 using Scalar = bool;
32 using base::var_name_;
33 using base::operator=;
34
35 protected:
36 // buffer[0] is indicator whether exception needs to be raised
37 // buffer[1,2] are problematic indices
40
41 public:
43 const char* function_;
44 const char* err_variable_;
45 const char* must_be_;
46
54 check_cl_(const char* function, const char* err_variable, T&& y,
55 const char* must_be)
56 : buffer_(constant(0, 3, 1)),
57 value_(1, 1),
58 arg_(std::forward<T>(y)),
59 function_(function),
60 err_variable_(err_variable),
61 must_be_(must_be) {
63 }
64
65 // this operation can not be used on the right hand side of assignment
66 inline kernel_parts get_kernel_parts(...) = delete;
67 inline void extreme_diagonals(...) = delete;
68
81 std::unordered_map<const void*, const char*>& generated,
82 std::unordered_map<const void*, const char*>& generated_all,
83 name_generator& name_gen, const std::string& row_index_name,
84 const std::string& col_index_name) const {
85 kernel_parts res;
86 this->var_name_ = name_gen.generate();
87 generated[this] = "";
88 res = arg_.get_kernel_parts(generated, generated_all, name_gen,
89 row_index_name, col_index_name, false);
90
91 res.args += "__global int* " + var_name_ + "_buffer, __global "
92 + type_str<value_type_t<T>>() + "* " + var_name_ + "_value, ";
93 res.body += "bool " + var_name_;
94 res.body_suffix += "if(!" + var_name_ +
95 " && atomic_xchg(" + var_name_ + "_buffer, 1) == 0){\n"
96 + var_name_ + "_buffer[1] = " + row_index_name + ";\n"
97 + var_name_ + "_buffer[2] = " + col_index_name + ";\n"
98 + var_name_ + "_value[0] = " + arg_.var_name_ + ";\n"
99 "}";
100 return res;
101 }
102
113 inline void set_args(
114 std::unordered_map<const void*, const char*>& generated,
115 std::unordered_map<const void*, const char*>& generated_all,
116 cl::Kernel& kernel, int& arg_num) const {
117 generated[this] = "";
118 arg_.set_args(generated, generated_all, kernel, arg_num);
119 kernel.setArg(arg_num++, buffer_.buffer());
120 kernel.setArg(arg_num++, value_.buffer());
121 }
122
130 inline void check_assign_dimensions(int rows, int cols) const {
131 if (arg_.rows() != base::dynamic) {
132 check_size_match("check_cl_.check_assign_dimensions", "Rows of ",
133 err_variable_, arg_.rows(), "rows of ",
134 "assigned expression", rows);
135 }
136 if (arg_.cols() != base::dynamic) {
137 check_size_match("check_cl_.check_assign_dimensions", "Columns of ",
138 err_variable_, arg_.cols(), "columns of ",
139 "assigned expression", cols);
140 }
141 }
142
149 std::vector<cl::Event>& events) const {
150 arg_.get_write_events(events);
151 events.insert(events.end(), buffer_.read_events().begin(),
152 buffer_.read_events().end());
153 events.insert(events.end(), buffer_.write_events().begin(),
154 buffer_.write_events().end());
155 }
156
163 inline void add_write_event(cl::Event& e) const {
164 e.wait();
165 Eigen::VectorXi res = from_matrix_cl<Eigen::VectorXi>(buffer_);
166 if (res.coeff(0)) {
167 double value = from_matrix_cl<scalar_type_t<T>>(value_);
168 std::stringstream s;
169 s << function_ << ": " << err_variable_ << "[" << res[1] << ", " << res[2]
170 << "] = " << value << ", but it must be " << must_be_ << "!";
171 throw std::domain_error(s.str());
172 }
173 }
174
180 inline int rows() const { return arg_.rows(); }
181
187 inline int cols() const { return arg_.cols(); }
188
194 void operator=(bool condition); // implemented in multi_result_kernel.hpp
195};
196
197namespace internal {
198template <typename T>
199struct is_scalar_check_impl : std::false_type {};
200
201template <typename T>
202struct is_scalar_check_impl<check_cl_<scalar_<T>>> : std::true_type {};
203
204template <typename T>
206} // namespace internal
207
218template <typename T, typename = require_all_kernel_expressions_t<T>>
219inline auto check_cl(const char* function, const char* var_name, T&& y,
220 const char* must_be) {
222 function, var_name, as_operation_cl(std::forward<T>(y)), must_be);
223}
224
227} // namespace math
228} // namespace stan
229
230#endif
231#endif // CHECK_CL_HPP
check_cl_(const char *function, const char *err_variable, T &&y, const char *must_be)
Constructor.
Definition check_cl.hpp:54
const char * must_be_
Definition check_cl.hpp:45
int rows() const
Number of rows of a matrix that would be the result of evaluating this expression.
Definition check_cl.hpp:180
void add_write_event(cl::Event &e) const
Instead of adding event to matrices, waits on the event and throws if check failed.
Definition check_cl.hpp:163
int cols() const
Number of columns of a matrix that would be the result of evaluating this expression.
Definition check_cl.hpp:187
kernel_parts get_kernel_parts(...)=delete
kernel_parts get_kernel_parts_lhs(std::unordered_map< const void *, const char * > &generated, std::unordered_map< const void *, const char * > &generated_all, name_generator &name_gen, const std::string &row_index_name, const std::string &col_index_name) const
Generates kernel code for this and nested expressions.
Definition check_cl.hpp:80
void set_args(std::unordered_map< const void *, const char * > &generated, std::unordered_map< const void *, const char * > &generated_all, cl::Kernel &kernel, int &arg_num) const
Sets kernel arguments for this expression.
Definition check_cl.hpp:113
void extreme_diagonals(...)=delete
void check_assign_dimensions(int rows, int cols) const
Checks if desired dimensions match dimensions of the argument.
Definition check_cl.hpp:130
const char * err_variable_
Definition check_cl.hpp:44
void get_clear_read_write_events(std::vector< cl::Event > &events) const
Adds all write events on any matrices used by nested expression to a list.
Definition check_cl.hpp:148
matrix_cl< int > buffer_
Definition check_cl.hpp:38
const char * function_
Definition check_cl.hpp:43
matrix_cl< value_type_t< T > > value_
Definition check_cl.hpp:39
Represents a check in kernel generator expressions.
Definition check_cl.hpp:28
const cl::Buffer & buffer() const
const matrix_cl_view & view() const
Definition matrix_cl.hpp:70
const tbb::concurrent_vector< cl::Event > & read_events() const
Get the events from the event stacks.
const tbb::concurrent_vector< cl::Event > & write_events() const
Get the events from the event stacks.
Represents an arithmetic matrix on the OpenCL device.
Definition matrix_cl.hpp:47
std::string generate()
Generates a unique variable name.
Unique name generator for variables used in generated kernels.
Base for all kernel generator operations that can be used on left hand side of an expression.
static constexpr int dynamic
Represents a scalar in kernel generator expressions.
Definition scalar.hpp:29
auto check_cl(const char *function, const char *var_name, T &&y, const char *must_be)
Constructs a check on opencl matrix or expression.
Definition check_cl.hpp:219
void operator=(bool condition)
Assignment of a scalar bool triggers the scalar check.
auto constant(const T a, int rows, int cols)
Matrix of repeated values in kernel generator expressions.
Definition constant.hpp:130
T_operation && as_operation_cl(T_operation &&a)
Converts any valid kernel generator expression into an operation.
static constexpr double e()
Return the base of the natural logarithm.
Definition constants.hpp:20
void check_size_match(const char *function, const char *name_i, T_size1 i, const char *name_j, T_size2 j)
Check if the provided sizes match.
The lgamma implementation in stan-math is based on either the reentrant safe lgamma_r implementation ...
Definition fvar.hpp:9
STL namespace.
Parts of an OpenCL kernel, generated by an expression.