EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
main.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file main.cpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2020 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 // Local include(s).
10 #include "CommandLineArguments.hpp"
11 #include "ReadSeedFile.hpp"
12 #include "TestDeviceCuts.hpp"
13 #include "TestHostCuts.hpp"
14 #include "TestSpacePoint.hpp"
15 
16 // CUDA plugin include(s).
18 
19 // Acts include(s).
25 
26 // System include(s).
27 #include <cassert>
28 #include <chrono>
29 #include <iomanip>
30 #include <iostream>
31 #include <iterator>
32 #include <memory>
33 
34 int main(int argc, char* argv[]) {
35  // Interpret the command line arguments passed to the executable.
37  cmdl.interpret(argc, argv);
38 
39  // Read in the seeds from the input text file.
40  auto spacepoints = readSeedFile(cmdl.spFile, cmdl.filterDuplicates);
41  std::cout << "Read " << spacepoints.size()
42  << " spacepoints from file: " << cmdl.spFile << std::endl;
43 
44  // Create a "view vector" on top of them. This is necessary to be able to pass
45  // the objects to the Acts code. While the return type of readSeedFile(...) is
46  // useful for simplified memory management...
47  std::vector<const TestSpacePoint*> spView;
48  spView.reserve(spacepoints.size());
49  for (const auto& sp : spacepoints) {
50  spView.push_back(sp.get());
51  }
52 
53  // Create binned groups of these spacepoints.
54  auto bottomBinFinder = std::make_shared<Acts::BinFinder<TestSpacePoint>>();
55  auto topBinFinder = std::make_shared<Acts::BinFinder<TestSpacePoint>>();
56 
57  // Set up the seedfinder configuration.
59  // silicon detector max
60  sfConfig.rMax = 160.;
61  sfConfig.deltaRMin = 5.;
62  sfConfig.deltaRMax = 160.;
63  sfConfig.collisionRegionMin = -250.;
64  sfConfig.collisionRegionMax = 250.;
65  sfConfig.zMin = -2800.;
66  sfConfig.zMax = 2800.;
67  sfConfig.maxSeedsPerSpM = 5;
68  // 2.7 eta
69  sfConfig.cotThetaMax = 7.40627;
70  sfConfig.sigmaScattering = 1.00000;
71  sfConfig.minPt = 500.;
72  sfConfig.bFieldInZ = 0.00199724;
73  sfConfig.beamPos = {-.5, -.5};
74  sfConfig.impactMax = 10.;
75 
76  // Use a size slightly smaller than what modern GPUs are capable of. This is
77  // because for debugging we can't use all available threads in a block, and
78  // because early testing shows that using this sort of block size results in
79  // better performance than using the maximal one. (It probably works better
80  // with the kind of branching that is present in the CUDA code.)
81  sfConfig.maxBlockSize = 256;
82 
83  // Set up the spacepoint grid configuration.
84  Acts::SpacePointGridConfig gridConfig;
85  gridConfig.bFieldInZ = sfConfig.bFieldInZ;
86  gridConfig.minPt = sfConfig.minPt;
87  gridConfig.rMax = sfConfig.rMax;
88  gridConfig.zMax = sfConfig.zMax;
89  gridConfig.zMin = sfConfig.zMin;
90  gridConfig.deltaRMax = sfConfig.deltaRMax;
91  gridConfig.cotThetaMax = sfConfig.cotThetaMax;
92 
93  // Covariance tool, sets covariances per spacepoint as required.
94  auto ct = [=](const TestSpacePoint& sp, float, float,
95  float) -> Acts::Vector2D {
96  return {sp.m_varianceR, sp.m_varianceZ};
97  };
98 
99  // Create a grid with bin sizes according to the configured geometry, and
100  // split the spacepoints into groups according to that grid.
101  auto grid =
102  Acts::SpacePointGridCreator::createGrid<TestSpacePoint>(gridConfig);
104  spView.begin(), spView.end(), ct, bottomBinFinder, topBinFinder,
105  std::move(grid), sfConfig);
106  // Make a convenient iterator that will be used multiple times later on.
107  auto spGroup_end = spGroup.end();
108 
109  // Set up the seedfinder configuration objects.
110  TestHostCuts hostCuts;
111  Acts::SeedFilterConfig filterConfig;
112  sfConfig.seedFilter = std::make_unique<Acts::SeedFilter<TestSpacePoint>>(
113  filterConfig, &hostCuts);
114  auto deviceCuts = testDeviceCuts();
115 
116  // Set up the seedfinder objects.
117  Acts::Seedfinder<TestSpacePoint> seedfinder_host(sfConfig);
118  Acts::Cuda::SeedFinder<TestSpacePoint> seedfinder_device(
119  sfConfig, filterConfig, deviceCuts);
120 
121  //
122  // Perform the seed finding on the host.
123  //
124 
125  // Record the start time.
126  auto start_host = std::chrono::system_clock::now();
127  // Create the result object.
128  std::vector<std::vector<Acts::Seed<TestSpacePoint>>> seeds_host;
129 
130  // Perform the seed finding.
131  if (!cmdl.onlyGPU) {
132  auto spGroup_itr = spGroup.begin();
133  for (std::size_t i = 0;
134  spGroup_itr != spGroup_end && i < cmdl.groupsToIterate;
135  ++i, ++spGroup_itr) {
136  seeds_host.push_back(seedfinder_host.createSeedsForGroup(
137  spGroup_itr.bottom(), spGroup_itr.middle(), spGroup_itr.top()));
138  }
139  }
140 
141  // Record the finish time.
142  auto end_host = std::chrono::system_clock::now();
143  double time_host = std::chrono::duration_cast<std::chrono::milliseconds>(
144  end_host - start_host)
145  .count() *
146  0.001;
147  if (!cmdl.onlyGPU) {
148  std::cout << "Done with the seedfinding on the host" << std::endl;
149  }
150 
151  //
152  // Perform the seed finding on the accelerator.
153  //
154 
155  // Record the start time.
156  auto start_device = std::chrono::system_clock::now();
157  // Create the result object.
158  std::vector<std::vector<Acts::Seed<TestSpacePoint>>> seeds_device;
159 
160  // Perform the seed finding.
161  auto spGroup_itr = spGroup.begin();
162  for (std::size_t i = 0;
163  spGroup_itr != spGroup_end && i < cmdl.groupsToIterate;
164  ++i, ++spGroup_itr) {
165  seeds_device.push_back(seedfinder_device.createSeedsForGroup(
166  spGroup_itr.bottom(), spGroup_itr.middle(), spGroup_itr.top()));
167  }
168 
169  // Record the finish time.
170  auto end_device = std::chrono::system_clock::now();
171  double time_device = std::chrono::duration_cast<std::chrono::milliseconds>(
172  end_device - start_device)
173  .count() *
174  0.001;
175  std::cout << "Done with the seedfinding on the device" << std::endl;
176 
177  //
178  // Print some summary about the seed finding.
179  //
180 
181  // Count the total number of reconstructed seeds.
182  std::size_t nSeeds_host = 0, nSeeds_device = 0;
183  for (const auto& seeds : seeds_host) {
184  nSeeds_host += seeds.size();
185  }
186  for (const auto& seeds : seeds_device) {
187  nSeeds_device += seeds.size();
188  }
189 
190  // Count how many seeds, reconstructed on the host, can be matched with seeds
191  // reconstructed on the accelerator.
192  std::size_t nMatch = 0;
193  double matchPercentage = 0.0;
194  if (!cmdl.onlyGPU) {
195  assert(seeds_host.size() == seeds_device.size());
196  for (size_t i = 0; i < seeds_host.size(); i++) {
197  // Access the seeds for this region.
198  const auto& seeds_in_host_region = seeds_host[i];
199  const auto& seeds_in_device_region = seeds_device[i];
200  // Loop over all seeds found on the host.
201  for (const auto& host_seed : seeds_in_host_region) {
202  assert(host_seed.sp().size() == 3);
203  // Try to find a matching seed that was found on the accelerator.
204  for (const auto& device_seed : seeds_in_device_region) {
205  assert(device_seed.sp().size() == 3);
206  if ((*(host_seed.sp()[0]) == *(device_seed.sp()[0])) &&
207  (*(host_seed.sp()[1]) == *(device_seed.sp()[1])) &&
208  (*(host_seed.sp()[2]) == *(device_seed.sp()[2]))) {
209  ++nMatch;
210  break;
211  }
212  }
213  }
214  }
215  matchPercentage = (100.0 * nMatch) / nSeeds_host;
216  }
217 
218  // Print the summary results.
219  std::cout << std::endl;
220  std::cout << "-------------------------- Results ---------------------------"
221  << std::endl;
222  std::cout << "| | Host | Device | Speedup/agreement |"
223  << std::endl;
224  std::cout << "--------------------------------------------------------------"
225  << std::endl;
226  std::cout << "| Time [s] | " << std::setw(10)
227  << (cmdl.onlyGPU ? "N/A " : std::to_string(time_host)) << " | "
228  << std::setw(10) << time_device << " | " << std::setw(10)
229  << (cmdl.onlyGPU ? "N/A "
230  : std::to_string(time_host / time_device))
231  << " |" << std::endl;
232  std::cout << "| Seeds | " << std::setw(10)
233  << (cmdl.onlyGPU ? "N/A " : std::to_string(nSeeds_host))
234  << " | " << std::setw(10) << nSeeds_device << " | "
235  << std::setw(10)
236  << (cmdl.onlyGPU ? "N/A " : std::to_string(matchPercentage))
237  << " |" << std::endl;
238  std::cout << "--------------------------------------------------------------"
239  << std::endl;
240  std::cout << std::endl;
241 
242  // Return gracefully.
243  return 0;
244 }