File indexing completed on 2026-07-26 08:22:05
0001
0002
0003
0004
0005
0006
0007
0008 #pragma once
0009
0010 #include <mutex>
0011
0012 #include <vecmem/memory/device_atomic_ref.hpp>
0013
0014 #include "traccc/clusterization/clustering_config.hpp"
0015 #include "traccc/clusterization/device/aggregate_cluster.hpp"
0016 #include "traccc/clusterization/device/ccl_kernel_definitions.hpp"
0017 #include "traccc/clusterization/device/reduce_problem_cell.hpp"
0018 #include "traccc/device/concepts/barrier.hpp"
0019 #include "traccc/device/concepts/thread_id.hpp"
0020 #include "traccc/device/mutex.hpp"
0021 #include "traccc/device/unique_lock.hpp"
0022 #include "traccc/edm/silicon_cell_collection.hpp"
0023
0024 namespace traccc::device {
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046 template <device::concepts::barrier barrier_t,
0047 device::concepts::thread_id1 thread_id_t, typename index_t>
0048 TRACCC_HOST_DEVICE void fast_sv_1(const thread_id_t& thread_id,
0049 vecmem::device_vector<index_t>& f,
0050 vecmem::device_vector<index_t>& gf,
0051 unsigned char* adjc, index_t* adjv,
0052 unsigned int thread_cell_count,
0053 barrier_t& barrier) {
0054
0055
0056
0057
0058
0059 bool gf_changed;
0060
0061 do {
0062
0063
0064
0065
0066 gf_changed = false;
0067
0068
0069
0070
0071
0072
0073
0074
0075 for (unsigned int tst = 0; tst < thread_cell_count; ++tst) {
0076 const unsigned int cid =
0077 tst * thread_id.getBlockDimX() + thread_id.getLocalThreadIdX();
0078
0079 TRACCC_ASSUME(adjc[tst] <= 4);
0080 for (unsigned char k = 0; k < adjc[tst]; ++k) {
0081 const auto cid2 = adjv[4 * tst + k];
0082
0083 index_t q2 = gf.at(cid2);
0084 index_t q1 = gf.at(cid);
0085
0086 if (gf.at(cid) > q2) {
0087 f.at(f.at(cid)) = q2;
0088 f.at(cid) = q2;
0089 }
0090 if (gf.at(cid2) > q1) {
0091 f.at(f.at(cid2)) = q1;
0092 f.at(cid2) = q1;
0093 }
0094 }
0095 }
0096
0097
0098
0099
0100
0101 barrier.blockBarrier();
0102
0103 for (unsigned int tst = 0; tst < thread_cell_count; ++tst) {
0104 const unsigned int cid =
0105 tst * thread_id.getBlockDimX() + thread_id.getLocalThreadIdX();
0106
0107
0108
0109
0110
0111 if (f.at(cid) > gf.at(cid)) {
0112 f.at(cid) = gf.at(cid);
0113 }
0114 }
0115
0116
0117
0118
0119 barrier.blockBarrier();
0120
0121 for (unsigned int tst = 0; tst < thread_cell_count; ++tst) {
0122 const unsigned int cid =
0123 tst * thread_id.getBlockDimX() + thread_id.getLocalThreadIdX();
0124
0125
0126
0127
0128 if (gf.at(cid) != f.at(f.at(cid))) {
0129 gf.at(cid) = f.at(f.at(cid));
0130 gf_changed = true;
0131 }
0132 }
0133
0134
0135
0136
0137
0138
0139
0140
0141 } while (barrier.blockOr(gf_changed));
0142 }
0143
0144 template <device::concepts::barrier barrier_t,
0145 device::concepts::thread_id1 thread_id_t, typename index_t>
0146 TRACCC_HOST_DEVICE inline void ccl_core(
0147 const clustering_config& cfg, const thread_id_t& thread_id,
0148 std::size_t& partition_start, std::size_t& partition_end,
0149 vecmem::device_vector<index_t> f, vecmem::device_vector<index_t> gf,
0150 index_t* adjv, unsigned char* adjc,
0151 const edm::silicon_cell_collection::const_device& cells_device,
0152 const detector_design_description::const_device& det_desc,
0153 const detector_conditions_description::const_device& det_cond,
0154 edm::measurement_collection::device measurements_device,
0155 const barrier_t& barrier, vecmem::device_vector<unsigned int>& disjoint_set,
0156 vecmem::device_vector<unsigned int>& cluster_size) {
0157 const auto size = static_cast<unsigned int>(partition_end - partition_start);
0158
0159 assert(size <= f.size());
0160 assert(size <= gf.size());
0161
0162 const unsigned int thread_cell_count =
0163 (size - thread_id.getLocalThreadIdX() + thread_id.getBlockDimX() - 1) /
0164 thread_id.getBlockDimX();
0165
0166 for (unsigned int tst = 0; tst < thread_cell_count; ++tst) {
0167
0168
0169
0170 const unsigned int cid =
0171 tst * thread_id.getBlockDimX() + thread_id.getLocalThreadIdX();
0172 adjc[tst] = 0;
0173
0174 reduce_problem_cell(
0175 cells_device, cid, static_cast<unsigned int>(partition_start),
0176 static_cast<unsigned int>(partition_end), adjc[tst], &adjv[4 * tst]);
0177
0178 f.at(cid) = static_cast<index_t>(cid);
0179 gf.at(cid) = static_cast<index_t>(cid);
0180 }
0181
0182
0183
0184
0185
0186 barrier.blockBarrier();
0187
0188
0189
0190
0191
0192 fast_sv_1(thread_id, f, gf, adjc, adjv, thread_cell_count, barrier);
0193
0194 barrier.blockBarrier();
0195
0196
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210
0211
0212
0213
0214
0215
0216
0217
0218
0219
0220
0221
0222 for (unsigned int i = thread_id.getLocalThreadIdX(); i < size;
0223 i += thread_id.getBlockDimX()) {
0224 gf.at(i) = static_cast<index_t>(partition_end - partition_start);
0225 }
0226
0227 barrier.blockBarrier();
0228
0229
0230
0231
0232
0233
0234 for (unsigned int i = thread_id.getLocalThreadIdX(); i < size;
0235 i += thread_id.getBlockDimX()) {
0236 const index_t effi =
0237 static_cast<index_t>((partition_end - partition_start) - (i + 1));
0238
0239 const auto fid = f.at(effi);
0240
0241 if (fid != effi) {
0242 for (unsigned int j = effi - 1; j < size; --j) {
0243 if (fid == f.at(j)) {
0244 gf.at(j) = effi;
0245 break;
0246 }
0247 }
0248 }
0249 }
0250
0251 barrier.blockBarrier();
0252
0253 for (details::index_t tst = 0; tst < thread_cell_count; ++tst) {
0254 const auto cid = static_cast<details::index_t>(
0255 tst * thread_id.getBlockDimX() + thread_id.getLocalThreadIdX());
0256
0257 if (f.at(cid) == cid) {
0258
0259
0260 const edm::measurement_collection::device::size_type meas_pos =
0261 measurements_device.push_back_default();
0262
0263 aggregate_cluster(
0264 cfg, cells_device, det_desc, det_cond, gf,
0265 static_cast<unsigned int>(partition_start),
0266 static_cast<unsigned int>(partition_end), cid,
0267 measurements_device.at(meas_pos), meas_pos, disjoint_set,
0268 (cluster_size.capacity()
0269 ? std::optional<
0270 std::reference_wrapper<unsigned int>>{cluster_size.at(
0271 meas_pos)}
0272 : std::nullopt));
0273 }
0274 }
0275 }
0276
0277 template <device::concepts::barrier barrier_t,
0278 device::concepts::thread_id1 thread_id_t>
0279 TRACCC_HOST_DEVICE inline void ccl_kernel(
0280 const clustering_config cfg, const thread_id_t& thread_id,
0281 const edm::silicon_cell_collection::const_view& cells_view,
0282 const detector_design_description::const_view& det_desc_view,
0283 const detector_conditions_description::const_view& det_cond_view,
0284 std::size_t& partition_start, std::size_t& partition_end, std::size_t& outi,
0285 vecmem::data::vector_view<details::index_t> f_view,
0286 vecmem::data::vector_view<details::index_t> gf_view,
0287 vecmem::data::vector_view<details::fallback_index_t> f_backup_view,
0288 vecmem::data::vector_view<details::fallback_index_t> gf_backup_view,
0289 vecmem::data::vector_view<unsigned char> adjc_backup_view,
0290 vecmem::data::vector_view<details::fallback_index_t> adjv_backup_view,
0291 vecmem::device_atomic_ref<uint32_t> backup_mutex,
0292 vecmem::data::vector_view<unsigned int> disjoint_set_view,
0293 vecmem::data::vector_view<unsigned int> cluster_size_view,
0294 const barrier_t& barrier,
0295 edm::measurement_collection::view measurements_view) {
0296
0297 const edm::silicon_cell_collection::const_device cells_device(cells_view);
0298 const detector_design_description::const_device det_desc(det_desc_view);
0299 const detector_conditions_description::const_device det_cond(det_cond_view);
0300 edm::measurement_collection::device measurements_device(measurements_view);
0301 vecmem::device_vector<details::index_t> f_primary(f_view);
0302 vecmem::device_vector<details::index_t> gf_primary(gf_view);
0303 vecmem::device_vector<details::fallback_index_t> f_backup(f_backup_view);
0304 vecmem::device_vector<details::fallback_index_t> gf_backup(gf_backup_view);
0305 vecmem::device_vector<unsigned char> adjc_backup(adjc_backup_view);
0306 vecmem::device_vector<details::fallback_index_t> adjv_backup(
0307 adjv_backup_view);
0308 vecmem::device_vector<unsigned int> disjoint_set(disjoint_set_view);
0309 vecmem::device_vector<unsigned int> cluster_size(cluster_size_view);
0310
0311 mutex<uint32_t> mutex(backup_mutex);
0312 unique_lock lock(mutex, std::defer_lock);
0313
0314 const unsigned int num_cells = cells_device.size();
0315
0316
0317
0318
0319
0320
0321
0322
0323
0324 if (thread_id.getLocalThreadIdX() == 0) {
0325 unsigned int start = thread_id.getBlockIdX() * cfg.target_partition_size();
0326 assert(start < num_cells);
0327 unsigned int end = std::min(num_cells, start + cfg.target_partition_size());
0328 outi = 0;
0329
0330
0331
0332
0333
0334
0335
0336 while (start != 0 && start < num_cells &&
0337 cells_device.module_index().at(start - 1) ==
0338 cells_device.module_index().at(start) &&
0339 cells_device.channel1().at(start) <=
0340 cells_device.channel1().at(start - 1) + 1) {
0341 ++start;
0342 }
0343
0344
0345
0346
0347
0348
0349 while (end < num_cells &&
0350 cells_device.module_index().at(end - 1) ==
0351 cells_device.module_index().at(end) &&
0352 cells_device.channel1().at(end) <=
0353 cells_device.channel1().at(end - 1) + 1) {
0354 ++end;
0355 }
0356 partition_start = start;
0357 partition_end = end;
0358 assert(partition_start <= partition_end);
0359 }
0360
0361 barrier.blockBarrier();
0362
0363
0364
0365
0366
0367
0368 const auto size = static_cast<unsigned int>(partition_end - partition_start);
0369
0370
0371 if (size == 0) {
0372 return;
0373 }
0374
0375
0376
0377
0378
0379
0380
0381
0382
0383 if (size > cfg.max_partition_size()) [[unlikely]] {
0384 if (thread_id.getLocalThreadIdX() == 0) {
0385 lock.lock();
0386 }
0387
0388 barrier.blockBarrier();
0389
0390 unsigned char* adjc = adjc_backup.data() + (thread_id.getLocalThreadIdX() *
0391 cfg.max_cells_per_thread *
0392 cfg.backup_size_multiplier);
0393 details::fallback_index_t* adjv =
0394 adjv_backup.data() +
0395 (thread_id.getLocalThreadIdX() * 4 * cfg.max_cells_per_thread *
0396 cfg.backup_size_multiplier);
0397 ccl_core(cfg, thread_id, partition_start, partition_end, f_backup,
0398 gf_backup, adjv, adjc, cells_device, det_desc, det_cond,
0399 measurements_device, barrier, disjoint_set, cluster_size);
0400 } else {
0401
0402
0403
0404 details::index_t adjv[details::CELLS_PER_THREAD_STACK_LIMIT * 4];
0405
0406
0407
0408
0409
0410
0411
0412 unsigned char adjc[details::CELLS_PER_THREAD_STACK_LIMIT];
0413
0414 ccl_core(cfg, thread_id, partition_start, partition_end, f_primary,
0415 gf_primary, adjv, adjc, cells_device, det_desc, det_cond,
0416 measurements_device, barrier, disjoint_set, cluster_size);
0417 }
0418
0419 barrier.blockBarrier();
0420 }
0421 }