File indexing completed on 2026-07-26 08:22:09
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "traccc/definitions/qualifiers.hpp"
0010
0011
0012 #include "../../utils/global_index.hpp"
0013 #include "rearrange_tracks.cuh"
0014
0015
0016 #include <vecmem/containers/device_vector.hpp>
0017
0018 namespace traccc::cuda::kernels {
0019
0020 TRACCC_DEVICE inline bool find_valid_index(
0021 unsigned int& idx, const int lower_bound, const int upper_bound,
0022 const vecmem::device_vector<const unsigned int>& sorted_ids,
0023 const vecmem::device_vector<const int>& is_updated) {
0024 const auto initial_idx = idx;
0025
0026 for (int i = initial_idx; i <= upper_bound; i++) {
0027 if (!is_updated[sorted_ids[i]]) {
0028 idx = i;
0029 return true;
0030 }
0031 }
0032
0033 for (int i = initial_idx - 1; i >= lower_bound; i--) {
0034 if (!is_updated[sorted_ids[i]]) {
0035 idx = i;
0036 return true;
0037 }
0038 }
0039
0040 return false;
0041 }
0042
0043 __launch_bounds__(1024) __global__
0044 void rearrange_tracks(device::rearrange_tracks_payload payload) {
0045 if (*(payload.terminate) == 1 || *(payload.n_updated_tracks) == 0) {
0046 return;
0047 }
0048
0049 auto gid = threadIdx.x / nThreads_per_track +
0050 blockIdx.x * (blockDim.x / nThreads_per_track);
0051 const unsigned int n_accepted = *(payload.n_accepted);
0052
0053 auto N = *(payload.n_updated_tracks);
0054
0055 int neff_threads = (N + nThreads_per_track - 1) / nThreads_per_track;
0056
0057 if (neff_threads > nThreads_per_track) {
0058 neff_threads = nThreads_per_track;
0059 }
0060
0061 bool is_valid_thread = true;
0062 if (threadIdx.x % nThreads_per_track >= neff_threads || gid >= n_accepted) {
0063 is_valid_thread = false;
0064 }
0065
0066 vecmem::device_vector<const unsigned int> sorted_ids(payload.sorted_ids_view);
0067 vecmem::device_vector<const unsigned int> inverted_ids(
0068 payload.inverted_ids_view);
0069 vecmem::device_vector<const traccc::scalar> rel_shared(
0070 payload.rel_shared_view);
0071 vecmem::device_vector<const traccc::scalar> pvals(payload.pvals_view);
0072 vecmem::device_vector<const unsigned int> updated_tracks(
0073 payload.updated_tracks_view);
0074 vecmem::device_vector<const int> is_updated(payload.is_updated_view);
0075 vecmem::device_vector<const int> prefix_sums(payload.prefix_sums_view);
0076 vecmem::device_vector<unsigned int> temp_sorted_ids(
0077 payload.temp_sorted_ids_view);
0078
0079 __shared__ int shifted_indices[1024];
0080 auto& shifted_idx = shifted_indices[threadIdx.x / nThreads_per_track];
0081 unsigned int tid = std::numeric_limits<unsigned int>::max();
0082
0083 if (is_valid_thread) {
0084 tid = sorted_ids[gid];
0085 auto rel_sh_ref = rel_shared[tid];
0086 auto pval_ref = pvals[tid];
0087
0088 shifted_idx = static_cast<int>(gid);
0089
0090 int stride = (N + neff_threads - 1) / neff_threads;
0091
0092 int ini_idx = stride * (threadIdx.x % nThreads_per_track);
0093 int fin_idx = std::min(ini_idx + stride, static_cast<int>(N));
0094
0095
0096
0097
0098 if (is_updated[tid]) {
0099 if (gid > 0) {
0100 unsigned int left = 0;
0101 unsigned int right = gid;
0102
0103 bool first_iteration = true;
0104
0105 if (threadIdx.x % nThreads_per_track == 0) {
0106 while (right > left) {
0107 const bool find_left =
0108 find_valid_index(left, 0, gid, sorted_ids, is_updated);
0109
0110 if (!find_left) {
0111 break;
0112 }
0113
0114 const bool find_right =
0115 find_valid_index(right, 0, gid, sorted_ids, is_updated);
0116
0117 if (!find_right) {
0118 break;
0119 }
0120
0121 if (first_iteration) {
0122 const auto right_idx = sorted_ids[right];
0123 auto rel_sh = rel_shared[right_idx];
0124 auto pval = pvals[right_idx];
0125
0126 if (rel_sh < rel_sh_ref ||
0127 (rel_sh == rel_sh_ref && pval >= pval_ref)) {
0128 left = gid;
0129 break;
0130 }
0131 }
0132
0133 first_iteration = false;
0134
0135 unsigned int mid = left + (right - left) / 2;
0136
0137 const bool find_mid =
0138 find_valid_index(mid, left, right - 1, sorted_ids, is_updated);
0139
0140 if (find_mid) {
0141 const auto mid_idx = sorted_ids[mid];
0142 auto rel_sh = rel_shared[mid_idx];
0143 auto pval = pvals[mid_idx];
0144
0145 if (rel_sh < rel_sh_ref ||
0146 (rel_sh == rel_sh_ref && pval >= pval_ref)) {
0147 left = mid + 1;
0148 } else {
0149 right = mid;
0150 }
0151 }
0152 }
0153
0154 int delta = delta =
0155 gid - left - (prefix_sums[gid] - prefix_sums[left]);
0156
0157 if (!is_updated[sorted_ids[left]]) {
0158 delta++;
0159 }
0160
0161 atomicAdd(&shifted_idx, -delta);
0162 }
0163 }
0164
0165 for (int i = ini_idx; i < fin_idx; i++) {
0166 auto id = updated_tracks[i];
0167
0168 if (inverted_ids[id] < gid) {
0169 atomicAdd(&shifted_idx, -1);
0170 }
0171 }
0172
0173 int offset = 0;
0174 for (int i = ini_idx; i < fin_idx; i++) {
0175 if (updated_tracks[i] == tid) {
0176 offset = i;
0177 break;
0178 }
0179 }
0180 if (offset != 0) {
0181 atomicAdd(&shifted_idx, offset);
0182 }
0183 }
0184
0185
0186 else {
0187 for (int i = ini_idx; i < fin_idx; i++) {
0188 auto id = updated_tracks[i];
0189 auto rel_sh = rel_shared[id];
0190 auto pval = pvals[id];
0191
0192 if (inverted_ids[id] > gid) {
0193 if (rel_sh < rel_sh_ref) {
0194 atomicAdd(&shifted_idx, 1);
0195 } else if (rel_sh == rel_sh_ref && pval > pval_ref) {
0196 atomicAdd(&shifted_idx, 1);
0197 }
0198 }
0199 }
0200 }
0201 }
0202
0203 __syncthreads();
0204
0205
0206 if (is_valid_thread && (threadIdx.x % nThreads_per_track) == 0) {
0207 temp_sorted_ids.at(shifted_idx) = tid;
0208 }
0209 }
0210
0211 }