Flow123d  DF_patch_fe_data_tables-5938e3d
arena_resource.hh
Go to the documentation of this file.
1 #ifndef ARENA_RESOURCE_HH_
2 #define ARENA_RESOURCE_HH_
3 
4 #include <memory_resource>
5 #include <vector>
6 #include <iostream>
7 #include <new>
8 #include <stdexcept> // !! Use Flow exception mechanism
9 
10 #include "system/asserts.hh"
11 
12 #include <Eigen/Core>
13 #include <Eigen/Dense>
14 
15 
16 // Final proposal of Arena
17 template <class Resource>
18 class ArenaResource : public std::pmr::memory_resource {
19 protected:
20  /// Returns different upstream resource in debug / release mode
21  static inline std::pmr::memory_resource* upstream_resource() {
22 #ifdef FLOW123D_DEBUG
23  return std::pmr::null_memory_resource();
24 #else
25  return std::pmr::get_default_resource();
26 #endif
27  }
28 
29 public:
30  ArenaResource(size_t buffer_size, size_t simd_alignment, std::pmr::memory_resource* upstream = ArenaResource<Resource>::upstream_resource())
31  : upstream_(upstream), // TODO needs use buffer and resource of upstream if default upstream is not used
32  buffer_( upstream_->allocate(buffer_size, simd_alignment) ),
33  buffer_size_(buffer_size),
34  used_size_(0),
35  resource_(buffer_, buffer_size, upstream_),
36  simd_alignment_(simd_alignment)
37  {
38  ASSERT_PERMANENT_EQ( (buffer_size%simd_alignment), 0 );
39  }
40 
41 
42  ~ArenaResource() = default;
43 
44  /// Getter for resource
45  Resource &resource() {
46  return resource_;
47  }
48 
49  /// Allocate and return data pointer of n_item array of type T (alignment to length 8 bytes)
50  template <class T>
51  T* allocate_8(size_t n_items) {
52  size_t bytes = sizeof(T) * n_items;
53  return (T*)this->do_allocate(bytes, 8);
54  }
55 
56  /// Allocate and return data pointer of n_item array of type T (alignment to length given by simd_alignment constructor argument)
57  template <class T>
58  T* allocate_simd(size_t n_items) {
59  size_t bytes = sizeof(T) * n_items;
60  return (T*)this->do_allocate(bytes, simd_alignment_);
61  }
62 
63  // Reset allocated data
64  void reset() {
65  resource_.release();
66  used_size_ = 0;
67  }
68 
69  inline size_t free_space() const {
71  }
72 
73 protected:
74  /// Override do_allocate to handle allocation logic
75  void* do_allocate(size_t bytes, size_t alignment) override {
76  void* p = resource_.allocate(bytes, alignment);
77  used_size_ += bytes;
78  if (p == nullptr) { // test only in Debug when null_pointer_resource is in use
79  throw std::bad_alloc();
80  }
81  return p;
82  }
83 
84  /// Override do_deallocate (no-op for monotonic buffer)
85  void do_deallocate(FMT_UNUSED void* p, FMT_UNUSED size_t bytes, FMT_UNUSED size_t alignment) override {
86  // No-op
87  }
88 
89  /// Override do_is_equal for memory resource comparison
90  bool do_is_equal(const std::pmr::memory_resource& other) const noexcept override {
91  return this == &other;
92  }
93 
94 private:
95  std::pmr::memory_resource* upstream_;
96  void* buffer_;
97  size_t buffer_size_;
98  size_t used_size_;
99  Resource resource_;
101 };
102 
103 
106 
107 
108 template<class T> class ArenaOVec;
109 
110 
111 /**
112  * Define vector allocated in Arena and aligned to SIMD size.
113  */
114 template<class T>
115 class ArenaVec {
116 public:
117  /// Type definition
118  typedef Eigen::Matrix<T, Eigen::Dynamic, 1> VecData;
119  typedef Eigen::Array<T, Eigen::Dynamic, 1> ArrayData;
120 
121  /// Default constructor, set invalid data pointer
123  : data_ptr_(nullptr), data_size_(0), arena_(nullptr) {}
124 
125  /**
126  * Constructor. Set scalar value
127  */
128  ArenaVec(T scalar_val)
129  : data_ptr_(nullptr), data_size_(0), arena_(nullptr), scalar_val_(scalar_val) {}
130 
131  /**
132  * Constructor. Set sizes and allocate data pointer
133  */
135  : data_ptr_(nullptr), data_size_(data_size), arena_(&arena) {
137  }
138 
139  /// Copy constructor
140  ArenaVec(const ArenaVec<T> &other)
141  : data_ptr_(other.data_ptr_), data_size_(other.data_size_),
142  arena_(other.arena_), scalar_val_(other.scalar_val_)
143  {}
144 
145  /**
146  * Maps data pointer to Eigen Map of dimensions given data_size_ and returns it.
147  */
148  inline Eigen::Map<VecData> eigen_map() {
150  return Eigen::Map<VecData>(data_ptr_, data_size_, 1);
151  }
152 
153  /// Smae as previous but with const modifier
154  inline const Eigen::Map<VecData> eigen_map() const {
156  return Eigen::Map<VecData>(data_ptr_, data_size_, 1);
157  }
158 
159  /**
160  * Maps data pointer to Eigen Map of dimensions given data_size_ and returns it.
161  */
162  inline Eigen::Map<ArrayData> array_map() {
164  return Eigen::Map<ArrayData>(data_ptr_, data_size_, 1);
165  }
166 
167  /// Smae as previous but with const modifier
168  inline const Eigen::Map<ArrayData> array_map() const {
170  return Eigen::Map<ArrayData>(data_ptr_, data_size_, 1);
171  }
172 
173  /// Return data pointer (development method)
174  T* data_ptr() {
175  return data_ptr_;
176  }
177 
178  /// Smae as previous but return const pointer
179  const T* data_ptr() const {
180  return data_ptr_;
181  }
182 
183  /// Getter for data_size_
184  inline size_t data_size() const {
185  return data_size_;
186  }
187 
188  inline ArenaVec<T> sqrt() const {
191  Eigen::Map<ArrayData> result_map = res.array_map();
192  result_map = this->array_map().sqrt();
193  return res;
194  }
195 
196  inline ArenaVec<T> inverse() const {
199  Eigen::Map<ArrayData> result_map = res.array_map();
200  result_map = this->array_map().inverse();
201  return res;
202  }
203 
204  inline ArenaVec<T> abs() const {
207  Eigen::Map<ArrayData> result_map = res.array_map();
208  result_map = this->array_map().abs();
209  return res;
210  }
211 
212  /// For development only. TODO remove
213  inline T & operator()(std::size_t item) {
215  ASSERT_LT(item, data_size_);
216  return data_ptr_[item];
217  }
218 
219  /// For development only. TODO remove
220  inline const T & operator()(std::size_t item) const {
221  ASSERT_LT(item, data_size_);
222  return data_ptr_[item];
223  }
224 
225  inline ArenaVec<T> operator+(const ArenaVec<T> &other) const {
227  ASSERT_PTR(other.data_ptr());
228  ASSERT_EQ(data_size_, other.data_size());
230  Eigen::Map<VecData> result_map = res.eigen_map();
231  result_map = this->eigen_map() + other.eigen_map();
232  return res;
233  }
234 
235  inline ArenaVec<T> operator-(const ArenaVec<T> &other) const {
237  ASSERT_PTR(other.data_ptr());
238  ASSERT_EQ(data_size_, other.data_size());
240  Eigen::Map<ArrayData> result_map = res.array_map();
241  result_map = this->array_map() - other.array_map();
242  return res;
243  }
244 
245  inline ArenaVec<T> operator*(T multi) const {
248  Eigen::Map<ArrayData> result_map = res.array_map();
249  result_map = this->array_map() * multi;
250  return res;
251  }
252 
253  inline ArenaVec<T> operator*(const ArenaVec<T> &other) const {
255  ASSERT_PTR(other.data_ptr());
256  ASSERT_EQ(data_size_, other.data_size());
258  Eigen::Map<ArrayData> result_map = res.array_map();
259  result_map = this->array_map() * other.array_map();
260  return res;
261  }
262 
263  inline ArenaVec<T> operator/(T div_by) const {
266  Eigen::Map<ArrayData> result_map = res.array_map();
267  result_map = this->array_map() / div_by;
268  return res;
269  }
270 
271  inline ArenaVec<T> operator/(const ArenaVec<T> &other) const {
273  ASSERT_PTR(other.data_ptr());
274  ASSERT_EQ(data_size_, other.data_size());
276  Eigen::Map<ArrayData> result_map = res.array_map();
277  result_map = this->array_map() / other.array_map();
278  return res;
279  }
280 
281 protected:
282  /// Constructor. Allows create ArenaVec from ArenaOVec
284  : data_ptr_(data_ptr), data_size_(data_size), arena_(&arena) {}
285 
286  T* data_ptr_; ///< Pointer to data array
287  size_t data_size_; ///< Length of data array
288  AssemblyArena *arena_; ///< Pointer to Arena
289  T scalar_val_; ///< Scalar value of T type
290 
291  friend class ArenaOVec<T>;
292 };
293 
294 
295 
296 /// Outer product - only proposal of multi operator
297 template<class T>
298 class ArenaOVec : public ArenaVec<T> {
299 public:
301  : vec_(vec) {
302  ASSERT_PTR(vec.data_ptr());
303  this->data_ptr_ = vec_.data_ptr();
304  this->data_size_ = vec_.data_size();
305  this->arena_ = vec_.arena_;
306  }
307 
309  return ArenaVec<T>(*this);
310  }
311 
312  inline ArenaOVec<T> operator+(const ArenaOVec<T> &other) const {
313  // Test of valid data_ptr is in constructor
314  ASSERT_EQ(this->data_size_, other.data_size());
315  ArenaVec<T> res_vec(this->data_size_, *this->arena_);
316  ArenaOVec<T> res(res_vec);
317  Eigen::Map<typename ArenaVec<T>::VecData> result_map = res.eigen_map();
318  result_map = this->eigen_map() + other.eigen_map();
319  return res;
320  }
321 
322 
323  //v obou testovat operatorech (v DEBUG), že oba operandy mají ArenaVec již alokovaný.
324 
325  inline ArenaOVec<T> operator*(const ArenaOVec<T> &other) const {
326  typedef Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> MatData;
327 
328  ArenaVec<T> res_vec(this->data_size_*other.data_size(), *this->arena_);
329  ArenaOVec<T> res(res_vec);
330  Eigen::Map<MatData> result_map = Eigen::Map<MatData>(res.data_ptr(), this->data_size_, other.data_size());
331  result_map = this->eigen_map() * other.eigen_map().transpose();
332  return res;
333  }
334 protected:
335  ArenaVec<T> &vec_; ///< Reference to ArenaVec
336 };
337 
338 
339 
340 
341 #endif /* ARENA_RESOURCE_HH_ */
Definitions of ASSERTS.
#define ASSERT_LT(a, b)
Definition of comparative assert macro (Less Than) only for debug mode.
Definition: asserts.hh:301
#define ASSERT_PERMANENT_EQ(a, b)
Definition of comparative assert macro (EQual)
Definition: asserts.hh:329
#define ASSERT_EQ(a, b)
Definition of comparative assert macro (EQual) only for debug mode.
Definition: asserts.hh:333
#define ASSERT_PTR(ptr)
Definition of assert macro checking non-null pointer (PTR) only for debug mode.
Definition: asserts.hh:341
Outer product - only proposal of multi operator.
ArenaOVec< T > operator+(const ArenaOVec< T > &other) const
ArenaVec< T > get_vec()
ArenaOVec(ArenaVec< T > &vec)
ArenaOVec< T > operator*(const ArenaOVec< T > &other) const
ArenaVec< T > & vec_
Reference to ArenaVec.
Resource resource_
std::pmr::memory_resource * upstream_
T * allocate_8(size_t n_items)
Allocate and return data pointer of n_item array of type T (alignment to length 8 bytes)
ArenaResource(size_t buffer_size, size_t simd_alignment, std::pmr::memory_resource *upstream=ArenaResource< Resource >::upstream_resource())
~ArenaResource()=default
void * do_allocate(size_t bytes, size_t alignment) override
Override do_allocate to handle allocation logic.
static std::pmr::memory_resource * upstream_resource()
Returns different upstream resource in debug / release mode.
T * allocate_simd(size_t n_items)
Allocate and return data pointer of n_item array of type T (alignment to length given by simd_alignme...
void do_deallocate(FMT_UNUSED void *p, FMT_UNUSED size_t bytes, FMT_UNUSED size_t alignment) override
Override do_deallocate (no-op for monotonic buffer)
bool do_is_equal(const std::pmr::memory_resource &other) const noexcept override
Override do_is_equal for memory resource comparison.
size_t simd_alignment_
Resource & resource()
Getter for resource.
size_t free_space() const
ArenaVec(T scalar_val)
Eigen::Array< T, Eigen::Dynamic, 1 > ArrayData
ArenaVec()
Default constructor, set invalid data pointer.
Eigen::Matrix< T, Eigen::Dynamic, 1 > VecData
Type definition.
ArenaVec< T > operator/(const ArenaVec< T > &other) const
ArenaVec(size_t data_size, AssemblyArena &arena)
const T * data_ptr() const
Smae as previous but return const pointer.
T * data_ptr()
Return data pointer (development method)
const T & operator()(std::size_t item) const
For development only. TODO remove.
const Eigen::Map< ArrayData > array_map() const
Smae as previous but with const modifier.
ArenaVec< T > sqrt() const
ArenaVec< T > operator*(T multi) const
ArenaVec< T > operator*(const ArenaVec< T > &other) const
Eigen::Map< VecData > eigen_map()
ArenaVec< T > abs() const
Eigen::Map< ArrayData > array_map()
size_t data_size_
Length of data array.
AssemblyArena * arena_
Pointer to Arena.
const Eigen::Map< VecData > eigen_map() const
Smae as previous but with const modifier.
ArenaVec< T > operator/(T div_by) const
ArenaVec< T > inverse() const
ArenaVec(T *data_ptr, size_t data_size, AssemblyArena &arena)
Constructor. Allows create ArenaVec from ArenaOVec.
ArenaVec< T > operator-(const ArenaVec< T > &other) const
T & operator()(std::size_t item)
For development only. TODO remove.
ArenaVec< T > operator+(const ArenaVec< T > &other) const
ArenaVec(const ArenaVec< T > &other)
Copy constructor.
size_t data_size() const
Getter for data_size_.
T scalar_val_
Scalar value of T type.
T * data_ptr_
Pointer to data array.
ArmaVec< double, N > vec
Definition: armor.hh:933
#define FMT_UNUSED
Definition: posix.h:75