omega_h
Reliable mesh adaptation
Omega_h_shared_alloc.hpp
1 #ifndef OMEGA_H_SHARED_ALLOC_HPP
2 #define OMEGA_H_SHARED_ALLOC_HPP
3 
4 #include <Omega_h_macros.h>
5 #include <cstddef>
6 #include <string>
7 #include <vector>
8 
9 namespace Omega_h {
10 
11 class Library;
12 
13 struct Allocs;
14 
15 OMEGA_H_DLL extern bool entering_parallel;
16 extern Allocs* global_allocs;
17 
18 void start_tracking_allocations();
19 void stop_tracking_allocations(Library* lib);
20 
21 struct Alloc {
22  std::size_t size;
23  std::string name;
24  void* ptr;
25  int use_count;
26  Alloc* prev;
27  Alloc* next;
28  Alloc(std::size_t size_in, std::string const& name_in);
29  Alloc(std::size_t size_in, std::string&& name_in);
30  OMEGA_H_DLL ~Alloc();
31  Alloc(Alloc const&) = delete;
32  Alloc(Alloc&&) = delete;
33  Alloc& operator=(Alloc const&) = delete;
34  Alloc& operator=(Alloc&&) = delete;
35  void init();
36 };
37 
39  std::string name;
40  std::size_t bytes;
41 };
42 
43 struct Allocs {
44  Alloc* first;
45  Alloc* last;
46  std::size_t total_bytes;
47  std::size_t high_water_bytes;
48  std::vector<HighWaterRecord> high_water_records;
49 };
50 
51 struct SharedAlloc {
52  Alloc* alloc;
53  void* direct_ptr;
54  OMEGA_H_INLINE SharedAlloc() noexcept : alloc(nullptr), direct_ptr(nullptr) {}
55  SharedAlloc(std::size_t size_in, std::string const& name_in);
56  SharedAlloc(std::size_t size_in, std::string&& name_in);
57  SharedAlloc(std::size_t size_in);
58  enum : std::uintptr_t {
59  FREE_BIT1 = 0x1,
60  FREE_BIT2 = 0x2,
61  FREE_BIT3 = 0x4,
62  FREE_MASK = 0x7,
63  IN_PARALLEL = FREE_BIT1,
64  IS_IDENTITY = FREE_BIT2,
65  };
66  /* possible states:
67  1. uninitialized: alloc == nullptr
68  2. uninitialized, parallel: alloc = IN_PARALLEL
69  3. allocated: alloc == true_alloc
70  4. allocated, parallel: alloc == (size << 3) & IN_PARALLEL
71  5. identity: alloc = (size << 3) & IS_IDENTITY
72  6. identity, parallel: alloc = (size << 3) & IS_IDENTITY & IN_PARALLEL
73  */
74  OMEGA_H_INLINE void copy(SharedAlloc const& other) noexcept {
75  alloc = other.alloc;
76 #ifndef __CUDA_ARCH__
77  if (alloc && (!(reinterpret_cast<std::uintptr_t>(alloc) & FREE_MASK))) {
78  // allocated
79  if (entering_parallel) {
80  alloc = reinterpret_cast<Alloc*>(
81  (std::uintptr_t(alloc->size) << 3) | IN_PARALLEL);
82  } else {
83  ++(alloc->use_count);
84  }
85  }
86 #endif
87  direct_ptr = other.direct_ptr;
88  }
89  OMEGA_H_INLINE SharedAlloc(SharedAlloc const& other) { copy(other); }
90  OMEGA_H_INLINE void move(SharedAlloc&& other) noexcept {
91  alloc = other.alloc;
92  direct_ptr = other.direct_ptr;
93 #ifndef __CUDA_ARCH__
94  if (alloc && (!(reinterpret_cast<std::uintptr_t>(alloc) & FREE_MASK))) {
95  // allocated
96  if (entering_parallel) {
97  --(alloc->use_count);
98  alloc = reinterpret_cast<Alloc*>(
99  (std::uintptr_t(alloc->size) << 3) | IN_PARALLEL);
100  }
101  }
102 #endif
103  other.alloc = nullptr;
104  other.direct_ptr = nullptr;
105  }
106  OMEGA_H_INLINE SharedAlloc(SharedAlloc&& other) { move(std::move(other)); }
107  OMEGA_H_INLINE SharedAlloc& operator=(SharedAlloc const& other) {
108  clear();
109  copy(other);
110  return *this;
111  }
112  OMEGA_H_INLINE SharedAlloc& operator=(SharedAlloc&& other) {
113  clear();
114  move(std::move(other));
115  return *this;
116  }
117 
118 #ifdef OMPTARGET
119 #pragma omp declare target
120 #endif
121  OMEGA_H_INLINE ~SharedAlloc() { clear(); }
122 #ifdef OMPTARGET
123 #pragma omp end declare target
124 #endif
125  OMEGA_H_INLINE void clear() {
126 #ifndef __CUDA_ARCH__
127  if (alloc && (!(reinterpret_cast<std::uintptr_t>(alloc) & FREE_MASK))) {
128  // allocated
129  --(alloc->use_count);
130  if (alloc->use_count == 0) delete alloc;
131  }
132 #endif
133  }
134  OMEGA_H_INLINE std::size_t size() const noexcept {
135 #ifndef __CUDA_ARCH__
136  if (!(reinterpret_cast<std::uintptr_t>(alloc) & IN_PARALLEL)) {
137 #if defined(__GNUC__) && (__GNUC__ >= 7) && (!defined(__clang__))
138 #pragma GCC diagnostic push
139 #pragma GCC diagnostic ignored "-Wnull-dereference"
140 #endif
141  return alloc->size;
142 #if defined(__GNUC__) && (__GNUC__ >= 7) && (!defined(__clang__))
143 #pragma GCC diagnostic pop
144 #endif
145  }
146 #endif
147  return reinterpret_cast<std::uintptr_t>(alloc) >> 3;
148  }
149  OMEGA_H_INLINE int maybe_identity_index(int i) const noexcept {
150  if (reinterpret_cast<std::uintptr_t>(alloc) == IS_IDENTITY) {
151  return i;
152  }
153  return static_cast<int*>(direct_ptr)[i];
154  }
155  OMEGA_H_INLINE void* data() const noexcept { return direct_ptr; }
156  static SharedAlloc identity(std::size_t size_in);
157 };
158 
159 } // namespace Omega_h
160 
161 #endif
Definition: amr_mpi_test.cpp:6
Definition: Omega_h_shared_alloc.hpp:21
Definition: Omega_h_shared_alloc.hpp:43
Definition: Omega_h_shared_alloc.hpp:38
Definition: Omega_h_shared_alloc.hpp:51
Definition: Omega_h_scalar.hpp:327