Skip to content

Commit 24d008e

Browse files
committed
ITSMFT: share tracking slab allocation primitives
1 parent 3a66565 commit 24d008e

19 files changed

Lines changed: 860 additions & 509 deletions

Detectors/ITSMFT/ITS/tracking/CMakeLists.txt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ o2_add_library(ITStracking
1313
TARGETVARNAME targetName
1414
SOURCES src/ClusterLines.cxx
1515
src/Cluster.cxx
16-
src/CapacityEstimator.cxx
1716
src/Configuration.cxx
1817
src/FastMultEstConfig.cxx
1918
src/FastMultEst.cxx
@@ -36,9 +35,14 @@ o2_add_library(ITStracking
3635
O2::ITSReconstruction
3736
O2::ITSMFTReconstruction
3837
O2::DataFormatsITS
38+
O2::ITSMFTTrackingAllocation
3939
PRIVATE_LINK_LIBRARIES
4040
O2::Steer
4141
TBB::tbb)
42+
43+
target_include_directories(${targetName} PUBLIC
44+
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/Detectors/ITSMFT/common/tracking/include>
45+
$<INSTALL_INTERFACE:include>)
4246
# target_compile_options(${targetName} PRIVATE -O0 -g -fPIC -fno-omit-frame-pointer)
4347

4448
o2_add_library(ITSTrackingInterface

Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/TrackingKernels.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
#include <gsl/gsl>
1818

1919
#include "ITStracking/BoundedAllocator.h"
20-
#include "ITStracking/CapacityEstimator.h"
20+
#include "ITSMFTTracking/CapacityEstimator.h"
2121
#include "ITStracking/ROFLookupTables.h"
2222
#include "ITStracking/TrackingTopology.h"
2323
#include "ITStracking/TrackExtensionHypothesis.h"
@@ -118,7 +118,7 @@ struct TrackingKernels {
118118
TrackSeed<NLayers>* seedsDevice,
119119
const int seedsCapacity,
120120
int& seedsCursor,
121-
CapacityEstimator& estimator,
121+
o2::itsmft::tracking::CapacityEstimator& estimator,
122122
const int iteration,
123123
const float bz,
124124
const float MaxChi2ClusterAttachment,

Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackerTraitsGPU.cxx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@
2020
namespace o2::its
2121
{
2222

23+
using o2::itsmft::tracking::CapacityEstimator;
24+
using o2::itsmft::tracking::runOnSlab;
25+
using o2::itsmft::tracking::SlabSite;
26+
2327
template <int NLayers>
2428
void TrackerTraitsGPU<NLayers>::initialiseTimeFrame(const int iteration)
2529
{

Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackingKernels.cu

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@ using namespace o2::track;
5252

5353
namespace o2::its
5454
{
55+
56+
using o2::itsmft::tracking::CapacityEstimator;
57+
using o2::itsmft::tracking::runOnSlab;
58+
using o2::itsmft::tracking::SlabSite;
5559
namespace gpu
5660
{
5761

Detectors/ITSMFT/ITS/tracking/include/ITStracking/BoundedAllocator.h

Lines changed: 8 additions & 294 deletions
Original file line numberDiff line numberDiff line change
@@ -16,305 +16,19 @@
1616
#ifndef TRACKINGITSU_INCLUDE_BOUNDEDALLOCATOR_H_
1717
#define TRACKINGITSU_INCLUDE_BOUNDEDALLOCATOR_H_
1818

19-
#include <limits>
20-
#include <memory_resource>
21-
#include <atomic>
22-
#include <new>
23-
#include <vector>
24-
25-
#if !defined(__HIPCC__) && !defined(__CUDACC__)
26-
#include <format>
27-
#include <string>
28-
#include "GPUCommonLogger.h"
29-
#endif
30-
#include "ITStracking/ExternalAllocator.h"
31-
#include "ITStracking/Constants.h"
19+
#include "ITSMFTTracking/BoundedAllocator.h"
3220

3321
namespace o2::its
3422
{
3523

36-
// #define BOUNDED_MR_STATS
37-
class BoundedMemoryResource final : public std::pmr::memory_resource
38-
{
39-
public:
40-
class MemoryLimitExceeded final : public std::bad_alloc
41-
{
42-
public:
43-
MemoryLimitExceeded(size_t attempted, size_t used, size_t max)
44-
{
45-
char buf[256];
46-
if (attempted != 0) {
47-
(void)snprintf(buf, sizeof(buf), "Reached set memory limit (attempted: %zu, used: %zu, max: %zu)", attempted, used, max);
48-
} else {
49-
(void)snprintf(buf, sizeof(buf), "New set maximum below current used (newMax: %zu, used: %zu)", max, used);
50-
}
51-
mMsg = buf;
52-
}
53-
const char* what() const noexcept final { return mMsg.c_str(); }
54-
55-
private:
56-
std::string mMsg;
57-
};
58-
59-
static std::pmr::memory_resource* cachingUpstream()
60-
{
61-
static std::pmr::synchronized_pool_resource pool{std::pmr::get_default_resource()};
62-
return &pool;
63-
}
64-
65-
BoundedMemoryResource(size_t maxBytes = std::numeric_limits<size_t>::max(),
66-
std::pmr::memory_resource* upstream = nullptr)
67-
: mMaxMemory(maxBytes), mUpstream(upstream != nullptr ? upstream : cachingUpstream()) {}
68-
69-
BoundedMemoryResource(ExternalAllocator* alloc,
70-
size_t maxBytes = std::numeric_limits<size_t>::max())
71-
: mMaxMemory(maxBytes),
72-
mAdaptor(std::make_unique<ExternalAllocatorAdaptor>(alloc)),
73-
mUpstream(mAdaptor.get()) {}
74-
75-
void* do_allocate(size_t bytes, size_t alignment) final
76-
{
77-
size_t new_used{0};
78-
size_t current_used{mUsedMemory.load(std::memory_order_relaxed)};
79-
do {
80-
new_used = current_used + bytes;
81-
if (new_used > mMaxMemory.load(std::memory_order_relaxed)) {
82-
mCountThrow.fetch_add(1, std::memory_order_relaxed);
83-
throw MemoryLimitExceeded(new_used, current_used,
84-
mMaxMemory.load(std::memory_order_relaxed));
85-
}
86-
} while (!mUsedMemory.compare_exchange_weak(current_used, new_used,
87-
std::memory_order_acq_rel,
88-
std::memory_order_relaxed));
89-
90-
void* p{nullptr};
91-
try {
92-
p = mUpstream->allocate(bytes, alignment);
93-
} catch (...) {
94-
mUsedMemory.fetch_sub(bytes, std::memory_order_relaxed);
95-
#ifdef BOUNDED_MR_STATS
96-
mStats.upstreamFailures.fetch_add(1, std::memory_order_relaxed);
97-
#endif
98-
throw;
99-
}
100-
101-
size_t peak = mPeakUsedMemory.load(std::memory_order_relaxed);
102-
while (new_used > peak &&
103-
!mPeakUsedMemory.compare_exchange_weak(peak, new_used,
104-
std::memory_order_relaxed)) {
105-
}
106-
107-
#ifdef BOUNDED_MR_STATS
108-
size_t statsPeak = mStats.peak.load(std::memory_order_relaxed);
109-
while (new_used > statsPeak &&
110-
!mStats.peak.compare_exchange_weak(statsPeak, new_used,
111-
std::memory_order_relaxed)) {
112-
}
113-
mStats.live.fetch_add(1, std::memory_order_relaxed);
114-
mStats.nAlloc.fetch_add(1, std::memory_order_relaxed);
115-
mStats.totalAlloc.fetch_add(bytes, std::memory_order_relaxed);
116-
117-
size_t ma = mStats.maxAlign.load(std::memory_order_relaxed);
118-
while (alignment > ma && !mStats.maxAlign.compare_exchange_weak(ma, alignment, std::memory_order_relaxed)) {
119-
}
120-
#endif
121-
return p;
122-
}
123-
124-
void do_deallocate(void* p, size_t bytes, size_t alignment) final
125-
{
126-
mUpstream->deallocate(p, bytes, alignment);
127-
mUsedMemory.fetch_sub(bytes, std::memory_order_relaxed);
128-
#ifdef BOUNDED_MR_STATS
129-
mStats.live.fetch_sub(1, std::memory_order_relaxed);
130-
mStats.nFree.fetch_add(1, std::memory_order_relaxed);
131-
mStats.totalFreed.fetch_add(bytes, std::memory_order_relaxed);
132-
#endif
133-
}
134-
135-
bool do_is_equal(const std::pmr::memory_resource& other) const noexcept final
136-
{
137-
return this == &other;
138-
}
139-
140-
[[nodiscard]] size_t getUsedMemory() const noexcept
141-
{
142-
return mUsedMemory.load(std::memory_order_relaxed);
143-
}
144-
[[nodiscard]] size_t getMaxMemory() const noexcept
145-
{
146-
return mMaxMemory.load(std::memory_order_relaxed);
147-
}
148-
[[nodiscard]] size_t getThrowCount() const noexcept
149-
{
150-
return mCountThrow.load(std::memory_order_relaxed);
151-
}
152-
[[nodiscard]] size_t getPeakMemory() const noexcept
153-
{
154-
return mPeakUsedMemory.load(std::memory_order_relaxed);
155-
}
156-
[[nodiscard]] size_t getPeakMemoryDelta() const noexcept
157-
{
158-
const size_t peak = mPeakUsedMemory.load(std::memory_order_relaxed);
159-
const size_t baseline = mPeakBaselineMemory.load(std::memory_order_relaxed);
160-
return peak > baseline ? peak - baseline : 0;
161-
}
162-
163-
void resetPeakMemory() noexcept
164-
{
165-
const size_t used = mUsedMemory.load(std::memory_order_acquire);
166-
mPeakBaselineMemory.store(used, std::memory_order_release);
167-
mPeakUsedMemory.store(used, std::memory_order_release);
168-
}
169-
170-
void setMaxMemory(size_t max)
171-
{
172-
size_t current = mMaxMemory.load(std::memory_order_relaxed);
173-
if (max == current) {
174-
return;
175-
}
176-
for (;;) {
177-
size_t used = mUsedMemory.load(std::memory_order_acquire);
178-
if (used > max) {
179-
mCountThrow.fetch_add(1, std::memory_order_relaxed);
180-
throw MemoryLimitExceeded(0, used, max);
181-
}
182-
if (mMaxMemory.compare_exchange_weak(current, max,
183-
std::memory_order_release,
184-
std::memory_order_relaxed)) {
185-
return;
186-
}
187-
if (current == max) {
188-
return;
189-
}
190-
}
191-
}
192-
193-
#if !defined(__HIPCC__) && !defined(__CUDACC__)
194-
std::string asString() const
195-
{
196-
const auto throw_ = mCountThrow.load(std::memory_order_relaxed);
197-
const auto used = static_cast<double>(mUsedMemory.load(std::memory_order_relaxed));
198-
const auto peak = static_cast<double>(mPeakUsedMemory.load(std::memory_order_relaxed));
199-
const auto peakDelta = static_cast<double>(getPeakMemoryDelta());
200-
const auto maxm = mMaxMemory.load(std::memory_order_relaxed);
201-
std::string ret;
202-
if (maxm == std::numeric_limits<size_t>::max()) {
203-
ret += std::format("maxthrow={} maxmem=unbounded used={:.2f} GB stagepeak={:.2f} GB stagealloc={:.2f} GB", throw_, used / constants::GB, peak / constants::GB, peakDelta / constants::GB);
204-
} else {
205-
ret += std::format("maxthrow={} maxmem={:.2f} GB used={:.2f} GB ({:.2f}%) stagepeak={:.2f} GB stagealloc={:.2f} GB", throw_, (double)maxm / constants::GB, used / constants::GB, 100.0 * used / (double)maxm, peak / constants::GB, peakDelta / constants::GB);
206-
}
207-
#ifdef BOUNDED_MR_STATS
208-
ret += std::format(" peak={:.2f} GB live={} nAlloc={} nFree={} totalAlloc={:.2f} GB totalFreed={:.2f} GB maxAlign={} upstreamFail={}",
209-
(float)mStats.peak.load(std::memory_order_relaxed) / constants::GB,
210-
mStats.live.load(std::memory_order_relaxed),
211-
mStats.nAlloc.load(std::memory_order_relaxed),
212-
mStats.nFree.load(std::memory_order_relaxed),
213-
(float)mStats.totalAlloc.load(std::memory_order_relaxed) / constants::GB,
214-
(float)mStats.totalFreed.load(std::memory_order_relaxed) / constants::GB,
215-
mStats.maxAlign.load(std::memory_order_relaxed),
216-
mStats.upstreamFailures.load(std::memory_order_relaxed));
217-
#endif
218-
return ret;
219-
}
220-
221-
void print() const
222-
{
223-
LOGP(info, "{}", asString());
224-
}
225-
#endif
226-
227-
private:
228-
std::atomic<size_t> mMaxMemory{std::numeric_limits<size_t>::max()};
229-
std::atomic<size_t> mCountThrow{0};
230-
std::atomic<size_t> mUsedMemory{0};
231-
std::atomic<size_t> mPeakUsedMemory{0};
232-
std::atomic<size_t> mPeakBaselineMemory{0};
233-
std::unique_ptr<ExternalAllocatorAdaptor> mAdaptor{nullptr};
234-
std::pmr::memory_resource* mUpstream{nullptr};
235-
236-
#ifdef BOUNDED_MR_STATS
237-
struct Stats {
238-
std::atomic<size_t> peak{0};
239-
std::atomic<size_t> live{0};
240-
std::atomic<size_t> nAlloc{0};
241-
std::atomic<size_t> nFree{0};
242-
std::atomic<size_t> totalAlloc{0};
243-
std::atomic<size_t> totalFreed{0};
244-
std::atomic<size_t> maxAlign{0};
245-
std::atomic<size_t> upstreamFailures{0};
246-
};
247-
Stats mStats{};
248-
#endif
249-
};
250-
24+
using o2::itsmft::tracking::BoundedMemoryResource;
25125
template <typename T>
252-
using bounded_vector = std::pmr::vector<T>;
253-
254-
template <typename T>
255-
inline void deepVectorClear(std::vector<T>& vec)
256-
{
257-
std::vector<T>().swap(vec);
258-
}
259-
260-
template <typename T>
261-
inline void deepVectorClear(bounded_vector<T>& vec, std::pmr::memory_resource* mr = nullptr)
262-
{
263-
std::pmr::memory_resource* tmr = (mr != nullptr) ? mr : vec.get_allocator().resource();
264-
vec.~bounded_vector<T>();
265-
new (&vec) bounded_vector<T>(std::pmr::polymorphic_allocator<T>{tmr});
266-
}
267-
268-
template <typename T>
269-
inline void deepVectorClear(std::vector<bounded_vector<T>>& vec, std::pmr::memory_resource* mr = nullptr)
270-
{
271-
for (auto& v : vec) {
272-
deepVectorClear(v, mr);
273-
}
274-
}
275-
276-
template <typename T, size_t S>
277-
inline void deepVectorClear(std::array<bounded_vector<T>, S>& arr, std::pmr::memory_resource* mr = nullptr)
278-
{
279-
for (size_t i{0}; i < S; ++i) {
280-
deepVectorClear(arr[i], mr);
281-
}
282-
}
283-
284-
template <typename T>
285-
inline void clearResizeBoundedVector(bounded_vector<T>& vec, size_t sz, std::pmr::memory_resource* mr = nullptr, T def = T())
286-
{
287-
std::pmr::memory_resource* tmr = (mr != nullptr) ? mr : vec.get_allocator().resource();
288-
vec.~bounded_vector<T>();
289-
new (&vec) bounded_vector<T>(sz, def, std::pmr::polymorphic_allocator<T>{tmr});
290-
}
291-
292-
template <typename T>
293-
inline void clearResizeBoundedVector(std::vector<bounded_vector<T>>& vec, size_t size, std::pmr::memory_resource* mr)
294-
{
295-
vec.clear();
296-
vec.reserve(size);
297-
for (size_t i = 0; i < size; ++i) {
298-
vec.emplace_back(std::pmr::polymorphic_allocator<bounded_vector<T>>{mr});
299-
}
300-
}
301-
302-
template <typename T, size_t S>
303-
inline void clearResizeBoundedArray(std::array<bounded_vector<T>, S>& arr, size_t size, std::pmr::memory_resource* mr = nullptr, T def = T())
304-
{
305-
for (size_t i{0}; i < S; ++i) {
306-
clearResizeBoundedVector(arr[i], size, mr, def);
307-
}
308-
}
309-
310-
template <typename T>
311-
inline std::vector<T> toSTDVector(const bounded_vector<T>& b)
312-
{
313-
std::vector<T> t(b.size());
314-
std::copy(b.cbegin(), b.cend(), t.begin());
315-
return t;
316-
}
26+
using bounded_vector = o2::itsmft::tracking::bounded_vector<T>;
27+
using o2::itsmft::tracking::clearResizeBoundedArray;
28+
using o2::itsmft::tracking::clearResizeBoundedVector;
29+
using o2::itsmft::tracking::deepVectorClear;
30+
using o2::itsmft::tracking::toSTDVector;
31731

31832
} // namespace o2::its
31933

320-
#endif
34+
#endif /* TRACKINGITSU_INCLUDE_BOUNDEDALLOCATOR_H_ */

0 commit comments

Comments
 (0)