ViennaCL - The Vienna Computing Library: viennacl/scheduler/execute_axbx.hpp Source File

ViennaCL - The Vienna Computing Library 1.7.1 Free open-source GPU-accelerated linear algebra and solver library. |

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
execute_axbx.hpp
Go to the documentation of this file.
1 #ifndef VIENNACL_SCHEDULER_EXECUTE_AXBX_HPP
2 #define VIENNACL_SCHEDULER_EXECUTE_AXBX_HPP
3
4 /* =========================================================================
5 Copyright (c) 2010-2016, Institute for Microelectronics,
6 Institute for Analysis and Scientific Computing,
7 TU Wien.
8 Portions of this software are copyright by UChicago Argonne, LLC.
9
10 -----------------
11 ViennaCL - The Vienna Computing Library
12 -----------------
13
14 Project Head: Karl Rupp rupp@iue.tuwien.ac.at
15
16 (A list of authors and contributors can be found in the manual)
17
18 License: MIT (X11), see file LICENSE in the base directory
19 ============================================================================= */
20
21
26 #include "viennacl/forwards.h"
27 #include "viennacl/scheduler/forwards.h"
28
29 #include "viennacl/scheduler/execute_scalar_assign.hpp"
30 #include "viennacl/scheduler/execute_generic_dispatcher.hpp"
31
32 namespace viennacl
33 {
34 namespace scheduler
35 {
36 namespace detail
37 {
38
40 inline void execute_axbx(statement const & s, statement_node const & root_node)
41 {
42 statement::container_type const & expr = s.array();
43 viennacl::context ctx = detail::extract_context(root_node);
44
45 statement_node const & leaf = expr[root_node.rhs.node_index];
46
47 if (leaf.op.type == OPERATION_BINARY_ADD_TYPE || leaf.op.type == OPERATION_BINARY_SUB_TYPE) // x = (y) +- (z) where y and z are either data objects or expressions
48 {
49 bool flip_sign_z = (leaf.op.type == OPERATION_BINARY_SUB_TYPE);
50
51 if ( leaf.lhs.type_family != COMPOSITE_OPERATION_FAMILY
52 && leaf.rhs.type_family != COMPOSITE_OPERATION_FAMILY)
53 {
54 lhs_rhs_element u = root_node.lhs;
55 lhs_rhs_element v = leaf.lhs;
56 lhs_rhs_element w = leaf.rhs;
57 switch (root_node.op.type)
58 {
59 case OPERATION_BINARY_ASSIGN_TYPE:
60 detail::axbx(u,
61 v, 1.0, 1, false, false,
62 w, 1.0, 1, false, flip_sign_z);
63 break;
64 case OPERATION_BINARY_INPLACE_ADD_TYPE:
65 detail::axbx_x(u,
66 v, 1.0, 1, false, false,
67 w, 1.0, 1, false, flip_sign_z);
68 break;
69 case OPERATION_BINARY_INPLACE_SUB_TYPE:
70 detail::axbx_x(u,
71 v, 1.0, 1, false, true,
72 w, 1.0, 1, false, !flip_sign_z);
73 break;
74 default:
75 throw statement_not_supported_exception("Unsupported binary operator for operation in root note (should be =, +=, or -=)");
76 }
77 }
78 else if ( leaf.lhs.type_family == COMPOSITE_OPERATION_FAMILY
79 && leaf.rhs.type_family != COMPOSITE_OPERATION_FAMILY) // x = (y) + z, y being a subtree itself, z being a scalar, vector, or matrix
80 {
81 statement_node const & y = expr[leaf.lhs.node_index];
82
83 if (y.op.type_family == OPERATION_BINARY_TYPE_FAMILY || y.op.type_family == OPERATION_UNARY_TYPE_FAMILY)
84 {
85 // y might be 'v * alpha' or 'v / alpha' with {scalar|vector|matrix} v
86 if ( (y.op.type == OPERATION_BINARY_MULT_TYPE || y.op.type == OPERATION_BINARY_DIV_TYPE)
87 && y.lhs.type_family != COMPOSITE_OPERATION_FAMILY
88 && y.rhs.type_family == SCALAR_TYPE_FAMILY)
89 {
90 lhs_rhs_element u = root_node.lhs;
91 lhs_rhs_element v = y.lhs;
92 lhs_rhs_element w = leaf.rhs;
93 lhs_rhs_element alpha = y.rhs;
94
95 bool is_division = (y.op.type == OPERATION_BINARY_DIV_TYPE);
96 switch (root_node.op.type)
97 {
98 case OPERATION_BINARY_ASSIGN_TYPE:
99 detail::axbx(u,
100 v, alpha, 1, is_division, false,
101 w, 1.0, 1, false, flip_sign_z);
102 break;
103 case OPERATION_BINARY_INPLACE_ADD_TYPE:
104 detail::axbx_x(u,
105 v, alpha, 1, is_division, false,
106 w, 1.0, 1, false, flip_sign_z);
107 break;
108 case OPERATION_BINARY_INPLACE_SUB_TYPE:
109 detail::axbx_x(u,
110 v, alpha, 1, is_division, true,
111 w, 1.0, 1, false, !flip_sign_z);
112 break;
113 default:
114 throw statement_not_supported_exception("Unsupported binary operator for vector operation in root note (should be =, +=, or -=)");
115 }
116 }
117 else // no built-in kernel, we use a temporary.
118 {
119 statement_node new_root_y;
120
121 detail::new_element(new_root_y.lhs, root_node.lhs, ctx);
122
123 new_root_y.op.type_family = OPERATION_BINARY_TYPE_FAMILY;
124 new_root_y.op.type = OPERATION_BINARY_ASSIGN_TYPE;
125
126 new_root_y.rhs.type_family = COMPOSITE_OPERATION_FAMILY;
127 new_root_y.rhs.subtype = INVALID_SUBTYPE;
128 new_root_y.rhs.numeric_type = INVALID_NUMERIC_TYPE;
129 new_root_y.rhs.node_index = leaf.lhs.node_index;
130
131 // work on subexpression:
132 // TODO: Catch exception, free temporary, then rethrow
133 execute_composite(s, new_root_y);
134
135 // now add:
136 lhs_rhs_element u = root_node.lhs;
137 lhs_rhs_element v = new_root_y.lhs;
138 lhs_rhs_element w = leaf.rhs;
139 switch (root_node.op.type)
140 {
141 case OPERATION_BINARY_ASSIGN_TYPE:
142 detail::axbx(u,
143 v, 1.0, 1, false, false,
144 w, 1.0, 1, false, flip_sign_z);
145 break;
146 case OPERATION_BINARY_INPLACE_ADD_TYPE:
147 detail::axbx_x(u,
148 v, 1.0, 1, false, false,
149 w, 1.0, 1, false, flip_sign_z);
150 break;
151 case OPERATION_BINARY_INPLACE_SUB_TYPE:
152 detail::axbx_x(u,
153 v, 1.0, 1, false, true,
154 w, 1.0, 1, false, !flip_sign_z);
155 break;
156 default:
157 throw statement_not_supported_exception("Unsupported binary operator for vector operation in root note (should be =, +=, or -=)");
158 }
159
160 detail::delete_element(new_root_y.lhs);
161 }
162 }
163 else
164 throw statement_not_supported_exception("Cannot deal with unknown non-unary and non-binary operations on vectors");
165
166 }
167 else if ( leaf.lhs.type_family != COMPOSITE_OPERATION_FAMILY
168 && leaf.rhs.type_family == COMPOSITE_OPERATION_FAMILY) // x = y + (z), y being vector, z being a subtree itself
169 {
170 statement_node const & z = expr[leaf.rhs.node_index];
171
172 if (z.op.type_family == OPERATION_BINARY_TYPE_FAMILY || z.op.type_family == OPERATION_UNARY_TYPE_FAMILY)
173 {
174 // z might be 'v * alpha' or 'v / alpha' with vector v
175 if ( (z.op.type == OPERATION_BINARY_MULT_TYPE || z.op.type == OPERATION_BINARY_DIV_TYPE)
176 && z.lhs.type_family != COMPOSITE_OPERATION_FAMILY
177 && z.rhs.type_family == SCALAR_TYPE_FAMILY)
178 {
179 lhs_rhs_element u = root_node.lhs;
180 lhs_rhs_element v = leaf.lhs;
181 lhs_rhs_element w = z.lhs;
182 lhs_rhs_element beta = z.rhs;
183
184 bool is_division = (z.op.type == OPERATION_BINARY_DIV_TYPE);
185 switch (root_node.op.type)
186 {
187 case OPERATION_BINARY_ASSIGN_TYPE:
188 detail::axbx(u,
189 v, 1.0, 1, false, false,
190 w, beta, 1, is_division, flip_sign_z);
191 break;
192 case OPERATION_BINARY_INPLACE_ADD_TYPE:
193 detail::axbx_x(u,
194 v, 1.0, 1, false, false,
195 w, beta, 1, is_division, flip_sign_z);
196 break;
197 case OPERATION_BINARY_INPLACE_SUB_TYPE:
198 detail::axbx_x(u,
199 v, 1.0, 1, false, true,
200 w, beta, 1, is_division, !flip_sign_z);
201 break;
202 default:
203 throw statement_not_supported_exception("Unsupported binary operator for vector operation in root note (should be =, +=, or -=)");
204 }
205 }
206 else // no built-in kernel, we use a temporary.
207 {
208 statement_node new_root_z;
209
210 detail::new_element(new_root_z.lhs, root_node.lhs, ctx);
211
212 new_root_z.op.type_family = OPERATION_BINARY_TYPE_FAMILY;
213 new_root_z.op.type = OPERATION_BINARY_ASSIGN_TYPE;
214
215 new_root_z.rhs.type_family = COMPOSITE_OPERATION_FAMILY;
216 new_root_z.rhs.subtype = INVALID_SUBTYPE;
217 new_root_z.rhs.numeric_type = INVALID_NUMERIC_TYPE;
218 new_root_z.rhs.node_index = leaf.rhs.node_index;
219
220 // work on subexpression:
221 // TODO: Catch exception, free temporary, then rethrow
222 execute_composite(s, new_root_z);
223
224 // now add:
225 lhs_rhs_element u = root_node.lhs;
226 lhs_rhs_element v = leaf.lhs;
227 lhs_rhs_element w = new_root_z.lhs;
228 switch (root_node.op.type)
229 {
230 case OPERATION_BINARY_ASSIGN_TYPE:
231 detail::axbx(u,
232 v, 1.0, 1, false, false,
233 w, 1.0, 1, false, flip_sign_z);
234 break;
235 case OPERATION_BINARY_INPLACE_ADD_TYPE:
236 detail::axbx_x(u,
237 v, 1.0, 1, false, false,
238 w, 1.0, 1, false, flip_sign_z);
239 break;
240 case OPERATION_BINARY_INPLACE_SUB_TYPE:
241 detail::axbx_x(u,
242 v, 1.0, 1, false, true,
243 w, 1.0, 1, false, !flip_sign_z);
244 break;
245 default:
246 throw statement_not_supported_exception("Unsupported binary operator for vector operation in root note (should be =, +=, or -=)");
247 }
248
249 detail::delete_element(new_root_z.lhs);
250 }
251 }
252 else
253 throw statement_not_supported_exception("Cannot deal with unknown non-unary and non-binary operations on vectors");
254
255 }
256 else if ( leaf.lhs.type_family == COMPOSITE_OPERATION_FAMILY
257 && leaf.rhs.type_family == COMPOSITE_OPERATION_FAMILY) // x = (y) + (z), y and z being subtrees
258 {
259 statement_node const & y = expr[leaf.lhs.node_index];
260 statement_node const & z = expr[leaf.rhs.node_index];
261
262 if ( (y.op.type_family == OPERATION_BINARY_TYPE_FAMILY || y.op.type_family == OPERATION_UNARY_TYPE_FAMILY)
263 && (z.op.type_family == OPERATION_BINARY_TYPE_FAMILY || z.op.type_family == OPERATION_UNARY_TYPE_FAMILY))
264 {
265 // z might be 'v * alpha' or 'v / alpha' with vector v
266 if ( (y.op.type == OPERATION_BINARY_MULT_TYPE || y.op.type == OPERATION_BINARY_DIV_TYPE)
267 && y.lhs.type_family != COMPOSITE_OPERATION_FAMILY
268 && y.rhs.type_family == SCALAR_TYPE_FAMILY
269 && (z.op.type == OPERATION_BINARY_MULT_TYPE || z.op.type == OPERATION_BINARY_DIV_TYPE)
270 && z.lhs.type_family != COMPOSITE_OPERATION_FAMILY
271 && z.rhs.type_family == SCALAR_TYPE_FAMILY)
272 {
273 lhs_rhs_element u = root_node.lhs;
274 lhs_rhs_element v = y.lhs;
275 lhs_rhs_element w = z.lhs;
276 lhs_rhs_element alpha = y.rhs;
277 lhs_rhs_element beta = z.rhs;
278
279 bool is_division_y = (y.op.type == OPERATION_BINARY_DIV_TYPE);
280 bool is_division_z = (z.op.type == OPERATION_BINARY_DIV_TYPE);
281 switch (root_node.op.type)
282 {
283 case OPERATION_BINARY_ASSIGN_TYPE:
284 detail::axbx(u,
285 v, alpha, 1, is_division_y, false,
286 w, beta, 1, is_division_z, flip_sign_z);
287 break;
288 case OPERATION_BINARY_INPLACE_ADD_TYPE:
289 detail::axbx_x(u,
290 v, alpha, 1, is_division_y, false,
291 w, beta, 1, is_division_z, flip_sign_z);
292 break;
293 case OPERATION_BINARY_INPLACE_SUB_TYPE:
294 detail::axbx_x(u,
295 v, alpha, 1, is_division_y, true,
296 w, beta, 1, is_division_z, !flip_sign_z);
297 break;
298 default:
299 throw statement_not_supported_exception("Unsupported binary operator for vector operation in root note (should be =, +=, or -=)");
300 }
301 }
302 else // no built-in kernel, we use a temporary.
303 {
304 statement_node new_root_y;
305
306 detail::new_element(new_root_y.lhs, root_node.lhs, ctx);
307
308 new_root_y.op.type_family = OPERATION_BINARY_TYPE_FAMILY;
309 new_root_y.op.type = OPERATION_BINARY_ASSIGN_TYPE;
310
311 new_root_y.rhs.type_family = COMPOSITE_OPERATION_FAMILY;
312 new_root_y.rhs.subtype = INVALID_SUBTYPE;
313 new_root_y.rhs.numeric_type = INVALID_NUMERIC_TYPE;
314 new_root_y.rhs.node_index = leaf.lhs.node_index;
315
316 // work on subexpression:
317 // TODO: Catch exception, free temporary, then rethrow
318 execute_composite(s, new_root_y);
319
320 statement_node new_root_z;
321
322 detail::new_element(new_root_z.lhs, root_node.lhs, ctx);
323
324 new_root_z.op.type_family = OPERATION_BINARY_TYPE_FAMILY;
325 new_root_z.op.type = OPERATION_BINARY_ASSIGN_TYPE;
326
327 new_root_z.rhs.type_family = COMPOSITE_OPERATION_FAMILY;
328 new_root_z.rhs.subtype = INVALID_SUBTYPE;
329 new_root_z.rhs.numeric_type = INVALID_NUMERIC_TYPE;
330 new_root_z.rhs.node_index = leaf.rhs.node_index;
331
332 // work on subexpression:
333 // TODO: Catch exception, free temporaries, then rethrow
334 execute_composite(s, new_root_z);
335
336 // now add:
337 lhs_rhs_element u = root_node.lhs;
338 lhs_rhs_element v = new_root_y.lhs;
339 lhs_rhs_element w = new_root_z.lhs;
340
341 switch (root_node.op.type)
342 {
343 case OPERATION_BINARY_ASSIGN_TYPE:
344 detail::axbx(u,
345 v, 1.0, 1, false, false,
346 w, 1.0, 1, false, flip_sign_z);
347 break;
348 case OPERATION_BINARY_INPLACE_ADD_TYPE:
349 detail::axbx_x(u,
350 v, 1.0, 1, false, false,
351 w, 1.0, 1, false, flip_sign_z);
352 break;
353 case OPERATION_BINARY_INPLACE_SUB_TYPE:
354 detail::axbx_x(u,
355 v, 1.0, 1, false, true,
356 w, 1.0, 1, false, !flip_sign_z);
357 break;
358 default:
359 throw statement_not_supported_exception("Unsupported binary operator for vector operation in root note (should be =, +=, or -=)");
360 }
361
362 detail::delete_element(new_root_y.lhs);
363 detail::delete_element(new_root_z.lhs);
364 }
365 }
366 else
367 throw statement_not_supported_exception("Cannot deal with unknown non-unary and non-binary operations on vectors");
368 }
369 else
370 throw statement_not_supported_exception("Cannot deal with addition of vectors");
371 }
372 else
373 throw statement_not_supported_exception("Unsupported binary operator for vector operations");
374 }
375
376 } // namespace detail
377 } // namespace scheduler
378 } // namespace viennacl
379
380 #endif
381
viennacl::scheduler::detail::extract_context
viennacl::context extract_context(statement_node const &root_node)
Helper routine for extracting the context in which a statement is executed.
Definition: execute_util.hpp:105
viennacl::scheduler::INVALID_SUBTYPE
Definition: forwards.h:266
viennacl::scheduler::lhs_rhs_element::subtype
statement_node_subtype subtype
Definition: forwards.h:340
viennacl::scheduler::statement_node::op
op_element op
Definition: forwards.h:481
viennacl::scheduler::SCALAR_TYPE_FAMILY
Definition: forwards.h:254
forwards.h
This file provides the forward declarations for the main types used within ViennaCL.
viennacl::scheduler::lhs_rhs_element::type_family
statement_node_type_family type_family
Definition: forwards.h:339
viennacl::scheduler::OPERATION_BINARY_ASSIGN_TYPE
Definition: forwards.h:115
viennacl::scheduler::lhs_rhs_element
A class representing the 'data' for the LHS or RHS operand of the respective node.
Definition: forwards.h:337
viennacl::scheduler::statement::array
container_type const & array() const
Definition: forwards.h:528
execute_generic_dispatcher.hpp
Provides unified wrappers for the common routines {as(), asbs(), asbs_s()}, {av(), avbv(), avbv_v()}, and {am(), ambm(), ambm_m()} such that scheduler logic is not cluttered with numeric type decutions.
viennacl::scheduler::op_element::type_family
operation_node_type_family type_family
Definition: forwards.h:473
execute_scalar_assign.hpp
Deals with the execution of x = RHS; for a vector x and any compatible right hand side expression RHS...
viennacl::scheduler::detail::delete_element
void delete_element(lhs_rhs_element &elem)
Definition: execute_util.hpp:266
viennacl::context
Represents a generic 'context' similar to an OpenCL context, but is backend-agnostic and thus also su...
Definition: context.hpp:39
viennacl::scheduler::COMPOSITE_OPERATION_FAMILY
Definition: forwards.h:251
viennacl::scheduler::statement::container_type
std::vector< value_type > container_type
Definition: forwards.h:507
viennacl::scheduler::detail::axbx
void axbx(lhs_rhs_element &x1, lhs_rhs_element const &x2, ScalarType1 const &alpha, vcl_size_t len_alpha, bool reciprocal_alpha, bool flip_sign_alpha, lhs_rhs_element const &x3, ScalarType2 const &beta, vcl_size_t len_beta, bool reciprocal_beta, bool flip_sign_beta)
Wrapper for viennacl::linalg::avbv(), taking care of the argument unwrapping.
Definition: execute_generic_dispatcher.hpp:67
viennacl::scheduler::INVALID_NUMERIC_TYPE
Definition: forwards.h:288
viennacl::scheduler::OPERATION_BINARY_INPLACE_ADD_TYPE
Definition: forwards.h:116
viennacl::scheduler::lhs_rhs_element::numeric_type
statement_node_numeric_type numeric_type
Definition: forwards.h:341
viennacl::scheduler::detail::execute_axbx
void execute_axbx(statement const &s, statement_node const &root_node)
Deals with x = (y) +- (z) where y and z are either data objects or expressions.
Definition: execute_axbx.hpp:40
viennacl::scheduler::statement_node::rhs
lhs_rhs_element rhs
Definition: forwards.h:482
viennacl::scheduler::statement_node::lhs
lhs_rhs_element lhs
Definition: forwards.h:480
viennacl::scheduler::OPERATION_BINARY_TYPE_FAMILY
Definition: forwards.h:59
forwards.h
Provides the datastructures for dealing with a single statement such as 'x = y + z;'.
viennacl::is_division
Helper metafunction for checking whether the provided type is viennacl::op_div (for division) ...
Definition: predicate.hpp:466
viennacl::scheduler::detail::execute_composite
void execute_composite(statement const &s, statement_node const &root_node)
Deals with x = RHS where RHS is an expression and x is either a scalar, a vector, or a matrix...
Definition: execute.hpp:42
viennacl::scheduler::OPERATION_BINARY_SUB_TYPE
Definition: forwards.h:119
viennacl::scheduler::OPERATION_BINARY_INPLACE_SUB_TYPE
Definition: forwards.h:117
viennacl::scheduler::detail::new_element
void new_element(lhs_rhs_element &new_elem, lhs_rhs_element const &old_element, viennacl::context const &ctx)
Definition: execute_util.hpp:204
viennacl::scheduler::op_element::type
operation_node_type type
Definition: forwards.h:474
viennacl::scheduler::OPERATION_BINARY_DIV_TYPE
Definition: forwards.h:121
viennacl::scheduler::statement
The main class for representing a statement such as x = inner_prod(y,z); at runtime.
Definition: forwards.h:502
viennacl::scheduler::OPERATION_BINARY_ADD_TYPE
Definition: forwards.h:118
viennacl::scheduler::lhs_rhs_element::node_index
vcl_size_t node_index
Definition: forwards.h:346
viennacl::scheduler::detail::axbx_x
void axbx_x(lhs_rhs_element &x1, lhs_rhs_element const &x2, ScalarType1 const &alpha, vcl_size_t len_alpha, bool reciprocal_alpha, bool flip_sign_alpha, lhs_rhs_element const &x3, ScalarType2 const &beta, vcl_size_t len_beta, bool reciprocal_beta, bool flip_sign_beta)
Wrapper for viennacl::linalg::avbv_v(), taking care of the argument unwrapping.
Definition: execute_generic_dispatcher.hpp:99
viennacl::scheduler::statement_node
Main datastructure for an node in the statement tree.
Definition: forwards.h:478
viennacl::scheduler::statement_not_supported_exception
Exception for the case the scheduler is unable to deal with the operation.
Definition: forwards.h:38
viennacl::scheduler::OPERATION_UNARY_TYPE_FAMILY
Definition: forwards.h:58
viennacl::scheduler::OPERATION_BINARY_MULT_TYPE
Definition: forwards.h:120