Skip to content

Commit 5686fda

Browse files
committed
GPU Common Algorithm: Improve QuickSort implementation
1 parent 05f62ce commit 5686fda

1 file changed

Lines changed: 22 additions & 16 deletions

File tree

‎GPU/Common/GPUCommonAlgorithm.h‎

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -41,37 +41,34 @@ class GPUCommonAlgorithm
4141
GPUd() static void sortInBlock(T* begin, T* end, const S& comp GPUCA_THREAD_INFO_DECL);
4242
template <class T, class S>
4343
GPUd() static void sortDeviceDynamic(T* begin, T* end, const S& comp);
44-
#if __cplusplus >= 202002L // sortOnDevice takes an auto parameter
44+
#if __cplusplus >= 202002L // FIXME: auto parameter not supported in C++17
4545
template <class T, class S>
4646
GPUh() static void sortOnDevice(auto* rec, int32_t stream, T* begin, size_t N, const S& comp);
4747
#endif
4848
template <class T>
4949
GPUd() static void swap(T& a, T& b);
5050

5151
private:
52-
// Quicksort implementation
5352
template <typename I>
54-
GPUd() static void QuickSort(I f, I l) GPUnoexcept();
53+
GPUd() static void QuickSort(I f, I l) GPUnoexcept(); // Quicksort implementation
5554

56-
// Quicksort implementation
5755
template <typename I, typename Cmp>
58-
GPUd() static void QuickSort(I f, I l, Cmp cmp) GPUnoexcept();
56+
GPUd() static void QuickSort(I f, I l, Cmp cmp) GPUnoexcept(); // Quicksort implementation
57+
58+
template <typename IndexType, typename I, typename Cmp>
59+
GPUd() static void QuickSortImpl(I f, I l, Cmp cmp) GPUnoexcept(); // Quicksort implementation with index type IndexType, which must be able to hold the number of elements
5960

60-
// Insertionsort implementation
6161
template <typename I, typename Cmp>
62-
GPUd() static void InsertionSort(I f, I l, Cmp cmp) GPUnoexcept();
62+
GPUd() static void InsertionSort(I f, I l, Cmp cmp) GPUnoexcept(); // Insertionsort implementation
6363

64-
// Helper for Quicksort implementation
6564
template <typename I, typename Cmp>
66-
GPUd() static I MedianOf3Select(I f, I l, Cmp cmp) GPUnoexcept();
65+
GPUd() static I MedianOf3Select(I f, I l, Cmp cmp) GPUnoexcept(); // Helper for Quicksort implementation
6766

68-
// Helper for Quicksort implementation
6967
template <typename I, typename T, typename Cmp>
70-
GPUd() static I UnguardedPartition(I f, I l, T piv, Cmp cmp) GPUnoexcept();
68+
GPUd() static I UnguardedPartition(I f, I l, T piv, Cmp cmp) GPUnoexcept(); // Helper for Quicksort implementation
7169

72-
// Helper
7370
template <typename I>
74-
GPUd() static void IterSwap(I a, I b) GPUnoexcept();
71+
GPUd() static void IterSwap(I a, I b) GPUnoexcept(); // Helper
7572
};
7673

7774
#ifndef GPUCA_ALGORITHM_STD
@@ -147,19 +144,28 @@ GPUdi() I GPUCommonAlgorithm::UnguardedPartition(I f, I l, T piv, Cmp cmp) GPUno
147144

148145
template <typename I, typename Cmp>
149146
GPUdi() void GPUCommonAlgorithm::QuickSort(I f, I l, Cmp cmp) GPUnoexcept()
147+
{
148+
if (l - f <= 0xFFFF) {
149+
QuickSortImpl<uint16_t>(f, l, cmp);
150+
} else {
151+
QuickSortImpl<uint32_t>(f, l, cmp);
152+
}
153+
}
154+
155+
template <typename IndexType, typename I, typename Cmp>
156+
GPUdi() void GPUCommonAlgorithm::QuickSortImpl(I f, I l, Cmp cmp) GPUnoexcept()
150157
{
151158
if (f == l) {
152159
return;
153160
}
154-
using IndexType = uint16_t;
155161

156162
struct pair {
157163
IndexType first;
158164
IndexType second;
159165
};
160166

161167
struct Stack {
162-
pair data[11];
168+
pair data[sizeof(IndexType) * 8 - 4]; // The smaller partition is processed first, so the depth is bounded by log2(n / cutoff) + 1, cutoff = 50 > 2^5
163169
uint8_t n{0};
164170

165171
GPUd() void emplace(IndexType x, IndexType y)
@@ -282,7 +288,7 @@ GPUdi() void GPUCommonAlgorithm::sortInBlock(T* begin, T* end, const S& comp GPU
282288
{
283289
#ifndef GPUCA_GPUCODE
284290
GPUCommonAlgorithm::sort(begin, end, comp);
285-
#elif defined(GPUCA_DETERMINISTIC_MODE) // Not using GPUCA_DETERMINISTIC_CODE, which is enforced in TPC compression
291+
#elif defined(GPUCA_DETERMINISTIC_MODE) // Cannot use GPUCA_DETERMINISTIC_CODE macro here, which is enforced in TPC compression
286292
if (get_local_id(0) == 0) {
287293
GPUCommonAlgorithm::sort(begin, end, comp);
288294
}

0 commit comments

Comments
 (0)