Expression Templates Library (ETL)
gpu_dyn.hpp
Go to the documentation of this file.
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 
13 #pragma once
14 
15 #include "etl/dyn_base.hpp" //The base class and utilities
16 
17 namespace etl {
18 
24 template <typename T, order SO, size_t D>
25 struct gpu_dyn_matrix_impl final : dense_dyn_base<gpu_dyn_matrix_impl<T, SO, D>, T, SO, D>, dim_testable<gpu_dyn_matrix_impl<T, SO, D>> {
26  static constexpr size_t n_dimensions = D;
27  static constexpr order storage_order = SO;
29 
33  using value_type = T;
34  using dimension_storage_impl = std::array<size_t, n_dimensions>;
36  using const_memory_type = const value_type*;
37 
38  using iterator = std::conditional_t<SO == order::RowMajor, value_type*, etl::iterator<this_type>>;
39  using const_iterator = std::conditional_t<SO == order::RowMajor, const value_type*, etl::iterator<const this_type>>;
40 
44  template <typename V = default_vec>
45  using vec_type = typename V::template vec_type<T>;
46 
47 private:
48  using base_type::_dimensions;
49  using base_type::_memory;
50  using base_type::_size;
51 
52  using base_type::check_invariants;
53 
54 public:
55  using base_type::_gpu;
56 
57  // Construction
58 
65  gpu_dyn_matrix_impl() noexcept : base_type() {
66  //Nothing else to init
67  }
68 
73  gpu_dyn_matrix_impl(const gpu_dyn_matrix_impl& rhs) noexcept(assert_nothrow) : base_type(rhs) {
74  // The CPU status is discarded!
75 
76  cpp_assert(rhs.is_gpu_up_to_date() == this->is_gpu_up_to_date(), "gpu_dyn_matrix_impl(&) must preserve GPU status");
77  }
78 
83  gpu_dyn_matrix_impl(gpu_dyn_matrix_impl&& rhs) noexcept : base_type(std::move(rhs)) {
84  _memory = rhs._memory;
85  rhs._memory = nullptr;
86  }
87 
96  gpu_dyn_matrix_impl& operator=(const gpu_dyn_matrix_impl& rhs) noexcept(assert_nothrow) {
97  if (this != &rhs) {
98  if (!_size) {
99  _size = rhs._size;
100  _dimensions = rhs._dimensions;
101  } else {
102  validate_assign(*this, rhs);
103  }
104 
105  // TODO Find a better solution
106  const_cast<gpu_dyn_matrix_impl&>(rhs).assign_to(*this);
107  }
108 
109  check_invariants();
110 
111  cpp_assert(rhs.is_gpu_up_to_date() == this->is_gpu_up_to_date(), "gpu_dyn_matrix_impl::operator= must preserve GPU status");
112 
113  return *this;
114  }
115 
125  if (this != &rhs) {
126  _gpu = std::move(rhs._gpu);
127 
128  _size = rhs._size;
129  _dimensions = std::move(rhs._dimensions);
130 
131  rhs._size = 0;
132  rhs._memory = nullptr;
133  }
134 
135  check_invariants();
136 
137  return *this;
138  }
139 
145  template <etl_expr E>
146  gpu_dyn_matrix_impl& operator=(E&& e) noexcept requires(!std::same_as<std::decay_t<E>, gpu_dyn_matrix_impl<T, SO, D>> && std::convertible_to<value_t<E>, value_type>) {
147  // It is possible that the matrix was not initialized before
148  // In the case, get the the dimensions from the expression and
149  // initialize the matrix
150  if (!_size) {
151  inherit(e);
152  } else {
153  validate_assign(*this, e);
154  }
155 
156  // Avoid aliasing issues
157  if constexpr (!decay_traits<E>::is_linear) {
158  if (e.alias(*this)) {
159  // Create a temporary to hold the result
160  this_type tmp;
161 
162  // Assign the expression to the temporary
163  tmp = e;
164 
165  // Assign the temporary to this matrix
166  *this = tmp;
167  } else {
168  e.assign_to(*this);
169  }
170  } else {
171  // Direct assignment of the expression into this matrix
172  e.assign_to(*this);
173  }
174 
175  check_invariants();
176 
177  return *this;
178  }
179 
184  gpu_dyn_matrix_impl& operator=([[maybe_unused]] value_type v) noexcept {
185  cpp_unreachable("Invalid call to operator=(value_type) for GPU dyn matrix");
186 
187  return *this;
188  }
189 
193  ~gpu_dyn_matrix_impl() noexcept {
194  // Nothing to do here
195  }
196 
201  template <typename Y>
202  auto& gpu_compute_hint([[maybe_unused]] Y& y) {
203  this->ensure_gpu_up_to_date();
204  return *this;
205  }
206 
211  template <typename Y>
212  const auto& gpu_compute_hint([[maybe_unused]] Y& y) const {
213  this->ensure_gpu_up_to_date();
214  return *this;
215  }
216 
217  // Assignment functions
218 
223  template <typename L>
224  void assign_to(L&& lhs) const {
225  std_assign_evaluate(*this, std::forward<L>(lhs));
226  }
227 
232  template <typename L>
233  void assign_add_to(L&& lhs) const {
234  std_add_evaluate(*this, std::forward<L>(lhs));
235  }
236 
241  template <typename L>
242  void assign_sub_to(L&& lhs) const {
243  std_sub_evaluate(*this, std::forward<L>(lhs));
244  }
245 
250  template <typename L>
251  void assign_mul_to(L&& lhs) const {
252  std_mul_evaluate(*this, std::forward<L>(lhs));
253  }
254 
259  template <typename L>
260  void assign_div_to(L&& lhs) const {
261  std_div_evaluate(*this, std::forward<L>(lhs));
262  }
263 
268  template <typename L>
269  void assign_mod_to(L&& lhs) const {
270  std_mod_evaluate(*this, std::forward<L>(lhs));
271  }
272 
273  // Internals
274 
279  void visit([[maybe_unused]] const detail::evaluator_visitor& visitor) const {}
280 
286  template <typename E>
287  void inherit([[maybe_unused]] const E& e) {
288  if constexpr (etl::decay_traits<E>::is_generator) {
289  cpp_unreachable("Impossible to inherit dimensions from generators");
290  } else {
291  cpp_assert(n_dimensions == etl::dimensions(e), "Invalid number of dimensions");
292 
293  // Compute the size and new dimensions
294  _size = 1;
295  for (size_t d = 0; d < n_dimensions; ++d) {
296  _dimensions[d] = etl::dim(e, d);
297  _size *= _dimensions[d];
298  }
299  }
300  }
301 
307  void resize_scalar() {
308  _size = 1;
309  _dimensions[0] = 1;
310  }
311 
318  friend std::ostream& operator<<(std::ostream& os, const gpu_dyn_matrix_impl& mat) {
319  if (D == 1) {
320  return os << "GV[" << mat.size() << "]";
321  }
322 
323  os << "GM[" << mat.dim(0);
324 
325  for (size_t i = 1; i < D; ++i) {
326  os << "," << mat.dim(i);
327  }
328 
329  return os << "]";
330  }
331 };
332 
333 #ifndef CPP_UTILS_ASSERT_EXCEPTION
334 static_assert(std::is_nothrow_default_constructible_v<gpu_dyn_matrix<double>>, "dyn_vector should be nothrow default constructible");
335 static_assert(std::is_nothrow_copy_constructible_v<gpu_dyn_matrix<double>>, "dyn_vector should be nothrow copy constructible");
336 static_assert(std::is_nothrow_move_constructible_v<gpu_dyn_matrix<double>>, "dyn_vector should be nothrow move constructible");
337 static_assert(std::is_nothrow_copy_assignable_v<gpu_dyn_matrix<double>>, "dyn_vector should be nothrow copy assignable");
338 static_assert(std::is_nothrow_move_assignable_v<gpu_dyn_matrix<double>>, "dyn_vector should be nothrow move assignable");
339 static_assert(std::is_nothrow_destructible_v<gpu_dyn_matrix<double>>, "dyn_vector should be nothrow destructible");
340 #endif
341 
342 } //end of namespace etl
CRTP class to inject iterators functions.
Definition: iterable.hpp:23
void visit([[maybe_unused]] const detail::evaluator_visitor &visitor) const
Apply the given visitor to this expression and its descendants.
Definition: gpu_dyn.hpp:279
value_type * memory_type
The memory type.
Definition: gpu_dyn.hpp:35
Dense Matrix with run-time fixed dimensions. The matrix support an arbitrary number of dimensions...
Definition: dyn_base.hpp:294
gpu_dyn_matrix_impl(const gpu_dyn_matrix_impl &rhs) noexcept(assert_nothrow)
Copy construct a matrix.
Definition: gpu_dyn.hpp:73
gpu_dyn_matrix_impl & operator=(gpu_dyn_matrix_impl &&rhs) noexcept
Move assign from another matrix.
Definition: gpu_dyn.hpp:124
void inherit([[maybe_unused]] const E &e)
Inherit the dimensions of an ETL expressions. This must only be called when the matrix has no dimensi...
Definition: gpu_dyn.hpp:287
void std_assign_evaluate(Expr &&expr, Result &&result)
Evaluation of the expr into result.
Definition: evaluator.hpp:1176
typename V::template vec_type< T > vec_type
The vectorization type for V.
Definition: gpu_dyn.hpp:45
D D
The number of dimensions.
Definition: dyn_matrix_view.hpp:24
Define traits to get vectorization information for types when no vector mode is available.
Definition: no_vectorization.hpp:16
~gpu_dyn_matrix_impl() noexcept
Destruct the matrix and release all its memory.
Definition: gpu_dyn.hpp:193
static constexpr size_t n_dimensions
The number of dimensions.
Definition: gpu_dyn.hpp:26
order
Storage order of a matrix.
Definition: order.hpp:15
const value_type * const_memory_type
The const memory type.
Definition: gpu_dyn.hpp:36
constexpr size_t dimensions() noexcept
Return the number of dimensions of the given ETL type.
Definition: helpers.hpp:28
void resize_scalar()
Resize the matrix as a scalar value.
Definition: gpu_dyn.hpp:307
std::conditional_t< SO==order::RowMajor, const value_type *, etl::iterator< const this_type > > const_iterator
The const iterator type.
Definition: gpu_dyn.hpp:39
void assign_div_to(L &&lhs) const
Divide to the given left-hand-side expression.
Definition: gpu_dyn.hpp:260
gpu_dyn_matrix_impl() noexcept
Construct an empty matrix.
Definition: gpu_dyn.hpp:65
Traits to get information about ETL types.
Definition: tmp.hpp:68
Root namespace for the ETL library.
Definition: adapter.hpp:15
dense_dyn_base< this_type, T, SO, D > base_type
The base type.
Definition: gpu_dyn.hpp:31
std::array< size_t, n_dimensions > dimension_storage_impl
The type used to store the dimensions.
Definition: gpu_dyn.hpp:34
static constexpr size_t alignment
The memory alignment.
Definition: gpu_dyn.hpp:28
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
void assign_mod_to(L &&lhs) const
Modulo the given left-hand-side expression.
Definition: gpu_dyn.hpp:269
gpu_dyn_matrix_impl & operator=(const gpu_dyn_matrix_impl &rhs) noexcept(assert_nothrow)
Copy assign from another matrix.
Definition: gpu_dyn.hpp:96
Visitor to perform local evaluation when necessary.
Definition: eval_visitors.hpp:23
const auto & gpu_compute_hint([[maybe_unused]] Y &y) const
Return a GPU computed version of this expression.
Definition: gpu_dyn.hpp:212
std::conditional_t< SO==order::RowMajor, value_type *, etl::iterator< this_type > > iterator
The iterator type.
Definition: gpu_dyn.hpp:38
auto & gpu_compute_hint([[maybe_unused]] Y &y)
Return a GPU computed version of this expression.
Definition: gpu_dyn.hpp:202
void std_mod_evaluate(Expr &&expr, Result &&result)
Compound modulo evaluation of the expr into result.
Definition: evaluator.hpp:1271
gpu_dyn_matrix_impl & operator=(E &&e) noexcept requires(!std
Assign from an ETL expression.
Definition: gpu_dyn.hpp:146
void assign_sub_to(L &&lhs) const
Subtract from the given left-hand-side expression.
Definition: gpu_dyn.hpp:242
void std_mul_evaluate(Expr &&expr, Result &&result)
Compound multiply evaluation of the expr into result.
Definition: evaluator.hpp:1233
Base class and utilities for dyn matrix implementations.
gpu_dyn_matrix_impl & operator=([[maybe_unused]] value_type v) noexcept
Assign a value to all elements of the matrix.
Definition: gpu_dyn.hpp:184
requires(D > 0) struct dyn_base
Matrix with run-time fixed dimensions.
Definition: dyn_base.hpp:113
bool is_gpu_up_to_date() const noexcept
Indicates if the GPU memory is up to date.
Definition: sub_view.hpp:785
void ensure_gpu_up_to_date() const
Copy back from the GPU to the expression memory if necessary.
Definition: dyn_matrix_view.hpp:280
void assign_mul_to(L &&lhs) const
Multiply the given left-hand-side expression.
Definition: gpu_dyn.hpp:251
void std_sub_evaluate(Expr &&expr, Result &&result)
Compound subtract evaluation of the expr into result.
Definition: evaluator.hpp:1214
static constexpr order storage_order
The storage order.
Definition: gpu_dyn.hpp:27
gpu_dyn_matrix_impl(gpu_dyn_matrix_impl &&rhs) noexcept
Move construct a matrix.
Definition: gpu_dyn.hpp:83
void assign_add_to(L &&lhs) const
Add to the given left-hand-side expression.
Definition: gpu_dyn.hpp:233
T value_type
The value type.
Definition: gpu_dyn.hpp:33
typename decay_traits< E >::value_type value_t
Traits to extract the value type out of an ETL type.
Definition: tmp.hpp:81
GPU special Matrix with run-time fixed dimensions.
Definition: gpu_dyn.hpp:25
void std_div_evaluate(Expr &&expr, Result &&result)
Compound divide evaluation of the expr into result.
Definition: evaluator.hpp:1252
friend std::ostream & operator<<(std::ostream &os, const gpu_dyn_matrix_impl &mat)
Print the description of the matrix to the given stream.
Definition: gpu_dyn.hpp:318
void std_add_evaluate(Expr &&expr, Result &&result)
Compound add evaluation of the expr into result.
Definition: evaluator.hpp:1195
value_type *ETL_RESTRICT _memory
Pointer to the allocated memory.
Definition: dyn_base.hpp:312
CRTP class to inject functions testing the dimensions.
Definition: dim_testable.hpp:45
gpu_memory_handler< T > _gpu
The GPU memory handler.
Definition: dyn_base.hpp:313
void assign_to(L &&lhs) const
Assign to the given left-hand-side expression.
Definition: gpu_dyn.hpp:224