Project
Loading...
Searching...
No Matches
Utils.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.
15
16#ifndef ITSTRACKINGGPU_UTILS_H_
17#define ITSTRACKINGGPU_UTILS_H_
18
19#include <vector>
20#include <string>
21#include <tuple>
22
25
26#include "GPUCommonDef.h"
27#include "GPUCommonHelpers.h"
28#include "GPUCommonLogger.h"
29#include "GPUCommonDefAPI.h"
30
31#ifdef GPUCA_GPUCODE
32#include <thrust/device_ptr.h>
33#ifndef __HIPCC__
34#define THRUST_NAMESPACE thrust::cuda
35#else
36#define THRUST_NAMESPACE thrust::hip
37#endif
38#endif
39
40#ifdef ITS_GPU_LOG
41#if defined(__HIPCC__)
42#define GPULogSync() GPUChkErrS(hipDeviceSynchronize())
43#elif defined(__CUDACC__)
44#define GPULogSync() GPUChkErrS(cudaDeviceSynchronize())
45#else
46#define GPULogSync()
47#endif
48#define GPULog(...) \
49 do { \
50 LOGP(info, __VA_ARGS__); \
51 GPULogSync(); \
52 } while (0)
53#else
54#define GPULog(...)
55#endif
56
57namespace o2::its
58{
59// FWD declarations
60template <int>
61class IndexTableUtils;
62class Tracklet;
63
64template <typename T1, typename T2>
65using gpuPair = std::pair<T1, T2>;
66
67namespace gpu
68{
69
70template <typename T>
71struct gpuSpan {
72 using value_type = T;
73 using ptr = T*;
74 using ref = T&;
75
76 GPUd() gpuSpan() : _data(nullptr), _size(0) {}
77 GPUd() gpuSpan(ptr data, unsigned int dim) : _data(data), _size(dim) {}
78 GPUd() ref operator[](unsigned int idx) const { return _data[idx]; }
79 GPUd() unsigned int size() const { return _size; }
80 GPUd() bool empty() const { return _size == 0; }
81 GPUd() ref front() const { return _data[0]; }
82 GPUd() ref back() const { return _data[_size - 1]; }
83 GPUd() ptr begin() const { return _data; }
84 GPUd() ptr end() const { return _data + _size; }
85
86 protected:
88 unsigned int _size;
89};
90
91template <typename T>
92struct gpuSpan<const T> {
93 using value_type = T;
94 using ptr = const T*;
95 using ref = const T&;
96
97 GPUd() gpuSpan() : _data(nullptr), _size(0) {}
98 GPUd() gpuSpan(ptr data, unsigned int dim) : _data(data), _size(dim) {}
100 GPUd() ref operator[](unsigned int idx) const { return _data[idx]; }
101 GPUd() unsigned int size() const { return _size; }
102 GPUd() bool empty() const { return _size == 0; }
103 GPUd() ref front() const { return _data[0]; }
104 GPUd() ref back() const { return _data[_size - 1]; }
105 GPUd() ptr begin() const { return _data; }
106 GPUd() ptr end() const { return _data + _size; }
107
108 protected:
110 unsigned int _size;
111};
112
113// Abstract stream class
115{
116 public:
117#if defined(__HIPCC__)
118 using Handle = hipStream_t;
119 static constexpr Handle DefaultStream = 0;
120 static constexpr unsigned int DefaultFlag = hipStreamNonBlocking;
121 using Event = hipEvent_t;
122#elif defined(__CUDACC__)
123 using Handle = cudaStream_t;
124 static constexpr Handle DefaultStream = 0;
125 static constexpr unsigned int DefaultFlag = cudaStreamNonBlocking;
126 using Event = cudaEvent_t;
127#else
128 using Handle = void*;
129 static constexpr Handle DefaultStream = nullptr;
130 static constexpr unsigned int DefaultFlag = 0;
131 using Event = void*;
132#endif
133
134 Stream(unsigned int flags = DefaultFlag)
135 {
136#if defined(__HIPCC__)
137 GPUChkErrS(hipStreamCreateWithFlags(&mHandle, flags));
138 GPUChkErrS(hipEventCreateWithFlags(&mEvent, hipEventDisableTiming));
139#elif defined(__CUDACC__)
140 GPUChkErrS(cudaStreamCreateWithFlags(&mHandle, flags));
141 GPUChkErrS(cudaEventCreateWithFlags(&mEvent, cudaEventDisableTiming));
142#endif
143 }
144
145 Stream(Handle h) : mHandle(h) {}
147 {
148 if (mHandle != DefaultStream) {
149#if defined(__HIPCC__)
150 GPUChkErrS(hipStreamDestroy(mHandle));
151 GPUChkErrS(hipEventDestroy(mEvent));
152#elif defined(__CUDACC__)
153 GPUChkErrS(cudaStreamDestroy(mHandle));
154 GPUChkErrS(cudaEventDestroy(mEvent));
155#endif
156 }
157 }
158
159 operator bool() const { return mHandle != DefaultStream; }
160 const Handle& get() { return mHandle; }
161 const Handle& getStream() { return mHandle; }
162 const Event& getEvent() { return mEvent; }
163 void sync() const
164 {
165#if defined(__HIPCC__)
166 GPUChkErrS(hipStreamSynchronize(mHandle));
167#elif defined(__CUDACC__)
168 GPUChkErrS(cudaStreamSynchronize(mHandle));
169#endif
170 }
171 void record()
172 {
173#if defined(__HIPCC__)
174 GPUChkErrS(hipEventRecord(mEvent, mHandle));
175#elif defined(__CUDACC__)
176 GPUChkErrS(cudaEventRecord(mEvent, mHandle));
177#endif
178 }
179
180 private:
181 Handle mHandle{DefaultStream};
182 Event mEvent{nullptr};
183};
184
185// Abstract vector for streams.
187{
188 public:
189 size_t size() const noexcept { return mStreams.size(); }
190 void resize(size_t n) { mStreams.resize(n); }
191 void clear() { mStreams.clear(); }
192 auto& operator[](size_t i) { return mStreams[i]; }
193 void push_back(const Stream& stream) { mStreams.push_back(stream); }
194 void sync(bool device = true)
195 {
196 if (device) {
197#if defined(__HIPCC__)
198 GPUChkErrS(hipDeviceSynchronize());
199#elif defined(__CUDACC__)
200 GPUChkErrS(cudaDeviceSynchronize());
201#endif
202 } else {
203 for (auto& s : mStreams) {
204 s.sync();
205 }
206 }
207 }
208 void waitEvent(size_t iStream, size_t iEvent)
209 {
210#if defined(__HIPCC__)
211 GPUChkErrS(hipStreamWaitEvent(mStreams[iStream].get(), mStreams[iEvent].getEvent()));
212#elif defined(__CUDACC__)
213 GPUChkErrS(cudaStreamWaitEvent(mStreams[iStream].get(), mStreams[iEvent].getEvent()));
214#endif
215 }
216
217 private:
218 std::vector<Stream> mStreams;
219};
220
221#ifdef ITS_MEASURE_GPU_TIME
222class GPUTimer
223{
224 public:
225 GPUTimer(const std::string& name)
226 : mName(name)
227 {
228 mStreams.emplace_back(Stream::DefaultStream);
229 startTimers();
230 }
231 GPUTimer(Streams& streams, const std::string& name)
232 : mName(name)
233 {
234 for (size_t i{0}; i < streams.size(); ++i) {
235 mStreams.push_back(streams[i].get());
236 }
237 startTimers();
238 }
239 GPUTimer(Streams& streams, const std::string& name, size_t end, size_t start = 0)
240 : mName(name)
241 {
242 for (size_t sta{start}; sta < end; ++sta) {
243 mStreams.push_back(streams[sta].get());
244 }
245 startTimers();
246 }
247 GPUTimer(Stream& stream, const std::string& name, const int id = 0)
248 : mName(name)
249 {
250 mStreams.push_back(stream.get());
251 mName += ":id" + std::to_string(id);
252 startTimers();
253 }
254 ~GPUTimer()
255 {
256 for (size_t i{0}; i < mStreams.size(); ++i) {
257 float ms = 0.0f;
258#if defined(__HIPCC__)
259 GPUChkErrS(hipEventRecord(mStops[i], mStreams[i]));
260 GPUChkErrS(hipEventSynchronize(mStops[i]));
261 GPUChkErrS(hipEventElapsedTime(&ms, mStarts[i], mStops[i]));
262 GPUChkErrS(hipEventDestroy(mStarts[i]));
263 GPUChkErrS(hipEventDestroy(mStops[i]));
264#elif defined(__CUDACC__)
265 GPUChkErrS(cudaEventRecord(mStops[i], mStreams[i]));
266 GPUChkErrS(cudaEventSynchronize(mStops[i]));
267 GPUChkErrS(cudaEventElapsedTime(&ms, mStarts[i], mStops[i]));
268 GPUChkErrS(cudaEventDestroy(mStarts[i]));
269 GPUChkErrS(cudaEventDestroy(mStops[i]));
270#endif
271 LOGP(info, "Elapsed time for {}:{} {} ms", mName, i, ms);
272 }
273 }
274
275 void startTimers()
276 {
277 mStarts.resize(mStreams.size());
278 mStops.resize(mStreams.size());
279 for (size_t i{0}; i < mStreams.size(); ++i) {
280#if defined(__HIPCC__)
281 GPUChkErrS(hipEventCreate(&mStarts[i]));
282 GPUChkErrS(hipEventCreate(&mStops[i]));
283 GPUChkErrS(hipEventRecord(mStarts[i], mStreams[i]));
284#elif defined(__CUDACC__)
285 GPUChkErrS(cudaEventCreate(&mStarts[i]));
286 GPUChkErrS(cudaEventCreate(&mStops[i]));
287 GPUChkErrS(cudaEventRecord(mStarts[i], mStreams[i]));
288#endif
289 }
290 }
291
292 private:
293 std::string mName;
294 std::vector<Stream::Event> mStarts, mStops;
295 std::vector<Stream::Handle> mStreams;
296};
297#else // ITS_MEASURE_GPU_TIME not defined
299{
300 public:
301 template <typename... Args>
302 GPUTimer(Args&&...)
303 {
304 }
305};
306#endif
307
308#ifdef GPUCA_GPUCODE
309template <typename T>
310struct TypedAllocator {
311 using value_type = T;
312 using pointer = thrust::device_ptr<T>;
313 using const_pointer = thrust::device_ptr<const T>;
314 using size_type = std::size_t;
315 using difference_type = std::ptrdiff_t;
316
317 TypedAllocator() noexcept : mInternalAllocator(nullptr) {}
318 explicit TypedAllocator(ExternalAllocator* a) noexcept : mInternalAllocator(a) {}
319
320 template <typename U>
321 TypedAllocator(const TypedAllocator<U>& o) noexcept : mInternalAllocator(o.mInternalAllocator)
322 {
323 }
324
325 pointer allocate(size_type n)
326 {
327 void* raw = mInternalAllocator->allocateStack(n * sizeof(T));
328 return thrust::device_pointer_cast(static_cast<T*>(raw));
329 }
330
331 void deallocate(pointer p, size_type n) noexcept
332 {
333 if (!p) {
334 return;
335 }
336 void* raw = thrust::raw_pointer_cast(p);
337 mInternalAllocator->deallocate(static_cast<char*>(raw), n * sizeof(T));
338 }
339
340 bool operator==(TypedAllocator const& o) const noexcept
341 {
342 return mInternalAllocator == o.mInternalAllocator;
343 }
344 bool operator!=(TypedAllocator const& o) const noexcept
345 {
346 return !(*this == o);
347 }
348
349 private:
350 ExternalAllocator* mInternalAllocator;
351};
352
353// first i in [beg,end) with a[i] >= key
354template <typename T>
355GPUdii() int deviceLowerBound(const T* a, int beg, int end, const T key)
356{
357 while (beg < end) {
358 const int mid = beg + (end - beg) / 2;
359 if (a[mid] < key) {
360 beg = mid + 1;
361 } else {
362 end = mid;
363 }
364 }
365 return beg;
366}
367
368// first i in [beg,end) with a[i] > key
369template <typename T>
370GPUdii() int deviceUpperBound(const T* a, int beg, int end, const T key)
371{
372 while (beg < end) {
373 const int mid = beg + (end - beg) / 2;
374 if (a[mid] <= key) {
375 beg = mid + 1;
376 } else {
377 end = mid;
378 }
379 }
380 return beg;
381}
382
383GPUdii() gpuSpan<const Cluster> getClustersOnLayer(const int rof,
384 const int totROFs,
385 const int layer,
386 const int** roframesClus,
387 const Cluster** clusters)
388{
389 if (rof < 0 || rof >= totROFs) {
390 return gpuSpan<const Cluster>();
391 }
392 const int start_clus_id{roframesClus[layer][rof]};
393 const int stop_rof = rof >= totROFs - 1 ? totROFs : rof + 1;
394 const unsigned int delta = roframesClus[layer][stop_rof] - start_clus_id;
395 return gpuSpan<const Cluster>(&(clusters[layer][start_clus_id]), delta);
396}
397
398#endif
399} // namespace gpu
400} // namespace o2::its
401
402#endif
int32_t i
#define GPUdii()
#define GPUChkErrS(x)
o2::raw::RawFileWriter * raw
StringRef key
Class for time synchronization of RawReader instances.
HMPID cluster implementation.
Definition Cluster.h:27
GPUTimer(Args &&...)
Definition Utils.h:302
const Handle & getStream()
Definition Utils.h:161
void sync() const
Definition Utils.h:163
const Handle & get()
Definition Utils.h:160
static constexpr Handle DefaultStream
Definition Utils.h:129
static constexpr unsigned int DefaultFlag
Definition Utils.h:130
const Event & getEvent()
Definition Utils.h:162
Stream(unsigned int flags=DefaultFlag)
Definition Utils.h:134
Stream(Handle h)
Definition Utils.h:145
void resize(size_t n)
Definition Utils.h:190
void push_back(const Stream &stream)
Definition Utils.h:193
void waitEvent(size_t iStream, size_t iEvent)
Definition Utils.h:208
void sync(bool device=true)
Definition Utils.h:194
auto & operator[](size_t i)
Definition Utils.h:192
size_t size() const noexcept
Definition Utils.h:189
GLdouble n
Definition glcorearb.h:1982
GLenum void ** pointer
Definition glcorearb.h:805
GLsizeiptr size
Definition glcorearb.h:659
GLuint GLuint end
Definition glcorearb.h:469
GLuint const GLchar * name
Definition glcorearb.h:781
GLboolean * data
Definition glcorearb.h:298
GLbitfield flags
Definition glcorearb.h:1570
GLenum GLuint GLint GLint layer
Definition glcorearb.h:1310
GLuint start
Definition glcorearb.h:469
GLboolean GLboolean GLboolean GLboolean a
Definition glcorearb.h:1233
GLuint GLuint stream
Definition glcorearb.h:1806
auto get(const std::byte *buffer, size_t=0)
Definition DataHeader.h:457
std::pair< T1, T2 > gpuPair
Definition Utils.h:65
const int end
bool operator!=(const DsChannelId &a, const DsChannelId &b)
Definition DsChannelId.h:66
std::string to_string(gsl::span< T, Size > span)
Definition common.h:52
void empty(int)
GPUd() gpuSpan(const gpuSpan< T > &other)
Definition Utils.h:99
GPUd() ref front() const
Definition Utils.h:103
GPUd() bool empty() const
Definition Utils.h:102
GPUd() ref operator[](unsigned int idx) const
Definition Utils.h:100
GPUd() ptr end() const
Definition Utils.h:106
GPUd() unsigned int size() const
Definition Utils.h:101
GPUd() ptr begin() const
Definition Utils.h:105
GPUd() ref back() const
Definition Utils.h:104
GPUd() bool empty() const
Definition Utils.h:80
unsigned int dim
Definition Utils.h:77
GPUd() ptr begin() const
Definition Utils.h:83
GPUd() ref operator[](unsigned int idx) const
Definition Utils.h:78
GPUd() gpuSpan()
Definition Utils.h:76
GPUd() ptr end() const
Definition Utils.h:84
GPUd() unsigned int size() const
Definition Utils.h:79
unsigned int _size
Definition Utils.h:88
GPUd() ref back() const
Definition Utils.h:82
GPUd() ref front() const
Definition Utils.h:81
bool operator==(const CoarseLocation &a, const CoarseLocation &b)
VectorOfTObjectPtrs other
std::vector< Cluster > clusters