Flow123d  DF_patch_fe_data_tables-47aef41
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 template <class Resource> class ArenaResource; // forward declaration
17 
18 
19 // Helper class of ArenaResource, allows allocate aligned blocks of data
20 template <class Upstream>
21 class AlignedMemoryResource : public std::pmr::memory_resource {
22 public:
23  explicit AlignedMemoryResource(std::pmr::monotonic_buffer_resource& upstream, size_t alignment)
24  : upstream_(upstream), alignment_(alignment) {}
25 
26 protected:
27  void* do_allocate(size_t bytes, size_t alignment) override {
28  if (alignment_ > alignment) {
29  alignment = alignment_;
30  }
31  void* p = upstream_.allocate(bytes, alignment);
32  if (p == nullptr) { // test only in Debug when null_pointer_resource is in use
33  throw std::bad_alloc();
34  }
35  return p;
36  }
37 
38  void do_deallocate(void* p, size_t bytes, size_t alignment) override {
39  upstream_.deallocate(p, bytes, alignment);
40  }
41 
42  bool do_is_equal(const std::pmr::memory_resource& other) const noexcept override {
43  return this == &other;
44  }
45 
46 private:
47  Upstream& upstream_;
48  size_t alignment_;
49 
50  friend class ArenaResource<Upstream>;
51 };
52 
53 
54 // Final proposal of Arena
55 template <class Resource>
56 class ArenaResource : public std::pmr::memory_resource {
57 public:
58  explicit ArenaResource(size_t buffer_size, size_t simd_alignment)
59  : buffer(new char[buffer_size]),
61 #ifdef FLOW123D_DEBUG
62  resource_(buffer.get(), buffer_size, std::pmr::null_memory_resource()),
63 #else
64  resource_(buffer.get(), buffer_size, std::pmr::get_default_resource()),
65 #endif
66  simd_alignment_(simd_alignment)
67  {}
68 
69 
70  ~ArenaResource() = default;
71 
72  /// Getter for resource
73  Resource &resource() {
74  return resource_;
75  }
76 
77  /// Allocate and return data pointer of n_item array of type T (alignment to length 8 bytes)
78  template <class T>
79  T* allocate_8(size_t n_items) {
80  size_t bytes = sizeof(T) * n_items;
82  return (T*)a_res.do_allocate(bytes, a_res.alignment_);
83  }
84 
85  /// Allocate and return data pointer of n_item array of type T (alignment to length given by simd_alignment constructor argument)
86  template <class T>
87  T* allocate_simd(size_t n_items) {
88  size_t bytes = sizeof(T) * n_items;
90  return (T*)a_res.do_allocate(bytes, a_res.alignment_);
91  }
92 
93  // Reset allocated data
94  void reset() {
95  resource_.release();
96  }
97 
98 protected:
99  /// Override do_allocate to handle allocation logic
100  void* do_allocate(FMT_UNUSED size_t bytes, FMT_UNUSED size_t alignment) override {
101  // No-op
102  return nullptr;
103  }
104 
105  /// Override do_deallocate (no-op for monotonic buffer)
106  void do_deallocate(FMT_UNUSED void* p, FMT_UNUSED size_t bytes, FMT_UNUSED size_t alignment) override {
107  // No-op
108  }
109 
110  /// Override do_is_equal for memory resource comparison
111  bool do_is_equal(const std::pmr::memory_resource& other) const noexcept override {
112  return this == &other;
113  }
114 
115 private:
116  std::unique_ptr<char[]> buffer;
117  size_t buffer_size;
118  Resource resource_;
120 };
121 
122 
125 
126 
127 /**
128  * Define vector allocated in Arena and aligned to SIMD size.
129  */
130 template<class T>
131 class ArenaVec {
132 public:
133  /// Type definition
134  typedef Eigen::Matrix<T, Eigen::Dynamic, 1> VecData;
135 
136  /// Default constructor, set invalid data pointer
138  : data_ptr_(nullptr), data_size_(0), arena_(nullptr) {}
139 
140  /**
141  * Constructor. Set sizes and allocate data pointer
142  */
144  : data_ptr_(nullptr), data_size_(data_size), arena_(&arena) {
146  }
147 
148  /**
149  * Maps data pointer to Eigen Map of dimensions given data_size_ and returns it.
150  */
151  inline Eigen::Map<VecData> eigen_map() {
152  return Eigen::Map<VecData>(data_ptr_, data_size_, 1);
153  }
154 
155  /// Return data pointer (development method)
156  T* data_ptr() {
157  return data_ptr_;
158  }
159 
160  /// Getter for data_size_
161  inline size_t data_size() const {
162  return data_size_;
163  }
164 
165  inline T & operator()(std::size_t item) {
166  ASSERT_LT(item, data_size_);
167  return data_ptr_[item];
168  }
169 
170  inline ArenaVec<T> operator+(const ArenaVec<T> &other) const {
171  ASSERT_EQ(data_size_, other.data_size());
173  Eigen::Map<VecData> result_map = res.eigen_map();
174  result_map = this->eigen_map() + other.eigen_map();
175  return res;
176  }
177 
178  inline ArenaVec<T> operator*(T multi) const {
180  Eigen::Map<VecData> result_map = res.eigen_map();
181  result_map = this->eigen_map() * multi;
182  return res;
183  }
184 
185 protected:
186  T* data_ptr_; ///< Pointer to data array
187  size_t data_size_; ///< Length of data array
188  AssemblyArena *arena_; ///< Pointer to Arena
189 };
190 
191 
192 
193 /// Outer product - only proposal of multi operator
194 //template<class T>
195 //class ArenaOVec {
196 //public:
197 // inline ArenaOVec<T> operator*(const ArenaOVec<T> &other) const {
198 // typedef Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> MatData;
199 //
200 // ArenaOVec<T> res(data_size_*other.data_size(), *arena_);
201 // Eigen::Map<MatData> result_map = Eigen::Map<MatData>(res.data_ptr(), data_size_, other.data_size());
202 // result_map = this->eigen_map() * other.eigen_map().transpose();
203 // return res;
204 // }
205 //};
206 
207 
208 
209 
210 #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_EQ(a, b)
Definition of comparative assert macro (EQual) only for debug mode.
Definition: asserts.hh:333
void * do_allocate(size_t bytes, size_t alignment) override
AlignedMemoryResource(std::pmr::monotonic_buffer_resource &upstream, size_t alignment)
bool do_is_equal(const std::pmr::memory_resource &other) const noexcept override
void do_deallocate(void *p, size_t bytes, size_t alignment) override
Resource resource_
std::unique_ptr< char[]> buffer
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)
~ArenaResource()=default
void * do_allocate(FMT_UNUSED size_t bytes, FMT_UNUSED size_t alignment) override
Override do_allocate to handle allocation logic.
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.
ArenaVec()
Default constructor, set invalid data pointer.
Eigen::Matrix< T, Eigen::Dynamic, 1 > VecData
Type definition.
ArenaVec(size_t data_size, AssemblyArena &arena)
T * data_ptr()
Return data pointer (development method)
ArenaVec< T > operator*(T multi) const
Eigen::Map< VecData > eigen_map()
size_t data_size_
Length of data array.
AssemblyArena * arena_
Pointer to Arena.
T & operator()(std::size_t item)
ArenaVec< T > operator+(const ArenaVec< T > &other) const
size_t data_size() const
Getter for data_size_.
T * data_ptr_
Pointer to data array.
#define FMT_UNUSED
Definition: posix.h:75