VisionCpp  0.0.1
executor_subexpr_if_needed.hpp
Go to the documentation of this file.
1 // This file is part of VisionCpp, a lightweight C++ template library
2 // for computer vision and image processing.
3 //
4 // Copyright (C) 2016 Codeplay Software Limited. All Rights Reserved.
5 //
6 // Contact: visioncpp@codeplay.com
7 //
8 // Licensed under the Apache License, Version 2.0 (the "License");
9 // you may not use this file except in compliance with the License.
10 // You may obtain a copy of the License at
11 //
12 // http://www.apache.org/licenses/LICENSE-2.0
13 //
14 // Unless required by applicable law or agreed to in writing, software
15 // distributed under the License is distributed on an "AS IS" BASIS,
16 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 // See the License for the specific language governing permissions and
18 // limitations under the License.
19 
20 /// \file executor_subexpr_if_needed.hpp
21 /// \brief This file contains required classes for break an expression tree into
22 /// subexpression trees for particular nodes when it is needed.
23 
24 #ifndef VISIONCPP_INCLUDE_FRAMEWORK_EXECUTOR_EXECUTOR_SUBEXPR_IF_NEEDED_HPP_
25 #define VISIONCPP_INCLUDE_FRAMEWORK_EXECUTOR_EXECUTOR_SUBEXPR_IF_NEEDED_HPP_
26 
27 namespace visioncpp {
28 namespace internal {
29 
30 /// \struct SubExprRes
31 /// \brief The SubExprRes is used to specialise the get_subexpr_executor
32 /// function for terminal and non-terminal node. The get function in SubExprRes
33 /// executes the expression and returns a leaf node representing the output
34 /// result of the kernel execution, when it is a non-terminal node.
35 template <size_t LC, size_t LR, size_t LCT, size_t LRT, size_t LVL,
36  typename Expr, typename DeviceT>
37 struct SubExprRes {
39  /// \brief The get function in SubExprRes
40  /// executes the expression and returns a leaf node representing the output.
41  /// \param eval_sub: the SubExprRes passed to be executed on the device
42  /// \param dev : the selected device for executing the expression
43  /// \return LeafNode: the leafNode containing the result of the
44  /// subexpression execution.
45  static Type get(Expr &eval_sub, const DeviceT &dev) {
46  using Intermediate_Output = internal::LeafNode<typename Expr::Type, LVL>;
47  auto intermediate_output = Intermediate_Output();
48  internal::fuse<LC, LR, LCT, LRT>(
49  internal::Assign<Intermediate_Output, Expr,
50  Intermediate_Output::Type::Cols,
51  Intermediate_Output::Type::Rows,
52  Intermediate_Output::Type::LeafType,
54  (Intermediate_Output::Level > Expr::Level),
55  Intermediate_Output, Expr>::Type::Level>(
56  intermediate_output, eval_sub),
57  dev);
58  return intermediate_output;
59  }
60 };
61 
62 /// \brief specialisation of the SubExprRes when it is a LeafNode. It does
63 /// nothing but returns the given input leaf node as there is no operation to
64 /// apply. This specialisation is used to speed up the process and to prevent
65 /// extra memory creation and execution.
66 template <size_t LC, size_t LR, size_t LCT, size_t LRT, typename RHS,
67  size_t LVL1, size_t LVL2, typename DeviceT>
68 struct SubExprRes<LC, LR, LCT, LRT, LVL1, internal::LeafNode<RHS, LVL2>, DeviceT> {
70  /// \brief The get function in SubExprRes do nothing but return the leaf node
71  /// when the input expression type is a leafNode.
72  /// \param eval_sub: the SubExprRes passed to be executed on the device
73  /// \return LeafNode: the leafNode containing the result of the
74  /// subexpression execution.
75  static inline Type get(Type &eval_sub, const DeviceT &) {
76  return eval_sub;
77  }
78 };
79 
80 /// \brief template deduction for SubExprRes. This is used when we manually need
81 /// to pass the level in order to avoid double naming
82 template <size_t LC, size_t LR, size_t LCT, size_t LRT, size_t LVL,
83  typename Expr, typename DeviceT>
84 auto get_subexpr_executor(Expr &expr, const DeviceT &dev) ->
87 };
88 
89 // \brief template deduction for SubExprRes. This one will automatically level
90 // the kernel and create a name
91 template <size_t LC, size_t LR, size_t LCT, size_t LRT, typename Expr,
92  typename DeviceT>
93 auto get_subexpr_executor(Expr &expr, const DeviceT &dev) ->
94  typename internal::SubExprRes<LC, LR, LCT, LRT, 1 + Expr::Level,
95  Expr, DeviceT>::Type {
97  expr, dev);
98 };
99 
100 /// \brief \struct ParentForcedExecute is used to check whether or not the
101 /// parent of the Expr requires that the expr to be executed and the LeafNode as
102 /// a result to be returned. True means that execute the expression and return
103 /// the LeafNode; false means return the execute as it is. This is an extra
104 /// check making sure that we wont break the tree when it is not necessary. Such
105 /// example would be when you have reduction as a root of a subexpression tree
106 /// in the middle of an expression, it is possible to minimise the number of
107 /// subexpression to be creating by 2.
108 template <bool ParentConds, typename Expr, typename DeviceT>
109 struct ParentForcedExecute;
110 
111 /// \brief specialisation of ParentForcedExecute when the condition is true
112 template <typename Expr, typename DeviceT>
113 struct ParentForcedExecute<true, Expr, DeviceT> {
115  /// \brief forced_exec here executes the expr and return the leafNode
116  /// template parameters
117  /// \tparam LC: suggested column size for the local memory
118  /// \tparam LR: suggested row size for the local memory
119  /// \tparam LRT: suggested workgroup row size
120  /// \tparam LCT: suggested workgroup column size
121  /// \tparam Expr: the expression type
122  /// function parameters:
123  /// \param expr: the expression needed to be executed
124  /// \param dev : the selected device for executing the expression
125  /// \return LeafNode
126  template <size_t LC, size_t LR, size_t LCT, size_t LRT>
127  static inline Type forced_exec(Expr &expr, const DeviceT &dev) {
128  auto lhs = Type();
129  internal::fuse<LC, LR, LCT, LRT>(
131  Type, Expr, Type::Type::Cols, Type::Type::Rows,
132  Type::Type::LeafType,
133  1 + internal::tools::StaticIf<(Type::Level > Expr::Level), Type,
134  Expr>::Type::Level>(lhs, expr),
135  dev);
136  return lhs;
137  }
138 };
139 /// \brief specialisation of ParentForcedExecute when the condition is false
140 template <typename Expr,typename DeviceT>
141 struct ParentForcedExecute<false, Expr,DeviceT> {
142  using Type = Expr;
143  /// \brief forced_exec here does nothing but return the expression as the parent
144  // of the expression does not require to break the expression further more.
145  /// template parameters
146  /// \tparam LC: suggested column size for the local memory
147  /// \tparam LR: suggested row size for the local memory
148  /// \tparam LRT: suggested workgroup row size
149  /// \tparam LCT: suggested workgroup column size
150  /// \tparam Expr: the expression type
151  /// function parameters:
152  /// \param expr: the input expression
153  /// \return Expr the input expression
154  template <size_t LC, size_t LR, size_t LCT, size_t LRT>
155  static inline Type forced_exec(Expr &expr, const DeviceT &) {
156  return expr;
157  }
158 };
159 
160 /// \brief the specialisation of the IfExprExecNeeded when the decision for
161 /// executing the children of the expression is false and the expression
162 /// category is unary.
163 template <bool ParentConds, typename Expr, typename DeviceT>
164 struct IfExprExecNeeded<false, ParentConds, internal::expr_category::Unary,
165  Expr, DeviceT> {
166  template <size_t LC, size_t LR, size_t LCT, size_t LRT, typename NestedExpr>
167  static inline auto execute_expr(NestedExpr &nestedExpr, const DeviceT &dev) ->
168  typename ParentForcedExecute<
169  ParentConds, typename Expr::template ExprExchange<NestedExpr>, DeviceT>::Type {
170  using NestedType = typename Expr::template ExprExchange<NestedExpr>;
171  auto res = NestedType(nestedExpr);
172 
174  LC, LR, LCT, LRT>(res, dev);
175  }
176 };
177 
178 /// \brief the specialisation of the IfExprExecNeeded when the decision for
179 /// executing the children of the expression is true and the expression
180 /// category is unary.
181 template <bool ParentConds, typename Expr,typename DeviceT>
182 struct IfExprExecNeeded<true, ParentConds, internal::expr_category::Unary,
183  Expr, DeviceT> {
184  template <size_t LC, size_t LR, size_t LCT, size_t LRT, typename NestedExpr>
185  static inline auto execute_expr(NestedExpr &sub_expr, const DeviceT &dev) ->
186  typename ParentForcedExecute<
187  ParentConds,
188  typename Expr::template ExprExchange<decltype(
189  get_subexpr_executor<LC, LR, LCT, LRT>(sub_expr, dev))>, DeviceT>::Type {
190  auto nested_output = get_subexpr_executor<LC, LR, LCT, LRT>(sub_expr, dev);
191  using NestedType =
192  typename Expr::template ExprExchange<decltype(nested_output)>;
193  auto res = NestedType(nested_output);
195  LC, LR, LCT, LRT>(res, dev);
196  }
197 };
198 
199 /// \brief the specialisation of the IfExprExecNeeded when the decision for
200 /// executing the children of the expression is false and the expression
201 /// category is binary.
202 template <bool ParentConds, typename Expr, typename DeviceT>
203 struct IfExprExecNeeded<false, ParentConds, internal::expr_category::Binary,
204  Expr, DeviceT> {
205  template <size_t LC, size_t LR, size_t LCT, size_t LRT, typename LHSExpr,
206  typename RHSExpr>
207  static inline auto execute_expr(LHSExpr &lhsExpr, RHSExpr &rhsExpr,
208  const DeviceT &dev) ->
209  typename ParentForcedExecute<
210  ParentConds,
211  typename Expr::template ExprExchange<LHSExpr, RHSExpr>, DeviceT>::Type {
212  using SubExprType = typename Expr::template ExprExchange<LHSExpr, RHSExpr>;
213  auto res = SubExprType(lhsExpr, rhsExpr);
215  LC, LR, LCT, LRT>(res, dev);
216  }
217 };
218 
219 /// \brief the specialisation of the IfExprExecNeeded when the decision for
220 /// executing the children of the expression is true and the expression
221 /// category is binary.
222 template <bool ParentConds, typename Expr, typename DeviceT>
223 struct IfExprExecNeeded<true, ParentConds, internal::expr_category::Binary,
224  Expr, DeviceT> {
225  template <size_t LC, size_t LR, size_t LCT, size_t LRT, typename LHSExpr,
226  typename RHSExpr>
227  static inline auto execute_expr(LHSExpr &lhsExpr, RHSExpr &rhsExpr,
228  const DeviceT &dev) ->
229 
230  typename ParentForcedExecute<
231  ParentConds,
232  typename Expr::template ExprExchange<
233  decltype(get_subexpr_executor<LC, LR, LCT, LRT>(lhsExpr, dev)),
234  decltype(get_subexpr_executor<LC, LR, LCT, LRT>(rhsExpr,
235  dev))>, DeviceT>::Type {
236  auto lhs_output = get_subexpr_executor<LC, LR, LCT, LRT>(lhsExpr, dev);
237  auto rhs_output = get_subexpr_executor<LC, LR, LCT, LRT>(rhsExpr, dev);
238  using SubExprType =
239  typename Expr::template ExprExchange<decltype(lhs_output),
240  decltype(rhs_output)>;
241  auto res = SubExprType(lhs_output, rhs_output);
243  LC, LR, LCT, LRT>(res, dev);
244  }
245 };
246 
247 /// \brief template deduction for IfExprExecNeeded when the expression category
248 /// is unary
249 template <bool Conds, bool ParentConds, typename Expr, size_t LC, size_t LR,
250  size_t LCT, size_t LRT, typename NestedExpr, typename DeviceT>
251 inline auto execute_expr(NestedExpr nestedExpr, const DeviceT &dev)
252  -> decltype(internal::IfExprExecNeeded<
253  Conds, ParentConds, internal::expr_category::Unary,
254  Expr, DeviceT>::template execute_expr<LC, LR, LCT, LRT>(nestedExpr, dev)) {
256  Conds, ParentConds, internal::expr_category::Unary,
257  Expr, DeviceT>::template execute_expr<LC, LR, LCT, LRT>(nestedExpr, dev);
258 }
259 
260 /// \brief template deduction for IfExprExecNeeded when the expression
261 /// category is Binary
262 template <bool Conds, bool ParentConds, typename Expr, size_t LC, size_t LR,
263  size_t LCT, size_t LRT, typename LHSExpr, typename RHSExpr,
264  typename DeviceT>
265 inline auto execute_expr(LHSExpr lhsExpr, RHSExpr rhsExpr, const DeviceT &dev)
266  -> decltype(internal::IfExprExecNeeded<
267  Conds, ParentConds, internal::expr_category::Binary,
268  Expr, DeviceT>::template execute_expr<LC, LR, LCT, LRT>(lhsExpr, rhsExpr, dev)) {
270  Conds, ParentConds, internal::expr_category::Binary,
271  Expr, DeviceT>::template execute_expr<LC, LR, LCT, LRT>(lhsExpr, rhsExpr, dev);
272 }
273 } // internal
274 } // visioncpp
275 #endif // VISIONCPP_INCLUDE_FRAMEWORK_EXECUTOR_EXECUTOR_SUBEXPR_IF_NEEDED_HPP_
auto get_subexpr_executor(Expr &expr, const DeviceT &dev) -> typename internal::SubExprRes< LC, LR, LCT, LRT, LVL, Expr, DeviceT >::Type
template deduction for SubExprRes.
auto execute_expr(NestedExpr nestedExpr, const DeviceT &dev) -> decltype(internal::IfExprExecNeeded< Conds, ParentConds, internal::expr_category::Unary, Expr, DeviceT >::template execute_expr< LC, LR, LCT, LRT >(nestedExpr, dev))
template deduction for IfExprExecNeeded when the expression category is unary
VisionCpp namespace.
Definition: sycl/device.hpp:24
The definition is in Assign file.
Definition: assign.hpp:44
static auto execute_expr(NestedExpr &nestedExpr, const DeviceT &dev) -> typename ParentForcedExecute< ParentConds, typename Expr::template ExprExchange< NestedExpr >, DeviceT >::Type
static auto execute_expr(LHSExpr &lhsExpr, RHSExpr &rhsExpr, const DeviceT &dev) -> typename ParentForcedExecute< ParentConds, typename Expr::template ExprExchange< LHSExpr, RHSExpr >, DeviceT >::Type
static auto execute_expr(NestedExpr &sub_expr, const DeviceT &dev) -> typename ParentForcedExecute< ParentConds, typename Expr::template ExprExchange< decltype(get_subexpr_executor< LC, LR, LCT, LRT >(sub_expr, dev))>, DeviceT >::Type
static auto execute_expr(LHSExpr &lhsExpr, RHSExpr &rhsExpr, const DeviceT &dev) -> typename ParentForcedExecute< ParentConds, typename Expr::template ExprExchange< decltype(get_subexpr_executor< LC, LR, LCT, LRT >(lhsExpr, dev)), decltype(get_subexpr_executor< LC, LR, LCT, LRT >(rhsExpr, dev))>, DeviceT >::Type
IfExprExecNeeded is used to decide: 1) the expression should force its children to launch a separate ...
Definition: executor.hpp:74
the definition is in LeafNode.
Definition: leaf_node.hpp:38
static constexpr size_t Level
Definition: leaf_node.hpp:43
static Type forced_exec(Expr &expr, const DeviceT &)
forced_exec here does nothing but return the expression as the parent
static Type forced_exec(Expr &expr, const DeviceT &dev)
forced_exec here executes the expr and return the leafNode template parameters
to check whether or not the parent of the Expr requires that the expr to be executed and the LeafNode...
static Type get(Type &eval_sub, const DeviceT &)
The get function in SubExprRes do nothing but return the leaf node when the input expression type is ...
The definition is in SubExprRes file.
static Type get(Expr &eval_sub, const DeviceT &dev)
The get function in SubExprRes executes the expression and returns a leaf node representing the outpu...
It is used to select either of the input type based the Conds template parameters.
Definition: static_if.hpp:52