Expression Templates Library (ETL)
helpers.hpp
1 //=======================================================================
2 // Copyright (c) 2014-2023 Baptiste Wicht
3 // Distributed under the terms of the MIT License.
4 // (See accompanying file LICENSE or copy at
5 // http://opensource.org/licenses/MIT)
6 //=======================================================================
7 
8 #pragma once
9 
10 namespace etl {
11 
17 template <typename E>
18 constexpr size_t dimensions([[maybe_unused]] const E& expr) noexcept {
20 }
21 
27 template <typename E>
28 constexpr size_t dimensions() noexcept {
30 }
31 
37 template <typename E>
38 constexpr int complexity([[maybe_unused]] const E& expr) noexcept {
40 }
41 
47 template <typename E>
48 constexpr int complexity() noexcept {
50 }
51 
57 template <dyn_expr E>
58 size_t rows(const E& expr) {
59  return etl_traits<E>::dim(expr, 0);
60 }
61 
67 template <fast_expr E>
68 constexpr size_t rows(const E& expr) noexcept {
69  return (void)expr, etl_traits<E>::template dim<0>();
70 }
71 
77 template <dyn_matrix_c E>
78 size_t columns(const E& expr) {
79  return etl_traits<E>::dim(expr, 1);
80 }
81 
87 template <fast_matrix_c E>
88 constexpr size_t columns(const E& expr) noexcept {
89  return (void)expr, etl_traits<E>::template dim<1>();
90 }
91 
97 template <dyn_expr E>
98 size_t size(const E& expr) {
99  return etl_traits<E>::size(expr);
100 }
101 
107 template <fast_expr E>
108 constexpr size_t size(const E& expr) noexcept {
109  return (void)expr, etl_traits<E>::size();
110 }
111 
117 template <dyn_matrix_c E>
118 size_t subsize(const E& expr) {
119  return etl_traits<E>::size(expr) / etl_traits<E>::dim(expr, 0);
120 }
121 
127 template <fast_matrix_c E>
128 constexpr size_t subsize(const E& expr) noexcept {
129  return (void)expr, etl_traits<E>::size() / etl_traits<E>::template dim<0>();
130 }
131 
138 template <size_t D, dyn_expr E>
139 size_t dim(const E& e) noexcept {
140  return etl_traits<E>::dim(e, D);
141 }
142 
149 template <etl_expr E>
150 size_t dim(const E& e, size_t d) noexcept {
151  return etl_traits<E>::dim(e, d);
152 }
153 
160 template <size_t D, fast_expr E>
161 constexpr size_t dim(const E& e) noexcept {
162  return (void)e, etl_traits<E>::template dim<D>();
163 }
164 
169 template <size_t D, fast_expr E>
170 constexpr size_t dim() noexcept {
171  return decay_traits<E>::template dim<D>();
172 }
173 
177 template <typename E>
179 
183 template <typename E>
184 requires(generator<E>)
185 struct safe_dimensions_impl<E> : std::integral_constant<size_t, std::numeric_limits<size_t>::max()> {};
186 
190 template <typename E>
191 requires(!generator<E>)
192 struct safe_dimensions_impl<E> : std::integral_constant<size_t, etl_traits<E>::dimensions()> {};
193 
197 template <typename E, typename Enable = void>
199 
206 template <typename E>
207 constexpr std::pair<size_t, size_t> index_to_2d(E&& sub, size_t i) {
208  return decay_traits<E>::storage_order == order::RowMajor ? std::make_pair(i / dim<1>(sub), i % dim<1>(sub))
209  : std::make_pair(i % dim<0>(sub), i / dim<0>(sub));
210 }
211 
217 template <etl_2d E>
218 size_t row_stride(E&& expr) {
219  return decay_traits<E>::storage_order == order::RowMajor ? etl::dim<1>(expr) : 1;
220 }
221 
227 template <etl_2d E>
228 size_t col_stride(E&& expr) {
229  return decay_traits<E>::storage_order == order::RowMajor ? 1 : etl::dim<0>(expr);
230 }
231 
237 template <etl_2d E>
238 size_t minor_stride(E&& expr) {
239  return decay_traits<E>::storage_order == order::RowMajor ? etl::dim<0>(expr) : etl::dim<1>(expr);
240 }
241 
247 template <etl_2d E>
248 size_t major_stride(E&& expr) {
249  return decay_traits<E>::storage_order == order::RowMajor ? etl::dim<1>(expr) : etl::dim<0>(expr);
250 }
251 
263 template <typename P1, typename P2>
264 bool memory_alias(const P1* a_begin, const P1* a_end, const P2* b_begin, const P2* b_end) {
265  cpp_assert(a_begin <= a_end, "memory_alias works on ordered ranges");
266  cpp_assert(b_begin <= b_end, "memory_alias works on ordered ranges");
267 
268  return reinterpret_cast<uintptr_t>(a_begin) < reinterpret_cast<uintptr_t>(b_end)
269  && reinterpret_cast<uintptr_t>(a_end) > reinterpret_cast<uintptr_t>(b_begin);
270 }
271 
277 template <typename E>
279  expr.ensure_cpu_up_to_date();
280 }
281 
288 template <typename E>
289 bool safe_is_cpu_up_to_date(E&& expr) {
290  if constexpr (is_dma<E>) {
291  return expr.is_cpu_up_to_date();
292  } else {
293  return true;
294  }
295 }
296 
303 template <typename E>
304 bool safe_is_gpu_up_to_date(E&& expr) {
305  if constexpr (is_dma<E>) {
306  return expr.is_gpu_up_to_date();
307  } else {
308  return false;
309  }
310 }
311 
322 template <typename E>
323 decltype(auto) smart_forward(E& expr) {
324  if constexpr (is_temporary_expr<E>) {
325  return force_temporary(expr);
326  } else {
327  return make_temporary(expr);
328  }
329 }
330 
342 template <typename E>
343 decltype(auto) smart_forward_gpu(E& expr) {
344  if constexpr (is_temporary_expr<E>) {
345  if constexpr (E::gpu_computable) {
346  return force_temporary_gpu(expr);
347  } else {
348  return force_temporary(expr);
349  }
350  } else {
351  return make_temporary(expr);
352  }
353 }
354 
355 // Unary smart_gpu_compute
356 
367 template <typename E, typename Y>
368 decltype(auto) smart_gpu_compute_hint(E& expr, Y& y) {
369  if constexpr (is_temporary_expr<E>) {
370  if constexpr (E::gpu_computable) {
371  return force_temporary_gpu(expr);
372  } else {
373  auto t = force_temporary(expr);
374  t.ensure_gpu_up_to_date();
375  return t;
376  }
377  } else {
378  return expr.gpu_compute_hint(y);
379  }
380 }
381 
382 // Binary smart_gpu_compute
383 
396 template <typename X, typename Y>
397 decltype(auto) smart_gpu_compute(X& x, Y& y) {
398  if constexpr (is_temporary_expr<X>) {
399  if constexpr (X::gpu_computable) {
400  return y = x;
401  } else {
402  auto t = force_temporary(x);
403  t.ensure_gpu_up_to_date();
404  y = t;
405  return y;
406  }
407  } else {
408  if constexpr (is_dma<X>) {
409  x.ensure_gpu_up_to_date();
410  y.ensure_gpu_allocated();
411  y.gpu_copy_from(x.gpu_memory());
412  return y;
413  } else {
414  return x.gpu_compute(y);
415  }
416  }
417 }
418 
419 // Select version
420 
433 template <typename X, typename Y>
434 decltype(auto) select_smart_gpu_compute(X& x, Y& y) {
435  if constexpr (should_gpu_compute_direct<X>) {
436  return smart_gpu_compute_hint(x, y);
437  } else {
438  return smart_gpu_compute(x, y);
439  }
440 }
441 
447 template <typename T>
448 constexpr size_t gpu_inc = is_scalar<T> ? 0 : 1;
449 
450 } //end of namespace etl
constexpr int complexity([[maybe_unused]] const E &expr) noexcept
Return the complexity of the expression.
Definition: helpers.hpp:38
Utility to get the dimensions of an expressions, with support for generator.
Definition: helpers.hpp:178
bool safe_is_gpu_up_to_date(E &&expr)
Indicates if the GPU memory is up to date. If the expression does not have direct memory access...
Definition: helpers.hpp:304
D D
The number of dimensions.
Definition: dyn_matrix_view.hpp:24
decltype(auto) select_smart_gpu_compute(X &x, Y &y)
Compute the expression into a representation that is GPU up to date and possibly store this represent...
Definition: helpers.hpp:434
Traits to get information about ETL types.
Definition: tmp.hpp:68
Root namespace for the ETL library.
Definition: adapter.hpp:15
static constexpr size_t dimensions()
Return the number of dimensions of the expression.
Definition: traits_base.hpp:31
bool memory_alias(const P1 *a_begin, const P1 *a_end, const P2 *b_begin, const P2 *b_end)
Test if two memory ranges overlap.
Definition: helpers.hpp:264
size_t minor_stride(E &&expr)
Returns the minor stride of the given ETL matrix expression.
Definition: helpers.hpp:238
size_t major_stride(E &&expr)
Returns the major stride of the given ETL matrix expression.
Definition: helpers.hpp:248
auto dim(E &&value, size_t i) -> detail::identity_helper< E, dim_view< detail::build_identity_type< E >, D >>
Return a view representing the ith Dth dimension.
Definition: view_expression_builder.hpp:25
size_t columns(const E &expr)
Returns the number of columns of the given ETL expression.
Definition: helpers.hpp:78
decltype(auto) smart_forward_gpu(E &expr)
Smart forwarding for a temporary expression that will be computed in GPU.
Definition: helpers.hpp:343
void safe_ensure_cpu_up_to_date(E &&expr)
Ensure that the CPU is up to date.
Definition: helpers.hpp:278
constexpr std::pair< size_t, size_t > index_to_2d(E &&sub, size_t i)
Convert a flat index into a 2D index.
Definition: helpers.hpp:207
requires(D > 0) struct dyn_base
Matrix with run-time fixed dimensions.
Definition: dyn_base.hpp:113
constexpr size_t gpu_inc
The space between two elements in GPU for the given type.
Definition: helpers.hpp:448
size_t col_stride(E &&expr)
Returns the column stride of the given ETL matrix expression.
Definition: helpers.hpp:228
decltype(auto) smart_forward(E &expr)
Smart forwarding for a temporary expression.
Definition: helpers.hpp:323
decltype(auto) force_temporary_gpu(E &&expr)
Force a temporary out of the expression.
Definition: temporary.hpp:196
decltype(auto) force_temporary(E &&expr)
Force a temporary out of the expression.
Definition: temporary.hpp:91
size_t row_stride(E &&expr)
Returns the row stride of the given ETL matrix expression.
Definition: helpers.hpp:218
size_t rows(const E &expr)
Returns the number of rows of the given ETL expression.
Definition: helpers.hpp:58
decltype(auto) smart_gpu_compute_hint(E &expr, Y &y)
Compute the expression into a representation that is GPU up to date.
Definition: helpers.hpp:368
Row-Major storage.
decltype(auto) smart_gpu_compute(X &x, Y &y)
Compute the expression into a representation that is GPU up to date and store this representation in ...
Definition: helpers.hpp:397
decltype(auto) make_temporary(E &&expr)
Make a temporary out of the expression if necessary.
Definition: temporary.hpp:173
bool safe_is_cpu_up_to_date(E &&expr)
Indicates if the CPU memory is up to date. If the expression does not have direct memory access...
Definition: helpers.hpp:289
size_t subsize(const E &expr)
Returns the sub-size of the given ETL expression, i.e. the size not considering the first dimension...
Definition: helpers.hpp:118
constexpr size_t safe_dimensions
Utility to get the dimensions of an expressions, with support for generator.
Definition: helpers.hpp:198