Project
Loading...
Searching...
No Matches
BoundedAllocator.h
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
19
20#ifndef ALICEO2_GENERICTRACKING_BOUNDEDALLOCATOR_H_
21#define ALICEO2_GENERICTRACKING_BOUNDEDALLOCATOR_H_
22
23#include <algorithm>
24#include <array>
25#include <atomic>
26#include <limits>
27#include <memory>
28#include <memory_resource>
29#include <new>
30#include <string>
31#include <utility>
32#include <vector>
33
34namespace o2::gtrk
35{
36
37// #define BOUNDED_MR_STATS
39{
40 public:
41 class MemoryLimitExceeded final : public std::bad_alloc
42 {
43 public:
44 MemoryLimitExceeded(size_t attempted, size_t used, size_t max);
45 const char* what() const noexcept final;
46
47 private:
48 std::string mMsg;
49 };
50
52
53 BoundedMemoryResource(size_t maxBytes = std::numeric_limits<size_t>::max(),
54 std::pmr::memory_resource* upstream = nullptr);
55
56 BoundedMemoryResource(std::unique_ptr<std::pmr::memory_resource> upstream,
57 size_t maxBytes = std::numeric_limits<size_t>::max());
58
59 [[nodiscard]] size_t getUsedMemory() const noexcept;
60 [[nodiscard]] size_t getMaxMemory() const noexcept;
61 [[nodiscard]] size_t getThrowCount() const noexcept;
62 [[nodiscard]] size_t getPeakMemory() const noexcept;
63 [[nodiscard]] size_t getPeakMemoryDelta() const noexcept;
64
65 // Reset the stage peak/baseline, returning the previous peak for nested profiling.
66 size_t resetPeakMemory() noexcept;
67 void raisePeakMemory(size_t peak) noexcept;
68 [[nodiscard]] size_t getAllocationCount() const noexcept { return mAllocations.load(std::memory_order_relaxed); }
69 [[nodiscard]] size_t getAllocatedBytes() const noexcept { return mAllocatedBytes.load(std::memory_order_relaxed); }
70 void setMaxMemory(size_t max);
71
72#if !defined(__HIPCC__) && !defined(__CUDACC__)
73 std::string asString() const;
74 void print() const;
75#endif
76
77 private:
78 void* do_allocate(size_t bytes, size_t alignment) final;
79 void do_deallocate(void* p, size_t bytes, size_t alignment) final;
80 bool do_is_equal(const std::pmr::memory_resource& other) const noexcept final;
81
82 std::atomic<size_t> mMaxMemory{std::numeric_limits<size_t>::max()};
83 std::atomic<size_t> mCountThrow{0};
84 std::atomic<size_t> mUsedMemory{0};
85 std::atomic<size_t> mAllocations{0};
86 std::atomic<size_t> mAllocatedBytes{0};
87 std::atomic<size_t> mPeakUsedMemory{0};
88 std::atomic<size_t> mPeakBaselineMemory{0};
89 std::unique_ptr<std::pmr::memory_resource> mOwnedUpstream;
90 std::pmr::memory_resource* mUpstream{nullptr};
91
92#ifdef BOUNDED_MR_STATS
93 struct Stats {
94 std::atomic<size_t> peak{0};
95 std::atomic<size_t> live{0};
96 std::atomic<size_t> nAlloc{0};
97 std::atomic<size_t> nFree{0};
98 std::atomic<size_t> totalAlloc{0};
99 std::atomic<size_t> totalFreed{0};
100 std::atomic<size_t> maxAlign{0};
101 std::atomic<size_t> upstreamFailures{0};
102 };
103 Stats mStats{};
104#endif
105};
106
107template <typename T>
108using BoundedVector = std::pmr::vector<T>;
109
110template <typename T>
112
113template <typename T>
114inline void deepVectorClear(std::vector<T>& vec)
115{
116 std::vector<T>().swap(vec);
117}
118
119template <typename T>
121{
122 std::pmr::memory_resource* tmr = (mr != nullptr) ? mr : vec.get_allocator().resource();
123 std::destroy_at(&vec);
124 new (&vec) bounded_vector<T>(std::pmr::polymorphic_allocator<T>{tmr});
125}
126
127template <typename T>
128inline void deepVectorClear(std::vector<bounded_vector<T>>& vec, std::pmr::memory_resource* mr = nullptr)
129{
130 for (auto& v : vec) {
131 deepVectorClear(v, mr);
132 }
133}
134
135template <typename T, size_t S>
136inline void deepVectorClear(std::array<bounded_vector<T>, S>& arr, std::pmr::memory_resource* mr = nullptr)
137{
138 for (size_t i{0}; i < S; ++i) {
139 deepVectorClear(arr[i], mr);
140 }
141}
142
143template <typename T>
144inline void clearResizeBoundedVector(bounded_vector<T>& vec, size_t sz, std::pmr::memory_resource* mr = nullptr, T def = T())
145{
146 // Rebuild a valid empty vector before allocation or element construction can
147 // throw. The old allocation is released first, as required by bounded pools.
148 deepVectorClear(vec, mr);
149 vec.assign(sz, def);
150}
151
152// GTRK's capacity-reusing resize: retained storage is intended for arrays
153// rewritten by the caller. A non-null different resource requires a rebuild.
154template <typename T>
156{
157 if (sz > vec.capacity() || (mr != nullptr && mr != vec.get_allocator().resource())) {
159 return;
160 }
161 vec.resize(sz);
162}
163
164// Release several bounded vectors onto one resource.
165template <typename... T>
167{
168 (deepVectorClear(vecs, mr), ...);
169}
170
171template <typename T>
173{
174 vec.clear();
175 vec.reserve(size);
176 for (size_t i = 0; i < size; ++i) {
177 vec.emplace_back(std::pmr::polymorphic_allocator<bounded_vector<T>>{mr});
178 }
179}
180
181template <typename T, size_t S>
182inline void clearResizeBoundedArray(std::array<bounded_vector<T>, S>& arr, size_t size, std::pmr::memory_resource* mr = nullptr, T def = T())
183{
184 for (size_t i{0}; i < S; ++i) {
185 clearResizeBoundedVector(arr[i], size, mr, def);
186 }
187}
188
189template <typename T>
190inline std::vector<T> toSTDVector(const bounded_vector<T>& b)
191{
192 std::vector<T> t(b.size());
193 std::copy(b.cbegin(), b.cend(), t.begin());
194 return t;
195}
196
197} // namespace o2::gtrk
198
199#endif /* ALICEO2_GENERICTRACKING_BOUNDEDALLOCATOR_H_ */
int32_t i
size_t bytes
static std::pmr::memory_resource * cachingUpstream()
size_t getAllocationCount() const noexcept
size_t getAllocatedBytes() const noexcept
size_t getThrowCount() const noexcept
size_t getMaxMemory() const noexcept
void raisePeakMemory(size_t peak) noexcept
size_t getUsedMemory() const noexcept
size_t getPeakMemoryDelta() const noexcept
size_t getPeakMemory() const noexcept
GLsizeiptr size
Definition glcorearb.h:659
const GLdouble * v
Definition glcorearb.h:832
GLboolean GLboolean GLboolean b
Definition glcorearb.h:1233
void clearResizeBoundedVector(bounded_vector< T > &vec, size_t sz, std::pmr::memory_resource *mr=nullptr, T def=T())
void resizeBoundedVector(BoundedVector< T > &vec, size_t sz, std::pmr::memory_resource *mr=nullptr)
void deepVectorClear(std::vector< T > &vec)
std::vector< T > toSTDVector(const bounded_vector< T > &b)
void clearResizeBoundedArray(std::array< bounded_vector< T >, S > &arr, size_t size, std::pmr::memory_resource *mr=nullptr, T def=T())
BoundedVector< T > bounded_vector
std::pmr::vector< T > BoundedVector
constexpr size_t max
VectorOfTObjectPtrs other
std::vector< o2::ctf::BufferType > vec