Skip to content

Commit 56040a3

Browse files
committed
[Math] Move TimingScope to ROOT::Math::Util
Move TimingScope to `ROOT::Math::Util` in MathCore to avoid code duplication while at the same time not introducing new dependencies (MathCore is the only dependency that Minuit2 is allowed to have because of the standalone build possibility).
1 parent fb526ff commit 56040a3

15 files changed

+116
-167
lines changed

math/mathcore/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,7 @@ ROOT_STANDARD_LIBRARY_PACKAGE(MathCore
189189
src/TRandomGen.cxx
190190
src/TStatistic.cxx
191191
src/UnBinData.cxx
192+
src/Util.cxx
192193
src/VectorizedTMath.cxx
193194
LIBRARIES
194195
${MATHCORE_LIBRARIES}

math/mathcore/inc/Math/Util.h

+21-8
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,12 @@
1313
#ifndef ROOT_Math_Util
1414
#define ROOT_Math_Util
1515

16-
#include <string>
17-
#include <sstream>
18-
1916
#include <cmath>
17+
#include <functional>
2018
#include <limits>
2119
#include <numeric>
20+
#include <sstream>
21+
#include <string>
2222

2323

2424
// This can be protected against by defining ROOT_Math_VecTypes
@@ -36,12 +36,25 @@
3636

3737
namespace ROOT {
3838

39-
namespace Math {
39+
namespace Math {
4040

41-
/**
42-
namespace defining Utility functions needed by mathcore
43-
*/
44-
namespace Util {
41+
/**
42+
namespace defining Utility functions needed by mathcore
43+
*/
44+
namespace Util {
45+
46+
class TimingScope {
47+
48+
public:
49+
TimingScope(std::function<void(std::string const&)> printer, std::string const &message);
50+
51+
~TimingScope();
52+
53+
private:
54+
void *fBegin;
55+
std::function<void(std::string const&)> fPrinter;
56+
const std::string fMessage;
57+
};
4558

4659
/**
4760
Utility function for conversion to strings

math/mathcore/src/Util.cxx

+69
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
#include "Math/Util.h"
2+
3+
#include <chrono>
4+
5+
ROOT::Math::Util::TimingScope::TimingScope(std::function<void(std::string const &)> printer, std::string const &message)
6+
: fPrinter{printer}, fMessage{message}
7+
{
8+
using std::chrono::steady_clock;
9+
fBegin = new steady_clock::time_point{steady_clock::now()};
10+
}
11+
12+
namespace {
13+
14+
template <class T>
15+
std::string printTime(T duration)
16+
{
17+
std::stringstream ss;
18+
// Here, nanoseconds are represented as "long int", so the maximum value
19+
// corresponds to about 300 years. Nobody will wait that long for a
20+
// computation to complete, so for timing measurements it's fine to cast to
21+
// nanoseconds to keep things simple.
22+
double ns = std::chrono::duration_cast<std::chrono::nanoseconds>(duration).count();
23+
bool forceSeconds = false;
24+
// The largest unit that we consider for pretty-printing is days.
25+
if (ns >= 24 * 60 * 60e9) {
26+
auto days = std::floor(ns / (24 * 60 * 60e9));
27+
ss << days << " d ";
28+
ns -= days * 24 * 60 * 60e9; // subtract the days to print only the rest
29+
// to avoid printouts like "1 d 4 h 23 min 324 ns", we force to print
30+
// seconds if we print either days, hours, or minutes
31+
forceSeconds = true;
32+
}
33+
if (ns >= 60 * 60e9) {
34+
auto hours = std::floor(ns / (60 * 60e9));
35+
ss << hours << " h ";
36+
ns -= hours * 60 * 60e9;
37+
forceSeconds = true;
38+
}
39+
if (ns >= 60e9) {
40+
auto minutes = std::floor(ns / 60e9);
41+
ss << minutes << " min ";
42+
ns -= minutes * 60e9;
43+
forceSeconds = true;
44+
}
45+
if (ns >= 1e9 || forceSeconds) {
46+
ss << (1e-9 * ns) << " s";
47+
} else if (ns >= 1e6) {
48+
ss << (1e-6 * ns) << " ms";
49+
} else if (ns >= 1e3) {
50+
ss << (1e-3 * ns) << " μs";
51+
} else {
52+
ss << ns << " ns";
53+
}
54+
return ss.str();
55+
}
56+
57+
} // namespace
58+
59+
ROOT::Math::Util::TimingScope::~TimingScope()
60+
{
61+
using std::chrono::steady_clock;
62+
auto *begin = reinterpret_cast<steady_clock::time_point *>(fBegin);
63+
steady_clock::time_point end = steady_clock::now();
64+
std::stringstream ss;
65+
ss << fMessage << " " << printTime(end - *begin);
66+
fPrinter(ss.str());
67+
// fROOT::Math::Util.Info(ss.str());
68+
delete begin;
69+
}

math/minuit2/inc/Minuit2/MnPrint.h

+1-14
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,12 @@
1313
#include "Minuit2/MnConfig.h"
1414

1515
#include <cassert>
16-
#include <chrono>
1716
#include <ios>
1817
#include <iostream>
1918
#include <sstream>
2019
#include <string>
2120
#include <utility>
21+
#include <functional>
2222

2323
namespace ROOT {
2424
namespace Minuit2 {
@@ -143,19 +143,6 @@ class MnPrint {
143143
Log(eTrace, args...);
144144
}
145145

146-
class TimingScope {
147-
148-
public:
149-
TimingScope(MnPrint &mnPrint, std::string const &message);
150-
151-
~TimingScope();
152-
153-
private:
154-
std::chrono::steady_clock::time_point fBegin;
155-
MnPrint &fMnPrint;
156-
const std::string fMessage;
157-
};
158-
159146
private:
160147
// low level logging
161148
template <class... Ts>

math/minuit2/src/MnHesse.cxx

+4-2
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525

2626
#include "./MnFcnCaller.h"
2727

28+
#include "Math/Util.h"
29+
2830
namespace ROOT {
2931

3032
namespace Minuit2 {
@@ -104,7 +106,7 @@ MinimumState ComputeAnalytical(const FCNBase &fcn, const MinimumState &st, const
104106
MnAlgebraicSymMatrix vhmat(n);
105107

106108
MnPrint print("MnHesse");
107-
MnPrint::TimingScope timingScope(print, "Done after");
109+
ROOT::Math::Util::TimingScope timingScope([&print](std::string const& s){ print.Info(s); }, "Done after");
108110

109111
const MnMachinePrecision &prec = trafo.Precision();
110112

@@ -176,7 +178,7 @@ MinimumState ComputeNumerical(const MnFcn &mfcn, const MinimumState &st, const M
176178
// Function who does the real Hessian calculations
177179
MnPrint print("MnHesse");
178180

179-
MnPrint::TimingScope timingScope(print, "Done after");
181+
ROOT::Math::Util::TimingScope timingScope([&print](std::string const& s){ print.Info(s); }, "Done after");
180182

181183
MnFcnCaller mfcnCaller{mfcn};
182184

math/minuit2/src/MnPrint.cxx

-59
Original file line numberDiff line numberDiff line change
@@ -419,64 +419,5 @@ std::ostream &operator<<(std::ostream &os, const std::pair<double, double> &poin
419419
return os;
420420
}
421421

422-
MnPrint::TimingScope::TimingScope(MnPrint &mnPrint, std::string const &message)
423-
: fBegin{std::chrono::steady_clock::now()}, fMnPrint{mnPrint}, fMessage{message}
424-
{
425-
}
426-
427-
namespace {
428-
429-
template<class T>
430-
std::string printTime(T duration) {
431-
std::stringstream ss;
432-
// Here, nanoseconds are represented as "long int", so the maximum value
433-
// corresponds to about 300 years. Nobody will wait that long for a
434-
// computation to complete, so for timing measurements it's fine to cast to
435-
// nanoseconds to keep things simple.
436-
double ns = std::chrono::duration_cast<std::chrono::nanoseconds>(duration).count();
437-
bool forceSeconds = false;
438-
// The largest unit that we consider for pretty-printing is days.
439-
if (ns >= 24 * 360e9) {
440-
auto days = std::floor(ns / (24 * 360e9));
441-
ss << days << " d ";
442-
ns -= days * 24 * 360e9; // subtract the days to print only the rest
443-
// to avoid printouts like "1 d 4 h 23 min 324 ns", we force to print
444-
// seconds if we print either days, hours, or minutes
445-
forceSeconds = true;
446-
}
447-
if (ns >= 360e9) {
448-
auto hours = std::floor(ns / 360e9);
449-
ss << hours << " h ";
450-
ns -= hours * 360e9;
451-
forceSeconds = true;
452-
}
453-
if (ns >= 60e9) {
454-
auto minutes = std::floor(ns / 60e9);
455-
ss << minutes << " min ";
456-
ns -= minutes * 60e9;
457-
forceSeconds = true;
458-
}
459-
if (ns >= 1e9 || forceSeconds) {
460-
ss << (1e-9 * ns) << " s";
461-
} else if (ns >= 1e6) {
462-
ss << (1e-6 * ns) << " ms";
463-
} else if (ns >= 1e3) {
464-
ss << (1e-3 * ns) << " μs";
465-
} else {
466-
ss << ns << " ns";
467-
}
468-
return ss.str();
469-
}
470-
471-
} // namespace
472-
473-
MnPrint::TimingScope::~TimingScope()
474-
{
475-
std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
476-
std::stringstream ss;
477-
ss << fMessage << " " << printTime(end - fBegin);
478-
fMnPrint.Info(ss.str());
479-
}
480-
481422
} // namespace Minuit2
482423
} // namespace ROOT

math/minuit2/src/MnSeedGenerator.cxx

+4-1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@
3232
#include "Minuit2/HessianGradientCalculator.h"
3333
#include "Minuit2/MnPrint.h"
3434

35+
#include "Math/Util.h"
36+
3537
#include <cmath>
3638

3739
namespace ROOT {
@@ -65,7 +67,8 @@ operator()(const MnFcn &fcn, const GradientCalculator &gc, const MnUserParameter
6567
// by default, and we're timing it here. If the G2 is negative, we also have
6668
// to run a NegativeG2LineSearch later, but this is timed separately inside
6769
// the line search.
68-
auto timingScope = std::make_unique<MnPrint::TimingScope>(print, "Evaluated function and gradient in");
70+
auto timingScope = std::make_unique<ROOT::Math::Util::TimingScope>([&print](std::string const &s) { print.Info(s); },
71+
"Evaluated function and gradient in");
6972
MinimumParameters pa(x, fcn(x));
7073
FunctionGradient dgrad = gc(pa);
7174
timingScope.reset();

math/minuit2/src/NegativeG2LineSearch.cxx

+3-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
#include "Minuit2/VariableMetricEDMEstimator.h"
1818
#include "Minuit2/MnPrint.h"
1919

20+
#include "Math/Util.h"
21+
2022
#include <cmath>
2123

2224
namespace ROOT {
@@ -35,7 +37,7 @@ MinimumState NegativeG2LineSearch::operator()(const MnFcn &fcn, const MinimumSta
3537
MnPrint print("NegativeG2LineSearch");
3638

3739
// Print the runtime on returning from the function
38-
MnPrint::TimingScope timingScope(print, "Done after");
40+
ROOT::Math::Util::TimingScope timingScope([&print](std::string const& s){ print.Info(s); }, "Done after");
3941

4042
bool negG2 = HasNegativeG2(st.Gradient(), prec);
4143
if (!negG2)

math/minuit2/src/VariableMetricBuilder.cxx

+3-1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
#include "Minuit2/MnHesse.h"
2424
#include "Minuit2/MnPrint.h"
2525

26+
#include "Math/Util.h"
27+
2628
#include <cmath>
2729
#include <cassert>
2830

@@ -94,7 +96,7 @@ FunctionMinimum VariableMetricBuilder::Minimum(const MnFcn &fcn, const GradientC
9496
print.Info("Start iterating until Edm is <", edmval, "with call limit =", maxfcn);
9597

9698
// print time after returning
97-
MnPrint::TimingScope timingScope(print, "Stop iterating after");
99+
ROOT::Math::Util::TimingScope timingScope([&print](std::string const &s) { print.Info(s); }, "Stop iterating after");
98100

99101
AddResult(result, seed.State());
100102

math/minuit2/src/math/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ set(MATH_SOURCES
3030
Minimizer.cxx
3131
MinimizerOptions.cxx
3232
ParameterSettings.cxx
33+
Util.cxx
3334
)
3435

3536
copy_standalone(SOURCE ../../../mathcore/inc/Fit DESTINATION ../../inc/Fit

roofit/roofitcore/res/RooFitImplHelpers.h

-17
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@
1515
#include <RooAbsArg.h>
1616
#include <RooAbsReal.h>
1717

18-
#include <chrono>
19-
#include <functional>
2018
#include <sstream>
2119
#include <string>
2220
#include <string_view>
@@ -107,21 +105,6 @@ void replaceAll(std::string &inOut, std::string_view what, std::string_view with
107105

108106
std::string makeSliceCutString(RooArgSet const &sliceDataSet);
109107

110-
// Similar to ROOT::Minuit2::MnPrint::TimingScope from the Minuit2
111-
// implementation details.
112-
class TimingScope {
113-
114-
public:
115-
TimingScope(std::function<void(std::string const&)> printer, std::string const &message);
116-
117-
~TimingScope();
118-
119-
private:
120-
std::chrono::steady_clock::time_point fBegin;
121-
std::function<void(std::string const&)> fPrinter;
122-
const std::string fMessage;
123-
};
124-
125108
} // namespace Detail
126109
} // namespace RooFit
127110

roofit/roofitcore/src/FitHelpers.cxx

+2-1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#include <RooFormulaVar.h>
3939

4040
#include <Math/CholeskyDecomp.h>
41+
#include <Math/Util.h>
4142

4243
#include "ConstraintHelpers.h"
4344
#include "RooEvaluatorWrapper.h"
@@ -591,7 +592,7 @@ std::unique_ptr<RooFitResult> minimize(RooAbsReal &pdf, RooAbsReal &nll, RooAbsD
591592

592593
std::unique_ptr<RooAbsReal> createNLL(RooAbsPdf &pdf, RooAbsData &data, const RooLinkedList &cmdList)
593594
{
594-
auto timingScope = std::make_unique<RooFit::Detail::TimingScope>(
595+
auto timingScope = std::make_unique<ROOT::Math::Util::TimingScope>(
595596
[&pdf](std::string const &msg) { oocoutI(&pdf, Fitting) << msg << std::endl; }, "Creation of NLL object took");
596597

597598
auto baseName = std::string("nll_") + pdf.GetName() + "_" + data.GetName();

0 commit comments

Comments
 (0)