Skip to content

Commit 9f4d3e2

Browse files
committed
GPU Metal: run the merger's sorts on the host
The sorts of the merged tracks by quality and by q/pT, of the looper candidates and of the O2 output tracks, which CUDA and HIP run with thrust, ran on a single GPU thread otherwise: about 730 ms per event on a 30-collision Pb-Pb time frame, at up to 140 times the CPU's time. The GPU memory is shared with the host, so sort there once the stream is drained, with the std::sort of the CPU backend, which also orders the elements that compare equal as on the CPU. The number of elements is read from the device copy of the counters, as the host copy of the O2 output count is still being transferred when the sort is launched.
1 parent 9e0c15e commit 9f4d3e2

2 files changed

Lines changed: 57 additions & 0 deletions

File tree

‎GPU/GPUTracking/Base/metal/GPUReconstructionMetal.h‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,10 @@ class GPUReconstructionMetal : public GPUReconstructionProcessing::KernelInterfa
6060
void CommitStream(int32_t stream);
6161
void DrainStream(int32_t stream);
6262
uint64_t EventValue(deviceEvent ev, bool next);
63+
template <class T>
64+
T* HostPointer(T* p);
65+
template <class T, class N, class S>
66+
void SortOnHost(const krnlSetupTime& _xyz, T* begin, const N& count, const S& comp);
6367

6468
private:
6569
int32_t AddKernels();

‎GPU/GPUTracking/Base/metal/GPUReconstructionMetalKernelsSpecialize.inc‎

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111

1212
/// \file GPUReconstructionMetalKernelsSpecialize.inc
1313

14+
#include "GPUTPCGMMergerSortComp.h"
15+
1416
template <>
1517
inline void GPUReconstructionMetal::runKernelBackend<GPUMemClean16, 0>(const krnlSetupTime& _xyz, void* const& ptr, uint64_t const& size)
1618
{
@@ -30,3 +32,54 @@ inline void GPUReconstructionMetal::runKernelBackend<GPUMemClean16, 0>(const krn
3032
RecordMarker(_xyz.z.ev, _xyz.x.stream);
3133
}
3234
}
35+
36+
// The sorts that CUDA and HIP run with thrust (GPUCA_SPECIALIZE_THRUST_SORTS)
37+
// run on a single GPU thread otherwise. The memory is shared with the host, so
38+
// sort there, with the same std::sort as the CPU backend, which also orders
39+
// the elements that compare equal as on the CPU. The number of elements is
40+
// read once the stream is drained, from the device copy of the counters,
41+
// since the host copy may still be on its way.
42+
template <class T>
43+
inline T* GPUReconstructionMetal::HostPointer(T* p)
44+
{
45+
const size_t offset = (const char*)p - (const char*)mDeviceMemoryBase;
46+
return offset < mDeviceMemorySize ? (T*)((char*)mInternals->mem_gpu.contents + offset) : p;
47+
}
48+
49+
template <class T, class N, class S>
50+
inline void GPUReconstructionMetal::SortOnHost(const krnlSetupTime& _xyz, T* begin, const N& count, const S& comp)
51+
{
52+
if (_xyz.z.evList) {
53+
StreamWaitForEvents(_xyz.x.stream, _xyz.z.evList, _xyz.z.nEvents);
54+
}
55+
DrainStream(_xyz.x.stream);
56+
T* hostBegin = HostPointer(begin);
57+
GPUCommonAlgorithm::sortDeviceDynamic(hostBegin, hostBegin + count(), comp);
58+
if (_xyz.z.ev) {
59+
RecordMarker(_xyz.z.ev, _xyz.x.stream);
60+
}
61+
}
62+
63+
template <>
64+
inline void GPUReconstructionMetal::runKernelBackend<GPUTPCGMMergerSortTracks, 0>(const krnlSetupTime& _xyz)
65+
{
66+
SortOnHost(_xyz, mProcessorsShadow->tpcMerger.TrackOrderProcess(), [&] { return HostPointer(mProcessorsShadow->tpcMerger.Memory())->nMergedTracks; }, internal::GPUTPCGMMergerSortTracks_comp(HostPointer(mProcessorsShadow->tpcMerger.MergedTracks())));
67+
}
68+
69+
template <>
70+
inline void GPUReconstructionMetal::runKernelBackend<GPUTPCGMMergerSortTracksQPt, 0>(const krnlSetupTime& _xyz)
71+
{
72+
SortOnHost(_xyz, mProcessorsShadow->tpcMerger.TrackSort(), [&] { return HostPointer(mProcessorsShadow->tpcMerger.Memory())->nMergedTracks; }, internal::GPUTPCGMMergerSortTracksQPt_comp(HostPointer(mProcessorsShadow->tpcMerger.MergedTracks())));
73+
}
74+
75+
template <>
76+
inline void GPUReconstructionMetal::runKernelBackend<GPUTPCGMMergerMergeLoopers, 1>(const krnlSetupTime& _xyz)
77+
{
78+
SortOnHost(_xyz, mProcessorsShadow->tpcMerger.LooperCandidates(), [&] { return HostPointer(mProcessorsShadow->tpcMerger.Memory())->nLooperMatchCandidates; }, internal::GPUTPCGMMergerMergeLoopers_comp());
79+
}
80+
81+
template <>
82+
inline void GPUReconstructionMetal::runKernelBackend<GPUTPCGMO2Output, GPUTPCGMO2Output::sort>(const krnlSetupTime& _xyz)
83+
{
84+
SortOnHost(_xyz, mProcessorsShadow->tpcMerger.TrackSortO2(), [&] { return HostPointer(mProcessorsShadow->tpcMerger.Memory())->nO2Tracks; }, internal::GPUTPCGMO2OutputSort_comp());
85+
}

0 commit comments

Comments
 (0)