EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
SolenoidFieldBenchmark.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file SolenoidFieldBenchmark.cpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2018 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 
13 #include "Acts/Utilities/Units.hpp"
14 
15 #include <chrono>
16 #include <iostream>
17 #include <random>
18 #include <string>
19 
20 using namespace Acts::UnitLiterals;
21 
22 int main(int argc, char* argv[]) {
23  size_t iters_map = 5e2;
24  size_t iters_solenoid = 3;
25  size_t runs_solenoid = 1000;
26  if (argc >= 2) {
27  iters_map = std::stoi(argv[1]);
28  }
29  if (argc >= 3) {
30  iters_solenoid = std::stoi(argv[2]);
31  }
32  if (argc >= 4) {
33  runs_solenoid = std::stoi(argv[3]);
34  }
35 
36  const double L = 5.8_m;
37  const double R = (2.56 + 2.46) * 0.5 * 0.5_m;
38  const size_t nCoils = 1154;
39  const double bMagCenter = 2_T;
40  const size_t nBinsR = 150;
41  const size_t nBinsZ = 200;
42 
43  double rMin = -0.1;
44  double rMax = R * 2.;
45  double zMin = 2 * (-L / 2.);
46  double zMax = 2 * (L / 2.);
47 
48  Acts::SolenoidBField bSolenoidField({R, L, nCoils, bMagCenter});
49  std::cout << "Building interpolated field map" << std::endl;
50  auto mapper = Acts::solenoidFieldMapper({rMin, rMax}, {zMin, zMax},
51  {nBinsR, nBinsZ}, bSolenoidField);
53 
54  BField_t::Config cfg(std::move(mapper));
55  auto bFieldMap = BField_t(std::move(cfg));
56 
57  std::minstd_rand rng;
58  std::uniform_real_distribution<> zDist(1.5 * (-L / 2.), 1.5 * L / 2.);
59  std::uniform_real_distribution<> rDist(0, R * 1.5);
60  std::uniform_real_distribution<> phiDist(-M_PI, M_PI);
61  auto genPos = [&]() -> Acts::Vector3D {
62  const double z = zDist(rng), r = rDist(rng), phi = phiDist(rng);
63  return {r * std::cos(phi), r * std::sin(phi), z};
64  };
65 
66  // SolenoidBField lookup is so slow that the cost of generating a random field
67  // lookup position is negligible in comparison...
68  std::cout << "Benchmarking random SolenoidBField lookup: " << std::flush;
69  const auto solenoid_result = Acts::Test::microBenchmark(
70  [&] { return bSolenoidField.getField(genPos()); }, iters_solenoid,
71  runs_solenoid);
72  std::cout << solenoid_result << std::endl;
73 
74  // ...but for interpolated B-field map, the overhead of a field lookup is
75  // comparable to that of generating a random position, so we must be more
76  // careful. Hence we do two microbenchmarks which represent a kind of
77  // lower and upper bound on field lookup performance.
78  //
79  // - The first benchmark operates at constant position, so it measures only
80  // field lookup overhead but has unrealistically good cache locality. In
81  // that sense, it provides a lower bound of field lookup performance.
82  std::cout << "Benchmarking cached interpolated field lookup: " << std::flush;
83  const auto fixedPos = genPos();
84  const auto map_cached_result = Acts::Test::microBenchmark(
85  [&] { return bFieldMap.getField(fixedPos); }, iters_map);
86  std::cout << map_cached_result << std::endl;
87 
88  // - The second benchmark generates random positions, so it is biased by the
89  // cost of random position generation and has unrealistically bad cache
90  // locality, but provides an upper bound of field lookup performance.
91  std::cout << "Benchmarking random interpolated field lookup: " << std::flush;
92  const auto map_rand_result = Acts::Test::microBenchmark(
93  [&] { return bFieldMap.getField(genPos()); }, iters_map);
94  std::cout << map_rand_result << std::endl;
95 }