File indexing completed on 2025-01-18 09:13:07
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "Acts/Plugins/Cuda/Seeding/SeedFinder.hpp"
0010 #include "Acts/Seeding/BinnedGroup.hpp"
0011 #include "Acts/Seeding/InternalSeed.hpp"
0012 #include "Acts/Seeding/InternalSpacePoint.hpp"
0013 #include "Acts/Seeding/Seed.hpp"
0014 #include "Acts/Seeding/SeedFilter.hpp"
0015 #include "Acts/Seeding/SeedFinder.hpp"
0016 #include "Acts/Seeding/SpacePointGrid.hpp"
0017 #include "Acts/Utilities/GridBinFinder.hpp"
0018
0019 #include <chrono>
0020 #include <fstream>
0021 #include <iomanip>
0022 #include <iostream>
0023 #include <optional>
0024 #include <sstream>
0025 #include <utility>
0026
0027 #include <boost/type_erasure/any_cast.hpp>
0028 #include <cuda_profiler_api.h>
0029
0030 #include "ATLASCuts.hpp"
0031 #include "SpacePoint.hpp"
0032
0033 using namespace Acts::UnitLiterals;
0034
0035 std::vector<const SpacePoint*> readFile(std::string filename) {
0036 std::string line;
0037 int layer;
0038 std::vector<const SpacePoint*> readSP;
0039
0040 std::ifstream spFile(filename);
0041 if (spFile.is_open()) {
0042 while (!spFile.eof()) {
0043 std::getline(spFile, line);
0044 std::stringstream ss(line);
0045 std::string linetype;
0046 ss >> linetype;
0047 float x, y, z, r, varianceR, varianceZ;
0048 if (linetype == "lxyz") {
0049 ss >> layer >> x >> y >> z >> varianceR >> varianceZ;
0050 r = std::hypot(x, y);
0051 float f22 = varianceR;
0052 float wid = varianceZ;
0053 float cov = wid * wid * .08333;
0054 if (cov < f22)
0055 cov = f22;
0056 if (std::abs(z) > 450.) {
0057 varianceZ = 9. * cov;
0058 varianceR = .06;
0059 } else {
0060 varianceR = 9. * cov;
0061 varianceZ = .06;
0062 }
0063 SpacePoint* sp =
0064 new SpacePoint{x, y, z, r, layer, varianceR, varianceZ};
0065
0066
0067
0068 readSP.push_back(sp);
0069 }
0070 }
0071 }
0072 return readSP;
0073 }
0074
0075 int main(int argc, char** argv) {
0076 auto start_pre = std::chrono::system_clock::now();
0077
0078 std::string file{"sp.txt"};
0079 bool help(false);
0080 bool quiet(false);
0081 bool allgroup(false);
0082 bool do_cpu(true);
0083 int nGroupToIterate = 500;
0084 int skip = 0;
0085 int deviceID = 0;
0086 int nTrplPerSpBLimit = 100;
0087 int nAvgTrplPerSpBLimit = 2;
0088
0089 int opt;
0090 while ((opt = getopt(argc, argv, "haf:n:s:d:l:m:qG")) != -1) {
0091 switch (opt) {
0092 case 'a':
0093 allgroup = true;
0094 break;
0095 case 'f':
0096 file = optarg;
0097 break;
0098 case 'n':
0099 nGroupToIterate = atoi(optarg);
0100 break;
0101 case 's':
0102 skip = atoi(optarg);
0103 break;
0104 case 'd':
0105 deviceID = atoi(optarg);
0106 break;
0107 case 'l':
0108 nAvgTrplPerSpBLimit = atoi(optarg);
0109 break;
0110 case 'm':
0111 nTrplPerSpBLimit = atoi(optarg);
0112 break;
0113 case 'q':
0114 quiet = true;
0115 break;
0116 case 'G':
0117 do_cpu = false;
0118 break;
0119 case 'h':
0120 help = true;
0121 [[fallthrough]];
0122 default:
0123 std::cerr << "Usage: " << argv[0] << " [-hq] [-f FILENAME]\n";
0124 if (help) {
0125 std::cout << " -h : this help" << std::endl;
0126 std::cout << " -a ALL : analyze all groups. Default is \""
0127 << allgroup << "\"" << std::endl;
0128 std::cout
0129 << " -f FILE : read spacepoints from FILE. Default is \""
0130 << file << "\"" << std::endl;
0131 std::cout << " -n NUM : Number of groups to iterate in seed "
0132 "finding. Default is "
0133 << nGroupToIterate << std::endl;
0134 std::cout << " -s SKIP : Number of groups to skip in seed "
0135 "finding. Default is "
0136 << skip << std::endl;
0137 std::cout << " -d DEVID : NVIDIA GPU device ID. Default is "
0138 << deviceID << std::endl;
0139 std::cout << " -l : A limit on the average number of triplets "
0140 "per bottom spacepoint: this is used for determining "
0141 "matrix size for triplets per middle space point"
0142 << nAvgTrplPerSpBLimit << std::endl;
0143 std::cout << " -m : A limit on the number of triplets per "
0144 "bottom spacepoint: users do not have to touch this for "
0145 "# spacepoints < ~200k"
0146 << nTrplPerSpBLimit << std::endl;
0147 std::cout << " -q : don't print out all found seeds"
0148 << std::endl;
0149 std::cout << " -G : only run on GPU, not CPU" << std::endl;
0150 }
0151
0152 exit(EXIT_FAILURE);
0153 }
0154 }
0155
0156 std::string devName;
0157 ACTS_CUDA_ERROR_CHECK(cudaSetDevice(deviceID));
0158
0159 std::ifstream f(file);
0160 if (!f.good()) {
0161 std::cerr << "input file \"" << file << "\" does not exist\n";
0162 exit(EXIT_FAILURE);
0163 }
0164
0165 std::vector<const SpacePoint*> spVec = readFile(file);
0166
0167 std::cout << "read " << spVec.size() << " SP from file " << file << std::endl;
0168
0169
0170 Acts::SeedFinderConfig<SpacePoint> config;
0171
0172 config.rMax = 160._mm;
0173 config.deltaRMin = 5._mm;
0174 config.deltaRMax = 160._mm;
0175 config.deltaRMinTopSP = config.deltaRMin;
0176 config.deltaRMinBottomSP = config.deltaRMin;
0177 config.deltaRMaxTopSP = config.deltaRMax;
0178 config.deltaRMaxBottomSP = config.deltaRMax;
0179 config.collisionRegionMin = -250._mm;
0180 config.collisionRegionMax = 250._mm;
0181 config.zMin = -2800._mm;
0182 config.zMax = 2800._mm;
0183 config.maxSeedsPerSpM = 5;
0184
0185 config.cotThetaMax = 7.40627;
0186 config.sigmaScattering = 1.00000;
0187
0188 config.minPt = 500._MeV;
0189 config.impactMax = 10._mm;
0190 config = config.toInternalUnits();
0191
0192 Acts::SeedFinderOptions options;
0193 options.bFieldInZ = 2_T;
0194 options.beamPos = {-.5_mm, -.5_mm};
0195 options = options.toInternalUnits().calculateDerivedQuantities(config);
0196
0197 int numPhiNeighbors = 1;
0198
0199
0200 Acts::Extent rRangeSPExtent;
0201
0202 const Acts::Range1D<float> rMiddleSPRange;
0203
0204 std::vector<std::pair<int, int>> zBinNeighborsTop;
0205 std::vector<std::pair<int, int>> zBinNeighborsBottom;
0206
0207
0208 cudaDeviceProp prop;
0209 ACTS_CUDA_ERROR_CHECK(cudaGetDeviceProperties(&prop, deviceID));
0210 printf("\n GPU Device %d: \"%s\" with compute capability %d.%d\n\n", deviceID,
0211 prop.name, prop.major, prop.minor);
0212 config.maxBlockSize = prop.maxThreadsPerBlock;
0213 config.nTrplPerSpBLimit = nTrplPerSpBLimit;
0214 config.nAvgTrplPerSpBLimit = nAvgTrplPerSpBLimit;
0215
0216
0217 auto bottomBinFinder = std::make_unique<Acts::GridBinFinder<2ul>>(
0218 Acts::GridBinFinder<2ul>(numPhiNeighbors, zBinNeighborsBottom));
0219 auto topBinFinder = std::make_unique<Acts::GridBinFinder<2ul>>(
0220 Acts::GridBinFinder<2ul>(numPhiNeighbors, zBinNeighborsTop));
0221 Acts::SeedFilterConfig sfconf;
0222 Acts::ATLASCuts<SpacePoint> atlasCuts = Acts::ATLASCuts<SpacePoint>();
0223 config.seedFilter = std::make_unique<Acts::SeedFilter<SpacePoint>>(
0224 Acts::SeedFilter<SpacePoint>(sfconf, &atlasCuts));
0225 Acts::SeedFinder<SpacePoint, Acts::CylindricalSpacePointGrid<SpacePoint>>
0226 seedFinder_cpu(config);
0227 Acts::SeedFinder<SpacePoint, Acts::Cuda> seedFinder_cuda(config, options);
0228
0229
0230 auto ct = [=](const SpacePoint& sp, float, float, float)
0231 -> std::tuple<Acts::Vector3, Acts::Vector2, std::optional<float>> {
0232 Acts::Vector3 position(sp.x(), sp.y(), sp.z());
0233 Acts::Vector2 variance(sp.varianceR, sp.varianceZ);
0234 return {position, variance, std::nullopt};
0235 };
0236
0237
0238 Acts::CylindricalSpacePointGridConfig gridConf;
0239 gridConf.minPt = config.minPt;
0240 gridConf.rMax = config.rMax;
0241 gridConf.zMax = config.zMax;
0242 gridConf.zMin = config.zMin;
0243 gridConf.deltaRMax = config.deltaRMax;
0244 gridConf.cotThetaMax = config.cotThetaMax;
0245
0246 Acts::CylindricalSpacePointGridOptions gridOpts;
0247 gridOpts.bFieldInZ = options.bFieldInZ;
0248
0249 Acts::CylindricalSpacePointGrid<SpacePoint> grid =
0250 Acts::CylindricalSpacePointGridCreator::createGrid<SpacePoint>(gridConf,
0251 gridOpts);
0252 Acts::CylindricalSpacePointGridCreator::fillGrid(
0253 config, options, grid, spVec.begin(), spVec.end(), ct, rRangeSPExtent);
0254
0255 auto spGroup = Acts::CylindricalBinnedGroup<SpacePoint>(
0256 std::move(grid), *bottomBinFinder, *topBinFinder);
0257
0258 auto end_pre = std::chrono::system_clock::now();
0259 std::chrono::duration<double> elapsec_pre = end_pre - start_pre;
0260 double preprocessTime = elapsec_pre.count();
0261 std::cout << "Preprocess Time: " << preprocessTime << std::endl;
0262
0263
0264
0265
0266
0267 auto start_cpu = std::chrono::system_clock::now();
0268
0269 std::array<std::vector<std::size_t>, 2ul> navigation;
0270 navigation[0ul].resize(spGroup.grid().numLocalBins()[0ul]);
0271 navigation[1ul].resize(spGroup.grid().numLocalBins()[1ul]);
0272 std::iota(navigation[0ul].begin(), navigation[0ul].end(), 1ul);
0273 std::iota(navigation[1ul].begin(), navigation[1ul].end(), 1ul);
0274
0275 std::array<std::size_t, 2ul> localPosition =
0276 spGroup.grid().localBinsFromGlobalBin(skip);
0277
0278 int group_count;
0279 auto groupIt = Acts::CylindricalBinnedGroupIterator<SpacePoint>(
0280 spGroup, localPosition, navigation);
0281
0282
0283 group_count = 0;
0284 std::vector<std::vector<Acts::Seed<SpacePoint>>> seedVector_cpu;
0285
0286 if (do_cpu) {
0287 decltype(seedFinder_cpu)::SeedingState state;
0288 state.spacePointData.resize(spVec.size());
0289 for (; groupIt != spGroup.end(); ++groupIt) {
0290 const auto [bottom, middle, top] = *groupIt;
0291 seedFinder_cpu.createSeedsForGroup(
0292 options, state, spGroup.grid(),
0293 std::back_inserter(seedVector_cpu.emplace_back()), bottom, middle,
0294 top, rMiddleSPRange);
0295 group_count++;
0296 if (allgroup == false) {
0297 if (group_count >= nGroupToIterate)
0298 break;
0299 }
0300 }
0301
0302 std::cout << "Analyzed " << group_count << " groups for CPU" << std::endl;
0303 }
0304
0305 auto end_cpu = std::chrono::system_clock::now();
0306 std::chrono::duration<double> elapsec_cpu = end_cpu - start_cpu;
0307 double cpuTime = elapsec_cpu.count();
0308
0309
0310
0311 cudaProfilerStart();
0312 auto start_cuda = std::chrono::system_clock::now();
0313
0314 group_count = 0;
0315 std::vector<std::vector<Acts::Seed<SpacePoint>>> seedVector_cuda;
0316 groupIt = Acts::CylindricalBinnedGroupIterator<SpacePoint>(
0317 spGroup, localPosition, navigation);
0318
0319 Acts::SpacePointData spacePointData;
0320 spacePointData.resize(spVec.size());
0321
0322 for (; groupIt != spGroup.end(); ++groupIt) {
0323 const auto [bottom, middle, top] = *groupIt;
0324 seedVector_cuda.push_back(seedFinder_cuda.createSeedsForGroup(
0325 spacePointData, spGroup.grid(), bottom, middle, top));
0326 group_count++;
0327 if (allgroup == false) {
0328 if (group_count >= nGroupToIterate)
0329 break;
0330 }
0331 }
0332
0333 auto end_cuda = std::chrono::system_clock::now();
0334 std::chrono::duration<double> elapsec_cuda = end_cuda - start_cuda;
0335 double cudaTime = elapsec_cuda.count();
0336
0337 cudaProfilerStop();
0338 std::cout << "Analyzed " << group_count << " groups for CUDA" << std::endl;
0339
0340 std::cout << std::endl;
0341 std::cout << "----------------------- Time Metric -----------------------"
0342 << std::endl;
0343 std::cout << " " << (do_cpu ? "CPU" : " ")
0344 << " CUDA " << (do_cpu ? "Speedup " : "")
0345 << std::endl;
0346 std::cout << "Seedfinding_Time " << std::setw(11)
0347 << (do_cpu ? std::to_string(cpuTime) : "") << " " << std::setw(11)
0348 << cudaTime << " " << std::setw(11)
0349 << (do_cpu ? std::to_string(cpuTime / cudaTime) : "") << std::endl;
0350 double wallTime_cpu = cpuTime + preprocessTime;
0351 double wallTime_cuda = cudaTime + preprocessTime;
0352 std::cout << "Wall_time " << std::setw(11)
0353 << (do_cpu ? std::to_string(wallTime_cpu) : "") << " "
0354 << std::setw(11) << wallTime_cuda << " " << std::setw(11)
0355 << (do_cpu ? std::to_string(wallTime_cpu / wallTime_cuda) : "")
0356 << std::endl;
0357 std::cout << "-----------------------------------------------------------"
0358 << std::endl;
0359 std::cout << std::endl;
0360
0361 int nSeed_cpu = 0;
0362 for (auto& outVec : seedVector_cpu) {
0363 nSeed_cpu += outVec.size();
0364 }
0365
0366 int nSeed_cuda = 0;
0367 for (auto& outVec : seedVector_cuda) {
0368 nSeed_cuda += outVec.size();
0369 }
0370
0371 std::cout << "Number of Seeds (CPU | CUDA): " << nSeed_cpu << " | "
0372 << nSeed_cuda << std::endl;
0373
0374 int nMatch = 0;
0375
0376 for (std::size_t i = 0; i < seedVector_cpu.size(); i++) {
0377 auto regionVec_cpu = seedVector_cpu[i];
0378 auto regionVec_cuda = seedVector_cuda[i];
0379
0380 std::vector<std::vector<SpacePoint>> seeds_cpu;
0381 std::vector<std::vector<SpacePoint>> seeds_cuda;
0382
0383
0384 for (auto sd : regionVec_cpu) {
0385 std::vector<SpacePoint> seed_cpu;
0386 seed_cpu.push_back(*(sd.sp()[0]));
0387 seed_cpu.push_back(*(sd.sp()[1]));
0388 seed_cpu.push_back(*(sd.sp()[2]));
0389
0390 seeds_cpu.push_back(seed_cpu);
0391 }
0392
0393 for (auto sd : regionVec_cuda) {
0394 std::vector<SpacePoint> seed_cuda;
0395 seed_cuda.push_back(*(sd.sp()[0]));
0396 seed_cuda.push_back(*(sd.sp()[1]));
0397 seed_cuda.push_back(*(sd.sp()[2]));
0398
0399 seeds_cuda.push_back(seed_cuda);
0400 }
0401
0402 for (auto seed : seeds_cpu) {
0403 for (auto other : seeds_cuda) {
0404 if (seed[0] == other[0] && seed[1] == other[1] && seed[2] == other[2]) {
0405 nMatch++;
0406 break;
0407 }
0408 }
0409 }
0410 }
0411
0412 if (do_cpu) {
0413 std::cout << nMatch << " seeds are matched" << std::endl;
0414 std::cout << "Matching rate: " << float(nMatch) / nSeed_cpu * 100 << "%"
0415 << std::endl;
0416 }
0417
0418 if (!quiet) {
0419 if (do_cpu) {
0420 std::cout << "CPU Seed result:" << std::endl;
0421
0422 for (auto& regionVec : seedVector_cpu) {
0423 for (std::size_t i = 0; i < regionVec.size(); i++) {
0424 const Acts::Seed<SpacePoint>* seed = ®ionVec[i];
0425 const SpacePoint* sp = seed->sp()[0];
0426 std::cout << " (" << sp->x() << ", " << sp->y() << ", " << sp->z()
0427 << ") ";
0428 sp = seed->sp()[1];
0429 std::cout << sp->surface << " (" << sp->x() << ", " << sp->y() << ", "
0430 << sp->z() << ") ";
0431 sp = seed->sp()[2];
0432 std::cout << sp->surface << " (" << sp->x() << ", " << sp->y() << ", "
0433 << sp->z() << ") ";
0434 std::cout << std::endl;
0435 }
0436 }
0437
0438 std::cout << std::endl;
0439 }
0440 std::cout << "CUDA Seed result:" << std::endl;
0441
0442 for (auto& regionVec : seedVector_cuda) {
0443 for (std::size_t i = 0; i < regionVec.size(); i++) {
0444 const Acts::Seed<SpacePoint>* seed = ®ionVec[i];
0445 const SpacePoint* sp = seed->sp()[0];
0446 std::cout << " (" << sp->x() << ", " << sp->y() << ", " << sp->z()
0447 << ") ";
0448 sp = seed->sp()[1];
0449 std::cout << sp->surface << " (" << sp->x() << ", " << sp->y() << ", "
0450 << sp->z() << ") ";
0451 sp = seed->sp()[2];
0452 std::cout << sp->surface << " (" << sp->x() << ", " << sp->y() << ", "
0453 << sp->z() << ") ";
0454 std::cout << std::endl;
0455 }
0456 }
0457 }
0458
0459 std::cout << std::endl;
0460 std::cout << std::endl;
0461
0462 return 0;
0463 }