Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-08-05 08:10:22

0001 // This file is part of the Acts project.
0002 //
0003 // Copyright (C) 2017-2018 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 http://mozilla.org/MPL/2.0/.
0008 
0009 #include "Acts/Definitions/Algebra.hpp"
0010 #include "Acts/Definitions/Units.hpp"
0011 #include "Acts/Surfaces/BoundaryCheck.hpp"
0012 #include "Acts/Tests/CommonHelpers/BenchmarkTools.hpp"
0013 
0014 #include <algorithm>
0015 #include <chrono>
0016 #include <functional>
0017 #include <iostream>
0018 #include <random>
0019 #include <vector>
0020 
0021 using namespace Acts;
0022 
0023 int main(int /*argc*/, char** /*argv[]*/) {
0024   // === PROBLEM DATA ===
0025 
0026   // Trapezoidal area of interest
0027   const Vector2 poly[] = {{0.4, 0.25}, {0.6, 0.25}, {0.8, 0.75}, {0.2, 0.75}};
0028 
0029   // Covariance matrix which specifies "soft" boundary check tolerance
0030   SquareMatrix2 cov;
0031   cov << 0.2, 0.02, 0.15, 0.02;
0032 
0033   // Random tests cover the ((0, 0), (1, 1)) rectangle. 20% of that area is
0034   // covered by the trapezoid and most of it is covered by a 3*sigma tolerance
0035   // given the above covariance matrix.
0036   std::mt19937 rng(42);
0037   std::uniform_real_distribution<double> axis(0, 1);
0038   auto random_point = [&]() -> Vector2 {
0039     return Vector2(axis(rng), axis(rng));
0040   };
0041 
0042   // This point is inside the area
0043   const Vector2 center(0.5, 0.5);
0044   // This point is still inside the area, but close to an edge
0045   const Vector2 edge_inside(0.401, 0.251);
0046   // This point is just a bit outside, should be considered "in" by tolerance
0047   const Vector2 edge_outside(0.399, 0.249);
0048   // This point should always be considered outside the area
0049   const Vector2 far_away(-1000., -1000.);
0050 
0051   // === BENCHMARKS ===
0052 
0053   // Number of benchmark runs
0054   constexpr int NTESTS = 5'000;
0055 
0056   // Some checks are much slower, so we tune down benchmark iterations
0057   constexpr int NTESTS_SLOW = NTESTS / 10;
0058 
0059   // Conversely, no-op tests are so fast that we need to tune up iterations
0060   constexpr int NTESTS_NOOP = NTESTS * 10;
0061 
0062   // We use this to switch between iteration counts
0063   enum class Mode { NoCheck, FastOutside, SlowOutside };
0064 
0065   // Benchmark output display
0066   auto print_bench_header = [](const std::string& check_name) {
0067     std::cout << check_name << ":" << std::endl;
0068   };
0069   auto print_bench_result = [](const std::string& bench_name,
0070                                const Acts::Test::MicroBenchmarkResult& res) {
0071     std::cout << "- " << bench_name << ": " << res << std::endl;
0072   };
0073 
0074   // Benchmark runner
0075   auto run_bench = [&](auto&& iteration, int num_iters,
0076                        const std::string& bench_name) {
0077     auto bench_result = Acts::Test::microBenchmark(iteration, num_iters);
0078     print_bench_result(bench_name, bench_result);
0079   };
0080   auto run_bench_with_inputs = [&](auto&& iterationWithArg, auto&& inputs,
0081                                    const std::string& bench_name) {
0082     auto bench_result = Acts::Test::microBenchmark(iterationWithArg, inputs);
0083     print_bench_result(bench_name, bench_result);
0084   };
0085   auto run_all_benches = [&](const BoundaryCheck& check,
0086                              const std::string& check_name, const Mode mode) {
0087     // Announce a set of benchmarks
0088     print_bench_header(check_name);
0089 
0090     // Pre-determined "interesting" test points
0091     int num_inside_points = 0;
0092     int num_outside_points = 0;
0093     switch (mode) {
0094       case Mode::NoCheck:
0095         num_inside_points = NTESTS_NOOP;
0096         num_outside_points = NTESTS_NOOP;
0097         break;
0098       case Mode::FastOutside:
0099         num_inside_points = NTESTS;
0100         num_outside_points = NTESTS;
0101         break;
0102       case Mode::SlowOutside:
0103         num_inside_points = NTESTS;
0104         num_outside_points = NTESTS_SLOW;
0105       default:  // do nothing
0106         break;
0107     };
0108     run_bench([&] { return check.isInside(center, poly); }, num_inside_points,
0109               "Center");
0110     run_bench([&] { return check.isInside(edge_inside, poly); },
0111               num_inside_points, "Inside edge");
0112     run_bench([&] { return check.isInside(edge_outside, poly); },
0113               num_outside_points, "Outside edge");
0114     run_bench([&] { return check.isInside(far_away, poly); },
0115               num_outside_points, "Far away");
0116 
0117     // Pre-rolled random points
0118     std::vector<Vector2> points(num_outside_points);
0119     std::generate(points.begin(), points.end(), random_point);
0120     run_bench_with_inputs(
0121         [&](const auto& point) { return check.isInside(point, poly); }, points,
0122         "Random");
0123   };
0124 
0125   // Benchmark scenarios
0126   run_all_benches(BoundaryCheck(false), "No check", Mode::NoCheck);
0127   run_all_benches(BoundaryCheck(true), "No tolerance", Mode::FastOutside);
0128   run_all_benches(BoundaryCheck(true, true, 0.6, 0.45), "Abs. tolerance",
0129                   Mode::SlowOutside);
0130   run_all_benches(BoundaryCheck(cov, 3.0), "Cov. tolerance", Mode::SlowOutside);
0131 
0132   return 0;
0133 }