Flow123d  DF_patch_fe_data_tables-dc3adc1
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 /**
109  * Define vector allocated in Arena and aligned to SIMD size.
110  */
111 template<class T>
112 class ArenaVec {
113 public:
114  /// Type definition
115  typedef Eigen::Matrix<T, Eigen::Dynamic, 1> VecData;
116  typedef Eigen::Array<T, Eigen::Dynamic, 1> ArrayData;
117 
118  /// Default constructor, set invalid data pointer
120  : data_ptr_(nullptr), data_size_(0), arena_(nullptr) {}
121 
122  /**
123  * Constructor. Set scalar value
124  */
125  ArenaVec(T scalar_val)
126  : data_ptr_(nullptr), data_size_(0), arena_(nullptr), scalar_val_(scalar_val) {}
127 
128  /**
129  * Constructor. Set sizes and allocate data pointer
130  */
132  : data_ptr_(nullptr), data_size_(data_size), arena_(&arena) {
134  }
135 
136  /// Copy constructor
137  ArenaVec(const ArenaVec<T> &other)
138  : data_ptr_(other.data_ptr_), data_size_(other.data_size_),
139  arena_(other.arena_), scalar_val_(other.scalar_val_)
140  {}
141 
142  /**
143  * Maps data pointer to Eigen Map of dimensions given data_size_ and returns it.
144  */
145  inline Eigen::Map<VecData> eigen_map() {
147  return Eigen::Map<VecData>(data_ptr_, data_size_, 1);
148  }
149 
150  /// Smae as previous but with const modifier
151  inline const Eigen::Map<VecData> eigen_map() const {
153  return Eigen::Map<VecData>(data_ptr_, data_size_, 1);
154  }
155 
156  /**
157  * Maps data pointer to Eigen Map of dimensions given data_size_ and returns it.
158  */
159  inline Eigen::Map<ArrayData> array_map() {
161  return Eigen::Map<ArrayData>(data_ptr_, data_size_, 1);
162  }
163 
164  /// Smae as previous but with const modifier
165  inline const Eigen::Map<ArrayData> array_map() const {
167  return Eigen::Map<ArrayData>(data_ptr_, data_size_, 1);
168  }
169 
170  /// Return data pointer (development method)
171  T* data_ptr() {
172  return data_ptr_;
173  }
174 
175  /// Smae as previous but return const pointer
176  const T* data_ptr() const {
177  return data_ptr_;
178  }
179 
180  /// Getter for data_size_
181  inline size_t data_size() const {
182  return data_size_;
183  }
184 
185  inline ArenaVec<T> sqrt() const {
188  Eigen::Map<ArrayData> result_map = res.array_map();
189  result_map = this->array_map().sqrt();
190  return res;
191  }
192 
193  inline ArenaVec<T> inverse() const {
196  Eigen::Map<ArrayData> result_map = res.array_map();
197  result_map = this->array_map().inverse();
198  return res;
199  }
200 
201  inline ArenaVec<T> abs() const {
204  Eigen::Map<ArrayData> result_map = res.array_map();
205  result_map = this->array_map().abs();
206  return res;
207  }
208 
209  /// For development only. TODO remove
210  inline T & operator()(std::size_t item) {
212  ASSERT_LT(item, data_size_);
213  return data_ptr_[item];
214  }
215 
216  /// For development only. TODO remove
217  inline const T & operator()(std::size_t item) const {
218  ASSERT_LT(item, data_size_);
219  return data_ptr_[item];
220  }
221 
222  inline ArenaVec<T> operator+(const ArenaVec<T> &other) const {
224  ASSERT_PTR(other.data_ptr());
225  ASSERT_EQ(data_size_, other.data_size());
227  Eigen::Map<VecData> result_map = res.eigen_map();
228  result_map = this->eigen_map() + other.eigen_map();
229  return res;
230  }
231 
232  inline ArenaVec<T> operator-(const ArenaVec<T> &other) const {
234  ASSERT_PTR(other.data_ptr());
235  ASSERT_EQ(data_size_, other.data_size());
237  Eigen::Map<ArrayData> result_map = res.array_map();
238  result_map = this->array_map() - other.array_map();
239  return res;
240  }
241 
242  inline ArenaVec<T> operator*(T multi) const {
245  Eigen::Map<ArrayData> result_map = res.array_map();
246  result_map = this->array_map() * multi;
247  return res;
248  }
249 
250  inline ArenaVec<T> operator*(const ArenaVec<T> &other) const {
252  ASSERT_PTR(other.data_ptr());
253  ASSERT_EQ(data_size_, other.data_size());
255  Eigen::Map<ArrayData> result_map = res.array_map();
256  result_map = this->array_map() * other.array_map();
257  return res;
258  }
259 
260  inline ArenaVec<T> operator/(T div_by) const {
263  Eigen::Map<ArrayData> result_map = res.array_map();
264  result_map = this->array_map() / div_by;
265  return res;
266  }
267 
268  inline ArenaVec<T> operator/(const ArenaVec<T> &other) const {
270  ASSERT_PTR(other.data_ptr());
271  ASSERT_EQ(data_size_, other.data_size());
273  Eigen::Map<ArrayData> result_map = res.array_map();
274  result_map = this->array_map() / other.array_map();
275  return res;
276  }
277 
278 protected:
279  /// Constructor. Allows create ArenaVec from ArenaOVec
281  : data_ptr_(data_ptr), data_size_(data_size), arena_(&arena) {}
282 
283  T* data_ptr_; ///< Pointer to data array
284  size_t data_size_; ///< Length of data array
285  AssemblyArena *arena_; ///< Pointer to Arena
286  T scalar_val_; ///< Scalar value of T type
287 };
288 
289 
290 
291 /// Outer product - only proposal of multi operator
292 template<class T>
293 class ArenaOVec : public ArenaVec<T> {
294 public:
296  : vec_(vec) {
297  ASSERT_PTR(vec.data_ptr());
298  this->data_ptr_ = vec_.data_ptr();
299  this->data_size_ = vec_.data_size();
300  this->arena_ = vec_.arena_;
301  }
302 
304  return ArenaVec<T>(this->data_ptr_, this->data_size_, this->arena_);
305  }
306 
307  inline ArenaOVec<T> operator+(const ArenaOVec<T> &other) const {
308  // Test of valid data_ptr is in constructor
309  ASSERT_EQ(this->data_size_, other.data_size());
310  ArenaOVec<T> res(this->data_size_, *this->arena_);
311  Eigen::Map<typename ArenaVec<T>::VecData> result_map = res.eigen_map();
312  result_map = this->eigen_map() + other.eigen_map();
313  return res;
314  }
315 
316 
317  //v obou testovat operatorech (v DEBUG), že oba operandy mají ArenaVec již alokovaný.
318 
319  inline ArenaOVec<T> operator*(const ArenaOVec<T> &other) const {
320  typedef Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> MatData;
321 
322  ArenaOVec<T> res(this->data_size_*other.data_size(), *this->arena_);
323  Eigen::Map<MatData> result_map = Eigen::Map<MatData>(res.data_ptr(), this->data_size_, other.data_size());
324  result_map = this->eigen_map() * other.eigen_map().transpose();
325  return res;
326  }
327 protected:
328  ArenaVec<T> &vec_; ///< Reference to ArenaVec
329 };
330 
331 
332 
333 
334 #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