Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
SeedFinder.ipp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file SeedFinder.ipp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2023 CERN for the benefit of the Acts project
4 //
5 // This Source Code Form is subject to the terms of the Mozilla Public
6 // License, v. 2.0. If a copy of the MPL was not distributed with this
7 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 
9 #pragma once
10 
11 // CUDA plugin include(s).
19 
20 // Acts include(s).
24 
25 // System include(s).
26 #include <cstring>
27 #include <vector>
28 
29 namespace Acts {
30 namespace Cuda {
31 
32 template <typename external_spacepoint_t>
35  const Acts::SeedFinderOptions& seedFinderOptions,
36  const SeedFilterConfig& seedFilterConfig,
37  const TripletFilterConfig& tripletFilterConfig, int device,
38  std::unique_ptr<const Logger> incomingLogger)
39  : m_commonConfig(commonConfig),
40  m_seedFinderOptions(seedFinderOptions),
41  m_seedFilterConfig(seedFilterConfig),
42  m_tripletFilterConfig(tripletFilterConfig),
43  m_device(device),
44  m_logger(std::move(incomingLogger)) {
46  throw std::runtime_error(
47  "SeedFinderConfig not in ACTS internal units in "
48  "Cuda/Seeding2/SeedFinder");
50  throw std::runtime_error(
51  "SeedFinderConfig not in ACTS internal units in "
52  "Cuda/Seeding2/SeedFinder");
54  throw std::runtime_error(
55  "SeedFilterConfig not in ACTS internal units in "
56  "Cuda/Seeding2/SeedFinder");
57  if (std::isnan(m_commonConfig.deltaRMaxTopSP)) {
58  throw std::runtime_error("Value of deltaRMaxTopSP was not initialised");
59  }
60  if (std::isnan(m_commonConfig.deltaRMinTopSP)) {
61  throw std::runtime_error("Value of deltaRMinTopSP was not initialised");
62  }
63  if (std::isnan(m_commonConfig.deltaRMaxBottomSP)) {
64  throw std::runtime_error("Value of deltaRMaxBottomSP was not initialised");
65  }
66  if (std::isnan(m_commonConfig.deltaRMinBottomSP)) {
67  throw std::runtime_error("Value of deltaRMinBottomSP was not initialised");
68  }
69 
70  // Tell the user what CUDA device will be used by the object.
71  if (static_cast<std::size_t>(m_device) < Info::instance().devices().size()) {
72  ACTS_DEBUG("Will be using device:\n"
73  << Info::instance().devices()[m_device]);
74  } else {
75  ACTS_FATAL("Invalid CUDA device requested");
76  throw std::runtime_error("Invalid CUDA device requested");
77  }
78 }
79 
80 template <typename external_spacepoint_t>
81 template <typename sp_range_t>
82 std::vector<Seed<external_spacepoint_t>>
84  Acts::SpacePointData& spacePointData,
86  const sp_range_t& bottomSPs, const std::size_t middleSPs,
87  const sp_range_t& topSPs) const {
88  // Create an empty vector, to be returned already early on when no seeds can
89  // be constructed.
90  std::vector<Seed<external_spacepoint_t>> outputVec;
91 
92  //---------------------------------
93  // Matrix Flattening
94  //---------------------------------
95 
96  // Create more convenient vectors out of the space point containers.
97  auto spVecMaker = [&grid](const sp_range_t& spRange) {
98  std::vector<Acts::InternalSpacePoint<external_spacepoint_t>*> result;
99  for (std::size_t idx : spRange) {
100  auto& collection = grid.at(idx);
101  for (auto& sp : collection) {
102  result.push_back(sp.get());
103  }
104  }
105  return result;
106  };
107 
108  std::vector<Acts::InternalSpacePoint<external_spacepoint_t>*> bottomSPVec(
109  spVecMaker(bottomSPs));
110  std::vector<Acts::InternalSpacePoint<external_spacepoint_t>*> topSPVec(
111  spVecMaker(topSPs));
112 
113  std::vector<Acts::InternalSpacePoint<external_spacepoint_t>*> middleSPVec;
114  {
115  auto& collection = grid.at(middleSPs);
116  for (auto& sp : collection) {
117  middleSPVec.push_back(sp.get());
118  }
119  }
120 
121  // If either one of them is empty, we have nothing to find.
122  if ((middleSPVec.size() == 0) || (bottomSPVec.size() == 0) ||
123  (topSPVec.size() == 0)) {
124  return outputVec;
125  }
126 
127  // Create helper objects for storing information about the spacepoints on the
128  // host in single memory blobs.
129  auto bottomSPArray = make_host_array<Details::SpacePoint>(bottomSPVec.size());
130  auto middleSPArray = make_host_array<Details::SpacePoint>(middleSPVec.size());
131  auto topSPArray = make_host_array<Details::SpacePoint>(topSPVec.size());
132 
133  // Fill these memory blobs.
134  auto fillSPArray = [](Details::SpacePoint* array, const auto& spVec) {
135  for (std::size_t i = 0; i < spVec.size(); ++i) {
136  array[i].x = spVec[i]->x();
137  array[i].y = spVec[i]->y();
138  array[i].z = spVec[i]->z();
139  array[i].radius = spVec[i]->radius();
140  array[i].varianceR = spVec[i]->varianceR();
141  array[i].varianceZ = spVec[i]->varianceZ();
142  }
143  };
144  fillSPArray(bottomSPArray.get(), bottomSPVec);
145  fillSPArray(middleSPArray.get(), middleSPVec);
146  fillSPArray(topSPArray.get(), topSPVec);
147 
148  // Copy the memory blobs to the device.
149  auto bottomSPDeviceArray =
150  make_device_array<Details::SpacePoint>(bottomSPVec.size());
151  auto middleSPDeviceArray =
152  make_device_array<Details::SpacePoint>(middleSPVec.size());
153  auto topSPDeviceArray =
154  make_device_array<Details::SpacePoint>(topSPVec.size());
155  copyToDevice(bottomSPDeviceArray, bottomSPArray, bottomSPVec.size());
156  copyToDevice(middleSPDeviceArray, middleSPArray, middleSPVec.size());
157  copyToDevice(topSPDeviceArray, topSPArray, topSPVec.size());
158 
159  //---------------------------------
160  // GPU Execution
161  //---------------------------------
162 
163  // Matrices holding the counts of the viable bottom-middle and middle-top
164  // pairs.
165  auto dubletCountsHost = make_host_array<unsigned int>(middleSPVec.size());
166  memset(dubletCountsHost.get(), 0, middleSPVec.size() * sizeof(unsigned int));
167  auto middleBottomCounts = make_device_array<unsigned int>(middleSPVec.size());
168  copyToDevice(middleBottomCounts, dubletCountsHost, middleSPVec.size());
169  auto middleTopCounts = make_device_array<unsigned int>(middleSPVec.size());
170  copyToDevice(middleTopCounts, dubletCountsHost, middleSPVec.size());
171 
172  // Matrices holding the indices of the viable bottom-middle and middle-top
173  // pairs.
174  auto middleBottomDublets =
175  make_device_array<std::size_t>(middleSPVec.size() * bottomSPVec.size());
176  auto middleTopDublets =
177  make_device_array<std::size_t>(middleSPVec.size() * topSPVec.size());
178 
179  // Launch the dublet finding code.
181  m_commonConfig.maxBlockSize, bottomSPVec.size(), bottomSPDeviceArray,
182  middleSPVec.size(), middleSPDeviceArray, topSPVec.size(),
183  topSPDeviceArray, m_commonConfig.deltaRMin, m_commonConfig.deltaRMax,
184  m_commonConfig.cotThetaMax, m_commonConfig.collisionRegionMin,
185  m_commonConfig.collisionRegionMax, middleBottomCounts,
186  middleBottomDublets, middleTopCounts, middleTopDublets);
187 
188  // Count the number of dublets that we have to launch the subsequent steps
189  // for.
190  Details::DubletCounts dubletCounts =
191  Details::countDublets(m_commonConfig.maxBlockSize, middleSPVec.size(),
192  middleBottomCounts, middleTopCounts);
193 
194  // If no dublets/triplet candidates have been found, stop here.
195  if ((dubletCounts.nDublets == 0) || (dubletCounts.nTriplets == 0)) {
196  return outputVec;
197  }
198 
199  // Launch the triplet finding code on all of the previously found dublets.
200  auto tripletCandidates = Details::findTriplets(
201  Info::instance().devices()[m_device], m_commonConfig.maxBlockSize,
202  dubletCounts, m_seedFilterConfig, m_tripletFilterConfig,
203  bottomSPVec.size(), bottomSPDeviceArray, middleSPVec.size(),
204  middleSPDeviceArray, topSPVec.size(), topSPDeviceArray,
205  middleBottomCounts, middleBottomDublets, middleTopCounts,
206  middleTopDublets, m_commonConfig.maxScatteringAngle2,
207  m_commonConfig.sigmaScattering, m_seedFinderOptions.minHelixDiameter2,
208  m_seedFinderOptions.pT2perRadius, m_commonConfig.impactMax);
209  assert(tripletCandidates.size() == middleSPVec.size());
210 
211  // Perform the final step of the filtering.
212  std::size_t middleIndex = 0;
213  auto triplet_itr = tripletCandidates.begin();
214  auto triplet_end = tripletCandidates.end();
215  for (; triplet_itr != triplet_end; ++triplet_itr, ++middleIndex) {
216  std::vector<typename CandidatesForMiddleSp<
218  candidates;
219 
220  auto& middleSP = *(middleSPVec[middleIndex]);
221  for (const Details::Triplet& triplet : *triplet_itr) {
222  assert(triplet.bottomIndex < bottomSPVec.size());
223  auto& bottomSP = *(bottomSPVec[triplet.bottomIndex]);
224  assert(triplet.topIndex < topSPVec.size());
225  auto& topSP = *(topSPVec[triplet.topIndex]);
226  candidates.emplace_back(bottomSP, middleSP, topSP, triplet.weight, 0,
227  false);
228  }
229  std::sort(
230  candidates.begin(), candidates.end(),
232  descendingByQuality);
233  std::size_t numQualitySeeds = 0; // not used but needs to be fixed
234  m_commonConfig.seedFilter->filterSeeds_1SpFixed(
235  spacePointData, candidates, numQualitySeeds,
236  std::back_inserter(outputVec));
237  }
238 
239  // Free up all allocated device memory.
240  MemoryManager::instance().reset(m_device);
241 
242  // Return the collected spacepoints.
243  return outputVec;
244 }
245 
246 template <typename external_spacepoint_t>
248  std::unique_ptr<const Logger> newLogger) {
249  return m_logger.swap(newLogger);
250 }
251 
252 } // namespace Cuda
253 } // namespace Acts