MUSIC
unknown
Analysis for the MUSIC active-target ionization chamber
Toggle main menu visibility
Loading...
Searching...
No Matches
gpu_sort.cu
Go to the documentation of this file.
1
#include "
gpu_interface.h
"
2
3
#include <cuda_runtime.h>
4
#include <thrust/device_vector.h>
5
#include <thrust/host_vector.h>
6
#include <thrust/sort.h>
7
8
#include <cstdint>
9
#include <cstring>
10
#include <iostream>
11
#include <vector>
12
13
// Mirrors layout of RawHit in include/BinaryUtils.hpp.
14
// The host struct uses ROOT types (UShort_t, ULong64_t, UInt_t) but the
15
// memory layout under the standard ABI is:
16
// offset 0: board (2 bytes)
17
// offset 2: channel (2 bytes)
18
// offset 4: energy (2 bytes)
19
// offset 6: padding (2 bytes for ULong64_t alignment)
20
// offset 8: timestamp (8 bytes)
21
// offset 16: flags (4 bytes)
22
// offset 20: padding (4 bytes for struct alignment)
23
// Total: 24 bytes.
24
struct
RawHitGPU
{
25
uint16_t
board
;
26
uint16_t
channel
;
27
uint16_t
energy
;
28
uint16_t
_pad0
;
29
uint64_t
timestamp
;
30
uint32_t
flags
;
31
uint32_t
_pad1
;
32
};
33
34
static_assert
(
sizeof
(
RawHitGPU
) == 24,
35
"RawHitGPU must be 24 bytes to match host RawHit layout"
);
36
static_assert
(offsetof(
RawHitGPU
, timestamp) == 8,
37
"timestamp must sit at byte offset 8"
);
38
39
// Sort hits by timestamp. Rather than shipping the full 24-byte structs to the
40
// device and sorting them with a comparator (which forces thrust into a
41
// comparator merge sort needing ~2x the data in scratch), we ship only the
42
// 8-byte uint64 timestamp keys plus a 4-byte uint32 index and run a key/value
43
// sort -- a primitive-key radix sort. The device footprint per call drops from
44
// ~48 B/hit to ~24 B/hit (so more sorts fit concurrently) and H2D/D2H traffic
45
// drops from 24 down to 8 (down) + 4 (back) B/hit. The resulting permutation is
46
// applied to the host array by a gather; the full structs never touch the GPU.
47
extern
"C"
int
gpu_sort_hits_by_timestamp
(
void
*hits,
long
long
n_hits) {
48
if
(n_hits <= 0)
49
return
0;
50
51
// Indices are uint32 to keep the device payload small; a single subfile's hit
52
// count is far below 2^32, but guard anyway and let the caller fall back to
53
// the CPU sort if that ever stops holding.
54
if
(
static_cast<
unsigned
long
long
>
(n_hits) > 0xFFFFFFFFULL) {
55
std::cerr <<
"[GPU sort] n_hits "
<< n_hits
56
<<
" exceeds uint32 index range"
<< std::endl;
57
return
6;
58
}
59
60
RawHitGPU
*host_hits =
static_cast<
RawHitGPU
*
>
(hits);
61
62
try
{
63
thrust::host_vector<uint64_t> h_keys(n_hits);
64
thrust::host_vector<uint32_t> h_idx(n_hits);
65
for
(
long
long
i = 0; i < n_hits; i++) {
66
h_keys[i] = host_hits[i].
timestamp
;
67
h_idx[i] =
static_cast<
uint32_t
>
(i);
68
}
69
70
thrust::device_vector<uint64_t> d_keys = h_keys;
71
thrust::device_vector<uint32_t> d_idx = h_idx;
72
73
cudaError_t err = cudaGetLastError();
74
if
(err != cudaSuccess) {
75
std::cerr <<
"[GPU sort] H2D copy failed: "
<< cudaGetErrorString(err)
76
<< std::endl;
77
return
1;
78
}
79
80
thrust::sort_by_key(d_keys.begin(), d_keys.end(), d_idx.begin());
81
82
err = cudaGetLastError();
83
if
(err != cudaSuccess) {
84
std::cerr <<
"[GPU sort] sort kernel failed: "
<< cudaGetErrorString(err)
85
<< std::endl;
86
return
2;
87
}
88
89
thrust::copy(d_idx.begin(), d_idx.end(), h_idx.begin());
90
91
err = cudaGetLastError();
92
if
(err != cudaSuccess) {
93
std::cerr <<
"[GPU sort] D2H copy failed: "
<< cudaGetErrorString(err)
94
<< std::endl;
95
return
3;
96
}
97
98
// Gather the hits into sorted order on the host.
99
std::vector<RawHitGPU> sorted(n_hits);
100
for
(
long
long
i = 0; i < n_hits; i++)
101
sorted[i] = host_hits[h_idx[i]];
102
std::memcpy(host_hits, sorted.data(),
103
static_cast<
size_t
>
(n_hits) *
sizeof
(
RawHitGPU
));
104
}
catch
(
const
std::exception &e) {
105
std::cerr <<
"[GPU sort] exception: "
<< e.what() << std::endl;
106
return
4;
107
}
catch
(...) {
108
std::cerr <<
"[GPU sort] unknown exception"
<< std::endl;
109
return
5;
110
}
111
112
return
0;
113
}
gpu_interface.h
gpu_sort_hits_by_timestamp
int gpu_sort_hits_by_timestamp(void *hits, long long n_hits)
Definition
gpu_sort.cu:47
RawHitGPU
Definition
gpu_sort.cu:24
RawHitGPU::energy
uint16_t energy
Definition
gpu_sort.cu:27
RawHitGPU::timestamp
uint64_t timestamp
Definition
gpu_sort.cu:29
RawHitGPU::flags
uint32_t flags
Definition
gpu_sort.cu:30
RawHitGPU::_pad0
uint16_t _pad0
Definition
gpu_sort.cu:28
RawHitGPU::channel
uint16_t channel
Definition
gpu_sort.cu:26
RawHitGPU::board
uint16_t board
Definition
gpu_sort.cu:25
RawHitGPU::_pad1
uint32_t _pad1
Definition
gpu_sort.cu:31
tooling
gpu
gpu_sort.cu
Generated by
1.17.0