Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-07-26 08:22:08

0001 /** TRACCC library, part of the ACTS project (R&D line)
0002  *
0003  * (c) 2022-2026 CERN for the benefit of the ACTS project
0004  *
0005  * Mozilla Public License Version 2.0
0006  */
0007 
0008 // Local include(s).
0009 #include "traccc/clusterization/device/clusterization_algorithm.hpp"
0010 
0011 #include <limits>
0012 #include <stdexcept>
0013 
0014 namespace traccc::device {
0015 
0016 clusterization_algorithm::clusterization_algorithm(
0017     const traccc::memory_resource& mr, const vecmem::copy& cp,
0018     const config_type& config, std::unique_ptr<const Logger> logger)
0019     : messaging(std::move(logger)),
0020       algorithm_base{mr, cp},
0021       m_config{config},
0022       m_f_backup{m_config.backup_size(), mr.main},
0023       m_gf_backup{m_config.backup_size(), mr.main},
0024       m_backup_mutex{vecmem::make_unique_alloc<unsigned int>(mr.main)},
0025       m_adjc_backup{m_config.backup_size(), mr.main},
0026       m_adjv_backup{m_config.backup_size() * 4, mr.main} {
0027   if (config.max_partition_size() >
0028       static_cast<unsigned int>(std::numeric_limits<details::index_t>::max())) {
0029     throw std::domain_error(
0030         "Maximal partition size is too large for the chosen index type!");
0031   }
0032 
0033   copy().setup(m_f_backup)->wait();
0034   copy().setup(m_gf_backup)->wait();
0035   copy().setup(m_adjc_backup)->wait();
0036   copy().setup(m_adjv_backup)->wait();
0037   copy()
0038       .memset(vecmem::data::vector_view<unsigned int>{1, m_backup_mutex.get()},
0039               0)
0040       ->wait();
0041 }
0042 
0043 edm::measurement_collection::buffer clusterization_algorithm::operator()(
0044     const edm::silicon_cell_collection::const_view& cells,
0045     const detector_design_description::const_view& det_descr,
0046     const detector_conditions_description::const_view& det_cond) const {
0047   return this->operator()(cells, det_descr, det_cond,
0048                           clustering_discard_disjoint_set{});
0049 }
0050 
0051 edm::measurement_collection::buffer clusterization_algorithm::operator()(
0052     const edm::silicon_cell_collection::const_view& cells,
0053     const detector_design_description::const_view& det_descr,
0054     const detector_conditions_description::const_view& det_cond,
0055     clustering_discard_disjoint_set&&) const {
0056   static constexpr bool KEEP_DISJOINT_SET = false;
0057   auto [res, djs] =
0058       this->execute_impl(cells, det_descr, det_cond, KEEP_DISJOINT_SET);
0059   assert(!djs.has_value());
0060   return std::move(res);
0061 }
0062 
0063 std::pair<edm::measurement_collection::buffer,
0064           edm::silicon_cluster_collection::buffer>
0065 clusterization_algorithm::operator()(
0066     const edm::silicon_cell_collection::const_view& cells,
0067     const detector_design_description::const_view& det_descr,
0068     const detector_conditions_description::const_view& det_cond,
0069     clustering_keep_disjoint_set&&) const {
0070   static constexpr bool KEEP_DISJOINT_SET = true;
0071   auto [res, djs] =
0072       this->execute_impl(cells, det_descr, det_cond, KEEP_DISJOINT_SET);
0073   assert(djs.has_value());
0074   return {std::move(res), std::move(*djs)};
0075 }
0076 
0077 std::pair<edm::measurement_collection::buffer,
0078           std::optional<edm::silicon_cluster_collection::buffer>>
0079 clusterization_algorithm::execute_impl(
0080     const edm::silicon_cell_collection::const_view& cells,
0081     const detector_design_description::const_view& det_descr,
0082     const detector_conditions_description::const_view& det_cond,
0083     bool keep_disjoint_set) const {
0084   // Check the input data in debug mode.
0085   assert(input_is_contiguous(cells));
0086 
0087   // Get the number of cells, in an asynchronous way if possible.
0088   edm::silicon_cell_collection::const_view::size_type num_cells = 0u;
0089   if (mr().host) {
0090     const vecmem::async_size size = copy().get_size(cells, *(mr().host));
0091     // Here we could give control back to the caller, once our code allows
0092     // for it. (coroutines...)
0093     num_cells = size.get();
0094   } else {
0095     num_cells = copy().get_size(cells);
0096   }
0097 
0098   // If there are no cells, return right away.
0099   if (num_cells == 0) {
0100     if (keep_disjoint_set) {
0101       return {edm::measurement_collection::buffer{},
0102               edm::silicon_cluster_collection::buffer{}};
0103     } else {
0104       return {};
0105     }
0106   }
0107 
0108   // Create the result object, overestimating the number of measurements.
0109   edm::measurement_collection::buffer measurements{
0110       num_cells, mr().main, vecmem::data::buffer_type::resizable};
0111   copy().setup(measurements)->ignore();
0112 
0113   // Ensure that the chosen maximum cell count is compatible with the maximum
0114   // stack size.
0115   assert(m_config.max_cells_per_thread <=
0116          device::details::CELLS_PER_THREAD_STACK_LIMIT);
0117 
0118   // If we are keeping the disjoint set data structure, allocate space for it.
0119   vecmem::data::vector_buffer<unsigned int> disjoint_set;
0120   vecmem::data::vector_buffer<unsigned int> cluster_sizes;
0121   if (keep_disjoint_set) {
0122     disjoint_set = {num_cells, mr().main};
0123     cluster_sizes = {num_cells, mr().main};
0124   }
0125 
0126   std::optional<edm::silicon_cell_collection::buffer> sorted_cells;
0127   vecmem::data::vector_buffer<unsigned int> permutation_map_buffer;
0128   edm::silicon_cell_collection::const_view sorted_cells_view;
0129 
0130   if (m_config.sort_cells) {
0131     sorted_cells = edm::silicon_cell_collection::buffer(num_cells, mr().main);
0132     copy().setup(*sorted_cells)->ignore();
0133     // The permutation map contents are only needed to reify the cluster
0134     // data, but the buffer is allocated unconditionally because
0135     // implementations may use it as scratch space while sorting.
0136     permutation_map_buffer =
0137         vecmem::data::vector_buffer<unsigned int>(num_cells, mr().main);
0138     copy().setup(permutation_map_buffer)->ignore();
0139 
0140     sort_cells_kernel(num_cells, cells, *sorted_cells, permutation_map_buffer,
0141                       keep_disjoint_set);
0142     sorted_cells_view = edm::silicon_cell_collection::const_view(*sorted_cells);
0143   } else {
0144     sorted_cells_view = edm::silicon_cell_collection::const_view(cells);
0145   }
0146 
0147   // Sorting must preserve module contiguity; a violation here indicates a
0148   // defect in the sorting kernel (e.g. key construction), which the
0149   // ordering check alone cannot detect.
0150   assert(input_is_contiguous(sorted_cells_view));
0151   assert(input_is_sorted(sorted_cells_view));
0152 
0153   // Launch the CCL kernel.
0154   ccl_kernel({num_cells, m_config, sorted_cells_view, det_descr, det_cond,
0155               measurements, m_f_backup, m_gf_backup, m_adjc_backup,
0156               m_adjv_backup, m_backup_mutex.get(), disjoint_set,
0157               cluster_sizes});
0158 
0159   std::optional<edm::silicon_cluster_collection::buffer> cluster_data =
0160       std::nullopt;
0161 
0162   // Create the cluster data if requested.
0163   if (keep_disjoint_set) {
0164     // Get the number of reconstructed measurements, in an asynchronous way
0165     // if possible.
0166     edm::measurement_collection::buffer::size_type num_measurements = 0u;
0167     if (mr().host) {
0168       const vecmem::async_size size =
0169           copy().get_size(measurements, *(mr().host));
0170       // Here we could give control back to the caller, once our code
0171       // allows for it. (coroutines...)
0172       num_measurements = size.get();
0173     } else {
0174       num_measurements = copy().get_size(measurements);
0175     }
0176 
0177     // This could be further optimized by only copying the number of
0178     // elements necessary. But since cluster making is mainly meant for
0179     // performance measurements, on first order this should be good enough.
0180     vecmem::vector<unsigned int> cluster_sizes_host =
0181         ((mr().host != nullptr) ? vecmem::vector<unsigned int>(mr().host)
0182                                 : vecmem::vector<unsigned int>());
0183     copy()(cluster_sizes, cluster_sizes_host)->wait();
0184     cluster_sizes_host.resize(num_measurements);
0185 
0186     // Create the result cluster collection.
0187     cluster_data.emplace(cluster_sizes_host, mr().main, mr().host,
0188                          vecmem::data::buffer_type::resizable);
0189     copy().setup(*cluster_data)->ignore();
0190 
0191     // Run the cluster data reification kernel.
0192     cluster_maker_kernel(num_cells, disjoint_set, *cluster_data,
0193                          permutation_map_buffer);
0194   }
0195 
0196   // Return the reconstructed measurements.
0197   return {std::move(measurements), std::move(cluster_data)};
0198 }
0199 
0200 }  // namespace traccc::device