forked from sPHENIX-Collaboration/acts
/
BoundaryCheckBenchmark.cpp
131 lines (112 loc) · 4.72 KB
/
BoundaryCheckBenchmark.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
// This file is part of the Acts project.
//
// Copyright (C) 2017-2018 CERN for the benefit of the Acts project
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include "Acts/Surfaces/BoundaryCheck.hpp"
#include "Acts/Tests/CommonHelpers/BenchmarkTools.hpp"
#include "Acts/Utilities/Definitions.hpp"
#include "Acts/Utilities/Units.hpp"
#include <algorithm>
#include <chrono>
#include <functional>
#include <iostream>
#include <random>
#include <vector>
using namespace Acts;
int main(int /*argc*/, char** /*argv[]*/) {
// === PROBLEM DATA ===
// Trapezoidal area of interest
const Vector2D poly[] = {{0.4, 0.25}, {0.6, 0.25}, {0.8, 0.75}, {0.2, 0.75}};
// Covariance matrix which specifies "soft" boundary check tolerance
SymMatrix2D cov;
cov << 0.2, 0.02, 0.15, 0.02;
// Random tests cover the ((0, 0), (1, 1)) rectangle. 20% of that area is
// covered by the trapezoid and most of it is covered by a 3*sigma tolerance
// given the above covariance matrix.
std::mt19937 rng(42);
std::uniform_real_distribution<double> axis(0, 1);
auto random_point = [&]() -> Vector2D {
return Vector2D(axis(rng), axis(rng));
};
// This point is inside the area
const Vector2D center(0.5, 0.5);
// This point is still inside the area, but close to an edge
const Vector2D edge_inside(0.401, 0.251);
// This point is just a bit outside, should be considered "in" by tolerance
const Vector2D edge_outside(0.399, 0.249);
// This point should always be considered outside the area
const Vector2D far_away(-1000., -1000.);
// === BENCHMARKS ===
// Number of benchmark runs
constexpr int NTESTS = 5'000;
// Some checks are much slower, so we tune down benchmark iterations
constexpr int NTESTS_SLOW = NTESTS / 10;
// Conversely, no-op tests are so fast that we need to tune up iterations
constexpr int NTESTS_NOOP = NTESTS * 10;
// We use this to switch between iteration counts
enum class Mode { NoCheck, FastOutside, SlowOutside };
// Benchmark output display
auto print_bench_header = [](const std::string& check_name) {
std::cout << check_name << ":" << std::endl;
};
auto print_bench_result = [](const std::string& bench_name,
const Acts::Test::MicroBenchmarkResult& res) {
std::cout << "- " << bench_name << ": " << res << std::endl;
};
// Benchmark runner
auto run_bench = [&](auto&& iteration, int num_iters,
const std::string& bench_name) {
auto bench_result = Acts::Test::microBenchmark(iteration, num_iters);
print_bench_result(bench_name, bench_result);
};
auto run_bench_with_inputs = [&](auto&& iterationWithArg, auto&& inputs,
const std::string& bench_name) {
auto bench_result = Acts::Test::microBenchmark(iterationWithArg, inputs);
print_bench_result(bench_name, bench_result);
};
auto run_all_benches = [&](const BoundaryCheck& check,
const std::string& check_name, const Mode mode) {
// Announce a set of benchmarks
print_bench_header(check_name);
// Pre-determined "interesting" test points
int num_inside_points;
int num_outside_points;
switch (mode) {
case Mode::NoCheck:
num_inside_points = NTESTS_NOOP;
num_outside_points = NTESTS_NOOP;
break;
case Mode::FastOutside:
num_inside_points = NTESTS;
num_outside_points = NTESTS;
break;
case Mode::SlowOutside:
num_inside_points = NTESTS;
num_outside_points = NTESTS_SLOW;
};
run_bench([&] { return check.isInside(center, poly); }, num_inside_points,
"Center");
run_bench([&] { return check.isInside(edge_inside, poly); },
num_inside_points, "Inside edge");
run_bench([&] { return check.isInside(edge_outside, poly); },
num_outside_points, "Outside edge");
run_bench([&] { return check.isInside(far_away, poly); },
num_outside_points, "Far away");
// Pre-rolled random points
std::vector<Vector2D> points(num_outside_points);
std::generate(points.begin(), points.end(), random_point);
run_bench_with_inputs(
[&](const auto& point) { return check.isInside(point, poly); }, points,
"Random");
};
// Benchmark scenarios
run_all_benches(BoundaryCheck(false), "No check", Mode::NoCheck);
run_all_benches(BoundaryCheck(true), "No tolerance", Mode::FastOutside);
run_all_benches(BoundaryCheck(true, true, 0.6, 0.45), "Abs. tolerance",
Mode::SlowOutside);
run_all_benches(BoundaryCheck(cov, 3.0), "Cov. tolerance", Mode::SlowOutside);
return 0;
}