Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-09 08:20:07

0001 // This file is part of the ACTS project.
0002 //
0003 // Copyright (C) 2016 CERN for the benefit of the ACTS project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
0008 
0009 #pragma once
0010 
0011 #include "Acts/Seeding/HoughTransformUtils.hpp"
0012 
0013 #include <cstddef>
0014 #include <cstdint>
0015 #include <span>
0016 #include <vector>
0017 
0018 #include <cuda_runtime.h>
0019 
0020 namespace ActsExamples {
0021 
0022 using YieldType = Acts::HoughTransformUtils::YieldType;
0023 using CoordType = Acts::HoughTransformUtils::CoordType;
0024 using LayerMask = unsigned long long;
0025 
0026 /// @brief Non-owning device-side view of a batch of Hough maxima.
0027 ///
0028 /// Maximum slots are stored bucket-by-bucket:
0029 ///
0030 ///   bucket 0: maximum 0, maximum 1, ..., maximum N - 1
0031 ///   bucket 1: maximum 0, maximum 1, ..., maximum N - 1
0032 struct CudaHoughMaximumBatchArrays {
0033   CoordType* tanBeta = nullptr;
0034   CoordType* interceptY = nullptr;
0035 
0036   YieldType* nHits = nullptr;
0037   YieldType* nLayers = nullptr;
0038   LayerMask* layerMask = nullptr;
0039 
0040   std::uint32_t* xBin = nullptr;
0041   std::uint32_t* yBin = nullptr;
0042 
0043   /// Number of occupied maximum slots in each bucket.
0044   std::uint32_t* nMaxima = nullptr;
0045 
0046   /// Number of input space points associated with each maximum.
0047   std::uint32_t* nAssociatedHits = nullptr;
0048 
0049   /// CSR offsets into associatedHitIndices.
0050   /// Maximum slot i owns [associatedHitOffsets[i], associatedHitOffsets[i+1])
0051   /// Array as max capacity + 1
0052   std::uint32_t* associatedHitOffsets = nullptr;
0053 
0054   /// Flat list of indices into CudaMuonSpacePointContainer.
0055   std::uint32_t* associatedHitIndices = nullptr;
0056 
0057   std::uint32_t nBuckets = 0;
0058   std::uint32_t capacityPerBucket = 0;
0059   /// Full size of the associated-hit list.
0060   std::uint32_t totalAssociatedHits = 0;
0061 
0062   /// Return the flat array index for a bucket and maximum slot.
0063   __host__ __device__ std::uint32_t index(
0064       std::uint32_t bucket, std::uint32_t maximum) const noexcept {
0065     return bucket * capacityPerBucket + maximum;
0066   }
0067 };
0068 
0069 /// @brief Owning host/device storage for Hough-maximum slots per bucket.
0070 ///
0071 /// The capacity per bucket specifies the maximum number of maxima that may be
0072 /// stored for each bucket. The actual number stored is tracked independently
0073 /// by the nMaxima counter for each bucket.
0074 class CudaHoughMaximumBatch {
0075  public:
0076   using size_type = std::size_t;
0077 
0078   CudaHoughMaximumBatch(size_type nBuckets, size_type capacityPerBucket);
0079 
0080   /// Copy creates problem with cuda memory ownership
0081   CudaHoughMaximumBatch(const CudaHoughMaximumBatch&) = delete;
0082   CudaHoughMaximumBatch& operator=(const CudaHoughMaximumBatch&) = delete;
0083 
0084   CudaHoughMaximumBatch(CudaHoughMaximumBatch&& other) noexcept;
0085   CudaHoughMaximumBatch& operator=(CudaHoughMaximumBatch&& other) noexcept;
0086 
0087   ~CudaHoughMaximumBatch() noexcept;
0088 
0089   size_type capacityPerBucket() const noexcept { return m_capacityPerBucket; }
0090 
0091   size_type nBuckets() const noexcept { return m_nBuckets; }
0092 
0093   size_type totalCapacity() const noexcept {
0094     return nBuckets() * capacityPerBucket();
0095   }
0096 
0097   bool empty() const noexcept { return nBuckets() == 0; }
0098 
0099   /// Return the number of stored maxima in one bucket.
0100   size_type nMaxima(size_type bucket) const;
0101 
0102   CoordType tanBeta(size_type bucket, size_type maximum) const;
0103   CoordType interceptY(size_type bucket, size_type maximum) const;
0104 
0105   YieldType nHits(size_type bucket, size_type maximum) const;
0106   YieldType nLayers(size_type bucket, size_type maximum) const;
0107 
0108   LayerMask layerMask(size_type bucket, size_type maximum) const;
0109 
0110   size_type xBin(size_type bucket, size_type maximum) const;
0111   size_type yBin(size_type bucket, size_type maximum) const;
0112 
0113   /// Copy only the metadata required to allocate hit-association storage.
0114   ///
0115   /// Copies nMaxima and nAssociatedHits from the device.
0116   void copyAssociationMetadataToHost(cudaStream_t stream);
0117 
0118   /// Calculate CSR offsets from the copied association counts and allocate
0119   /// exact associated-hit storage on the device.
0120   void allocateAssociationStorage(cudaStream_t stream);
0121 
0122   /// Copy the associated space-point indices from the device to the host.
0123   ///
0124   /// This is called after the association-fill kernel has completed.
0125   void copyAssociatedHitIndicesToHost(cudaStream_t stream);
0126 
0127   /// Return the number of associated input space points for one maximum.
0128   size_type nAssociatedHits(size_type bucket, size_type maximum) const;
0129 
0130   /// Return all original space-point indices associated with one maximum.
0131   std::span<const std::uint32_t> associatedHitIndices(size_type bucket,
0132                                                       size_type maximum) const;
0133 
0134   /// Return the total exact size of associatedHitIndices.
0135   size_type totalAssociatedHits() const noexcept {
0136     return m_hostAssociatedHitIndices.size();
0137   }
0138 
0139   bool hasAssociationStorage() const noexcept {
0140     return m_associationStorageAllocated;
0141   }
0142 
0143   /// Allocate device output storage for use on the supplied stream.
0144   void moveToDevice(cudaStream_t stream);
0145 
0146   /// Copy device data back into host storage.
0147   void moveToHost(cudaStream_t stream);
0148 
0149   /// Release all owned device storage.
0150   void clearDevice() noexcept;
0151 
0152   bool isOnDevice() const noexcept { return m_onDevice; }
0153 
0154   CudaHoughMaximumBatchArrays deviceArrays() const noexcept { return m_device; }
0155 
0156  private:
0157   size_type m_nBuckets = 0;
0158   size_type m_capacityPerBucket = 0;
0159 
0160   std::vector<CoordType> m_hostTanBeta{};
0161   std::vector<CoordType> m_hostInterceptY{};
0162 
0163   std::vector<YieldType> m_hostHits{};
0164   std::vector<YieldType> m_hostLayers{};
0165   std::vector<LayerMask> m_hostLayerMask{};
0166 
0167   std::vector<std::uint32_t> m_hostXBin{};
0168   std::vector<std::uint32_t> m_hostYBin{};
0169 
0170   /// One counter per bucket, not one counter per maximum slot.
0171   std::vector<std::uint32_t> m_hostNMaxima{};
0172 
0173   /// One exact association count per maximum slot.
0174   std::vector<std::uint32_t> m_hostNAssociatedHits{};
0175 
0176   /// CSR offsets. Size is totalCapacity() + 1 after allocation.
0177   std::vector<std::uint32_t> m_hostAssociatedHitOffsets{};
0178 
0179   /// Exact flat associated-hit storage.
0180   std::vector<std::uint32_t> m_hostAssociatedHitIndices{};
0181 
0182   /// Whether nMaxima and nAssociatedHits have been copied from the device.
0183   bool m_associationMetadataOnHost = false;
0184 
0185   /// Whether exact device-side offsets and index storage have been allocated.
0186   bool m_associationStorageAllocated = false;
0187 
0188   /// Whether the final associated indices have been copied back to the host.
0189   bool m_associatedHitIndicesOnHost = false;
0190 
0191   CudaHoughMaximumBatchArrays m_device{};
0192   bool m_onDevice = false;
0193 
0194   size_type slotIndex(size_type bucket, size_type maximum) const noexcept {
0195     return bucket * capacityPerBucket() + maximum;
0196   }
0197 
0198   void checkBucket(size_type bucket) const;
0199   void checkMaximum(size_type bucket, size_type maximum) const;
0200 
0201   /// Build host-side CSR offsets and resize the exact hit-index storage.
0202   void prepareAssociationStorageHost();
0203 
0204   /// Release only the variable-size association offset/index storage.
0205   void clearAssociationStorage() noexcept;
0206 };
0207 
0208 }  // namespace ActsExamples