ViennaCL - The Vienna Computing Library  1.7.0
Free open-source GPU-accelerated linear algebra and solver library.
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-2015, 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"
28 
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();
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 
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  {
60  detail::axbx(u,
61  v, 1.0, 1, false, false,
62  w, 1.0, 1, false, flip_sign_z);
63  break;
66  v, 1.0, 1, false, false,
67  w, 1.0, 1, false, flip_sign_z);
68  break;
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  }
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 
84  {
85  // y might be 'v * alpha' or 'v / alpha' with {scalar|vector|matrix} v
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 
96  switch (root_node.op.type)
97  {
99  detail::axbx(u,
100  v, alpha, 1, is_division, false,
101  w, 1.0, 1, false, flip_sign_z);
102  break;
104  detail::axbx_x(u,
105  v, alpha, 1, is_division, false,
106  w, 1.0, 1, false, flip_sign_z);
107  break;
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 
124  new_root_y.op.type = OPERATION_BINARY_ASSIGN_TYPE;
125 
127  new_root_y.rhs.subtype = INVALID_SUBTYPE;
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  {
142  detail::axbx(u,
143  v, 1.0, 1, false, false,
144  w, 1.0, 1, false, flip_sign_z);
145  break;
147  detail::axbx_x(u,
148  v, 1.0, 1, false, false,
149  w, 1.0, 1, false, flip_sign_z);
150  break;
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 
173  {
174  // z might be 'v * alpha' or 'v / alpha' with vector v
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 
185  switch (root_node.op.type)
186  {
188  detail::axbx(u,
189  v, 1.0, 1, false, false,
190  w, beta, 1, is_division, flip_sign_z);
191  break;
193  detail::axbx_x(u,
194  v, 1.0, 1, false, false,
195  w, beta, 1, is_division, flip_sign_z);
196  break;
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 
213  new_root_z.op.type = OPERATION_BINARY_ASSIGN_TYPE;
214 
216  new_root_z.rhs.subtype = INVALID_SUBTYPE;
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  {
231  detail::axbx(u,
232  v, 1.0, 1, false, false,
233  w, 1.0, 1, false, flip_sign_z);
234  break;
236  detail::axbx_x(u,
237  v, 1.0, 1, false, false,
238  w, 1.0, 1, false, flip_sign_z);
239  break;
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 
264  {
265  // z might be 'v * alpha' or 'v / alpha' with vector v
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  {
284  detail::axbx(u,
285  v, alpha, 1, is_division_y, false,
286  w, beta, 1, is_division_z, flip_sign_z);
287  break;
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;
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 
309  new_root_y.op.type = OPERATION_BINARY_ASSIGN_TYPE;
310 
312  new_root_y.rhs.subtype = INVALID_SUBTYPE;
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 
325  new_root_z.op.type = OPERATION_BINARY_ASSIGN_TYPE;
326 
328  new_root_z.rhs.subtype = INVALID_SUBTYPE;
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  {
344  detail::axbx(u,
345  v, 1.0, 1, false, false,
346  w, 1.0, 1, false, flip_sign_z);
347  break;
349  detail::axbx_x(u,
350  v, 1.0, 1, false, false,
351  w, 1.0, 1, false, flip_sign_z);
352  break;
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::context extract_context(statement_node const &root_node)
Helper routine for extracting the context in which a statement is executed.
statement_node_subtype subtype
Definition: forwards.h:340
This file provides the forward declarations for the main types used within ViennaCL.
statement_node_type_family type_family
Definition: forwards.h:339
A class representing the 'data' for the LHS or RHS operand of the respective node.
Definition: forwards.h:337
container_type const & array() const
Definition: forwards.h:528
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.
operation_node_type_family type_family
Definition: forwards.h:473
Deals with the execution of x = RHS; for a vector x and any compatible right hand side expression RHS...
void delete_element(lhs_rhs_element &elem)
Represents a generic 'context' similar to an OpenCL context, but is backend-agnostic and thus also su...
Definition: context.hpp:39
Main namespace in ViennaCL. Holds all the basic types such as vector, matrix, etc. and defines operations upon them.
Definition: cpu_ram.hpp:34
std::vector< value_type > container_type
Definition: forwards.h:507
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: blas3.hpp:36
statement_node_numeric_type numeric_type
Definition: forwards.h:341
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.
Provides the datastructures for dealing with a single statement such as 'x = y + z;'.
Helper metafunction for checking whether the provided type is viennacl::op_div (for division) ...
Definition: predicate.hpp:466
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
void new_element(lhs_rhs_element &new_elem, lhs_rhs_element const &old_element, viennacl::context const &ctx)
operation_node_type type
Definition: forwards.h:474
The main class for representing a statement such as x = inner_prod(y,z); at runtime.
Definition: forwards.h:502
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.
Main datastructure for an node in the statement tree.
Definition: forwards.h:478
Exception for the case the scheduler is unable to deal with the operation.
Definition: forwards.h:38