BlackCat_Tensors
A GPU-supported autograd and linear algebra library, designed for neural network construction
tree_evaluator.h
Go to the documentation of this file.
1 /* Project: BlackCat_Tensors
2  * Author: JosephJaspers
3  * Copyright 2018
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
8 
9 #ifndef PARSE_TREE_COMPLEX_EVALUATOR_H_
10 #define PARSE_TREE_COMPLEX_EVALUATOR_H_
11 
12 #include "nd_evaluator/evaluator.h"
14 
15 
37 namespace bc {
38 namespace tensors {
39 namespace exprs {
40 
41 template<class Is_SubXpr=std::false_type>
42 class Evaluator
43 {
44  template<class Xpr, class Stream>
45  static void nd_evaluate(const Xpr expression, Stream stream)
46  {
47  using system_tag = typename Stream::system_tag;
48  using nd_evaluator = exprs::evaluator::Evaluator<system_tag>;
49 
50  bc::traits::constexpr_if<expression_traits<Xpr>::is_expr::value>([&]() {
51  nd_evaluator::template nd_evaluate<Xpr::tensor_iterator_dim>(expression, stream);
52  });
53  }
54 
55  template<class AssignmentOp, class Left, class Right, class Stream>
56  static void greedy_optimization(Left left, Right right, Stream stream)
57  {
58  auto right_xpr = optimizer<Right>::temporary_injection(right, stream);
59  auto assign_xpr = make_bin_expr<AssignmentOp>(left, right_xpr);
60  nd_evaluate(assign_xpr, stream);
61 
62  if (!Is_SubXpr::value) {
63  using right_xpr_t = std::decay_t<decltype(right_xpr)>;
65  }
66  }
67 
68 public:
69  // y += blas_op(x1) +/- blas_op(x2) OR y -= blas_op(x1) +/- blas_op(x2)
70  template<class lv, class rv, class Stream, class Op>
71  static std::enable_if_t<
72  optimizer<Bin_Op<Op, lv, rv>>::requires_greedy_eval &&
74  evaluate(Bin_Op<Op, lv, rv> expression, Stream stream)
75  {
76  static constexpr bool entirely_blas_expression = optimizer<rv>::entirely_blas_expr; // all operations are +/- blas calls
77  static constexpr int alpha_mod = bc::oper::operation_traits<Op>::alpha_modifier;
78  static constexpr int beta_mod = bc::oper::operation_traits<Op>::beta_modifier;
79 
80  auto output = make_output_data<alpha_mod, beta_mod>(expression.left);
81  auto right = optimizer<rv>::linear_eval(expression.right, output, stream);
82 
83  if /*constexpr*/ (!entirely_blas_expression)
84  greedy_optimization<Op>(expression.left, right, stream);
85  else if (!Is_SubXpr::value) {
87  }
88  }
89 
90  // y = <expression with at least 1 blas_op>
91  template<class lv, class rv, class Stream>
92  static std::enable_if_t<
93  optimizer<Bin_Op<bc::oper::Assign, lv, rv>>::requires_greedy_eval>
95  {
98  constexpr bool entirely_blas_expr = optimizer<rv>::entirely_blas_expr;
99  constexpr bool partial_blas_expr = optimizer<rv>::partial_blas_expr;
100 
101  auto output = make_output_data<alpha, beta>(expression.left);
102  using expr_rv_t = std::decay_t<decltype(expression.right)>;
103 
104  auto right = bc::traits::constexpr_ternary<partial_blas_expr>(
105  [&]() {
107  expression.right, output, stream);
108  },
109  [&]() {
111  expression.right, output, stream);
112  });
113 
114  using assignment_oper = std::conditional_t<
115  partial_blas_expr, oper::Add_Assign, oper::Assign>;
116 
117  bc::traits::constexpr_if<!entirely_blas_expr>([&]() {
118  greedy_optimization<assignment_oper>(expression.left, right, stream);
119  });
120  }
121 
122  // y %= <expression> OR y /= <expression>
123  template<class lv, class rv, class Stream, class Op>
124  static std::enable_if_t<
125  optimizer<Bin_Op<Op, lv, rv>>::requires_greedy_eval &&
127  evaluate(Bin_Op<Op, lv, rv> expression, Stream stream) {
128  greedy_optimization<Op>(expression.left, expression.right, stream);
129  }
130 
131  // y <any assignment op> <elementwise-only expression>
132  template<class Xpr, class Stream>
133  static std::enable_if_t<!optimizer<Xpr>::requires_greedy_eval>
134  evaluate(Xpr expression, Stream stream) {
135  nd_evaluate(expression, stream);
136  }
137 };
138 
140 
141  template<
142  class Xpr,
143  class Stream,
144  class=std::enable_if_t<expression_traits<Xpr>::is_array::value>>
145  static auto evaluate(Xpr expression, Stream stream) {
146  return expression;
147  }
148 
154  template<
155  class Xpr,
156  class Stream,
157  class=std::enable_if_t<expression_traits<Xpr>::is_expr::value>,
158  int=0>
159  static auto evaluate(Xpr expression, Stream stream)
160  {
161  using value_type = typename Xpr::value_type;
162  auto allocator = stream.template get_allocator_rebound<value_type>();
163  auto shape = expression.get_shape();
164  auto temporary = make_kernel_array(shape, allocator, temporary_tag());
165 
167  make_bin_expr<oper::Assign>(temporary, expression), stream);
168  return temporary;
169  }
170 };
171 
172 // ------------------------------ endpoints ------------------------------//
173 template<class Xpr, class Stream>
174 static auto greedy_evaluate(Xpr expression, Stream stream) {
176  //Initialize a logging_stream (does not call any jobs-enqueued or allocate memory, simply logs memory requirements)
178  GreedyEvaluator::evaluate(expression, logging_stream); //record allocations/deallocations
179  stream.get_allocator().reserve(logging_stream.get_max_allocated()); //Reserve the maximum amount of memory
180  }
181  return GreedyEvaluator::evaluate(expression, stream); //Do the actual calculation
182 }
183 
184 template<class Xpr, class Stream>
185 static auto evaluate(Xpr expression, Stream stream) {
188  Evaluator<>::evaluate(expression, logging_stream);
189  stream.get_allocator().reserve(logging_stream.get_max_allocated());
190  }
191 
192  return Evaluator<>::evaluate(expression, stream);
193 }
194 
195 template<class Xpr, class SystemTag>
196 static auto greedy_evaluate(Xpr expression, bc::streams::Logging_Stream<SystemTag> logging_stream) {
197  return GreedyEvaluator::evaluate(expression, logging_stream);
198 }
199 
200 template<class Xpr, class SystemTag>
201 static auto evaluate(Xpr expression, bc::streams::Logging_Stream<SystemTag> logging_stream) {
202  return Evaluator<>::evaluate(expression, logging_stream);
203 }
204 
205 } //ns exprs
206 } //ns tensors
207 } //ns BC
208 
209 #endif /* PARSE_TREE_COMPLEX_EVALUATOR_H_ */
Definition: tree_evaluator.h:139
auto make_kernel_array(Shape< N > shape, Allocator allocator, Tags...)
Definition: array_kernel_array.h:134
static std::enable_if_t< optimizer< Bin_Op< Op, lv, rv > >::requires_greedy_eval &&bc::oper::operation_traits< Op >::is_linear_assignment_operation > evaluate(Bin_Op< Op, lv, rv > expression, Stream stream)
Definition: tree_evaluator.h:74
Rv right
Definition: expression_binary.h:62
Definition: expression_template_traits.h:48
static auto evaluate(Xpr expression, Stream stream)
Definition: tree_evaluator.h:145
Lv left
Definition: expression_binary.h:61
static std::enable_if_t< optimizer< Bin_Op< Op, lv, rv > >::requires_greedy_eval &&!bc::oper::operation_traits< Op >::is_linear_assignment_operation > evaluate(Bin_Op< Op, lv, rv > expression, Stream stream)
Definition: tree_evaluator.h:127
Definition: binary.h:48
unsigned get_max_allocated() const
Definition: logging_stream.h:79
static std::enable_if_t<!optimizer< Xpr >::requires_greedy_eval > evaluate(Xpr expression, Stream stream)
Definition: tree_evaluator.h:134
Definition: common.h:18
Definition: tree_evaluator.h:42
Definition: tree_evaluator_optimizer.h:28
Definition: operation_traits.h:24
static auto evaluate(Xpr expression, Stream stream)
Returns a kernel_array containing the tag temporary_tag, the caller of the function is responsible fo...
Definition: tree_evaluator.h:159
Definition: logging_stream.h:56
BCINLINE auto shape(Integers... ints)
Definition: shape.h:264
static std::enable_if_t< optimizer< Bin_Op< bc::oper::Assign, lv, rv > >::requires_greedy_eval > evaluate(Bin_Op< oper::Assign, lv, rv > expression, Stream stream)
Definition: tree_evaluator.h:94
Definition: device.h:27
The Evaluator determines if an expression needs to be greedily optimized.
Definition: algorithms.h:22
Definition: binary.h:54