Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Math] Move TimingScope to ROOT::Math::Util #18021

Merged
merged 2 commits into from
Mar 19, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions math/mathcore/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ ROOT_STANDARD_LIBRARY_PACKAGE(MathCore
src/TRandomGen.cxx
src/TStatistic.cxx
src/UnBinData.cxx
src/Util.cxx
src/VectorizedTMath.cxx
LIBRARIES
${MATHCORE_LIBRARIES}
Expand Down
30 changes: 22 additions & 8 deletions math/mathcore/inc/Math/Util.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,13 @@
#ifndef ROOT_Math_Util
#define ROOT_Math_Util

#include <string>
#include <sstream>

#include <chrono>
#include <cmath>
#include <functional>
#include <limits>
#include <numeric>
#include <sstream>
#include <string>


// This can be protected against by defining ROOT_Math_VecTypes
Expand All @@ -36,12 +37,25 @@

namespace ROOT {

namespace Math {
namespace Math {

/**
namespace defining Utility functions needed by mathcore
*/
namespace Util {
/**
namespace defining Utility functions needed by mathcore
*/
namespace Util {

class TimingScope {

public:
TimingScope(std::function<void(std::string const&)> printer, std::string const &message);

~TimingScope();

private:
std::chrono::steady_clock::time_point fBegin;
std::function<void(std::string const&)> fPrinter;
const std::string fMessage;
};

/**
Utility function for conversion to strings
Expand Down
62 changes: 62 additions & 0 deletions math/mathcore/src/Util.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#include "Math/Util.h"

ROOT::Math::Util::TimingScope::TimingScope(std::function<void(std::string const &)> printer, std::string const &message)
: fBegin{std::chrono::steady_clock::now()}, fPrinter{printer}, fMessage{message}
{
}

namespace {

template <class T>
std::string printTime(T duration)
{
std::stringstream ss;
// Here, nanoseconds are represented as "long int", so the maximum value
// corresponds to about 300 years. Nobody will wait that long for a
// computation to complete, so for timing measurements it's fine to cast to
// nanoseconds to keep things simple.
double ns = std::chrono::duration_cast<std::chrono::nanoseconds>(duration).count();
bool forceSeconds = false;
// The largest unit that we consider for pretty-printing is days.
if (ns >= 24 * 60 * 60e9) {
auto days = std::floor(ns / (24 * 60 * 60e9));
ss << days << " d ";
ns -= days * 24 * 60 * 60e9; // subtract the days to print only the rest
// to avoid printouts like "1 d 4 h 23 min 324 ns", we force to print
// seconds if we print either days, hours, or minutes
forceSeconds = true;
}
if (ns >= 60 * 60e9) {
auto hours = std::floor(ns / (60 * 60e9));
ss << hours << " h ";
ns -= hours * 60 * 60e9;
forceSeconds = true;
}
if (ns >= 60e9) {
auto minutes = std::floor(ns / 60e9);
ss << minutes << " min ";
ns -= minutes * 60e9;
forceSeconds = true;
}
if (ns >= 1e9 || forceSeconds) {
ss << (1e-9 * ns) << " s";
} else if (ns >= 1e6) {
ss << (1e-6 * ns) << " ms";
} else if (ns >= 1e3) {
ss << (1e-3 * ns) << " μs";
} else {
ss << ns << " ns";
}
return ss.str();
}

} // namespace

ROOT::Math::Util::TimingScope::~TimingScope()
{
using std::chrono::steady_clock;
steady_clock::time_point end = steady_clock::now();
std::stringstream ss;
ss << fMessage << " " << printTime(end - fBegin);
fPrinter(ss.str());
}
15 changes: 1 addition & 14 deletions math/minuit2/inc/Minuit2/MnPrint.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@
#include "Minuit2/MnConfig.h"

#include <cassert>
#include <chrono>
#include <ios>
#include <iostream>
#include <sstream>
#include <string>
#include <utility>
#include <functional>

namespace ROOT {
namespace Minuit2 {
Expand Down Expand Up @@ -143,19 +143,6 @@ class MnPrint {
Log(eTrace, args...);
}

class TimingScope {

public:
TimingScope(MnPrint &mnPrint, std::string const &message);

~TimingScope();

private:
std::chrono::steady_clock::time_point fBegin;
MnPrint &fMnPrint;
const std::string fMessage;
};

private:
// low level logging
template <class... Ts>
Expand Down
6 changes: 4 additions & 2 deletions math/minuit2/src/MnHesse.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@

#include "./MnFcnCaller.h"

#include "Math/Util.h"

namespace ROOT {

namespace Minuit2 {
Expand Down Expand Up @@ -104,7 +106,7 @@ MinimumState ComputeAnalytical(const FCNBase &fcn, const MinimumState &st, const
MnAlgebraicSymMatrix vhmat(n);

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

const MnMachinePrecision &prec = trafo.Precision();

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

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

MnFcnCaller mfcnCaller{mfcn};

Expand Down
59 changes: 0 additions & 59 deletions math/minuit2/src/MnPrint.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -419,64 +419,5 @@ std::ostream &operator<<(std::ostream &os, const std::pair<double, double> &poin
return os;
}

MnPrint::TimingScope::TimingScope(MnPrint &mnPrint, std::string const &message)
: fBegin{std::chrono::steady_clock::now()}, fMnPrint{mnPrint}, fMessage{message}
{
}

namespace {

template<class T>
std::string printTime(T duration) {
std::stringstream ss;
// Here, nanoseconds are represented as "long int", so the maximum value
// corresponds to about 300 years. Nobody will wait that long for a
// computation to complete, so for timing measurements it's fine to cast to
// nanoseconds to keep things simple.
double ns = std::chrono::duration_cast<std::chrono::nanoseconds>(duration).count();
bool forceSeconds = false;
// The largest unit that we consider for pretty-printing is days.
if (ns >= 24 * 360e9) {
auto days = std::floor(ns / (24 * 360e9));
ss << days << " d ";
ns -= days * 24 * 360e9; // subtract the days to print only the rest
// to avoid printouts like "1 d 4 h 23 min 324 ns", we force to print
// seconds if we print either days, hours, or minutes
forceSeconds = true;
}
if (ns >= 360e9) {
auto hours = std::floor(ns / 360e9);
ss << hours << " h ";
ns -= hours * 360e9;
forceSeconds = true;
}
if (ns >= 60e9) {
auto minutes = std::floor(ns / 60e9);
ss << minutes << " min ";
ns -= minutes * 60e9;
forceSeconds = true;
}
if (ns >= 1e9 || forceSeconds) {
ss << (1e-9 * ns) << " s";
} else if (ns >= 1e6) {
ss << (1e-6 * ns) << " ms";
} else if (ns >= 1e3) {
ss << (1e-3 * ns) << " μs";
} else {
ss << ns << " ns";
}
return ss.str();
}

} // namespace

MnPrint::TimingScope::~TimingScope()
{
std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
std::stringstream ss;
ss << fMessage << " " << printTime(end - fBegin);
fMnPrint.Info(ss.str());
}

} // namespace Minuit2
} // namespace ROOT
5 changes: 4 additions & 1 deletion math/minuit2/src/MnSeedGenerator.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
#include "Minuit2/HessianGradientCalculator.h"
#include "Minuit2/MnPrint.h"

#include "Math/Util.h"

#include <cmath>

namespace ROOT {
Expand Down Expand Up @@ -65,7 +67,8 @@ operator()(const MnFcn &fcn, const GradientCalculator &gc, const MnUserParameter
// by default, and we're timing it here. If the G2 is negative, we also have
// to run a NegativeG2LineSearch later, but this is timed separately inside
// the line search.
auto timingScope = std::make_unique<MnPrint::TimingScope>(print, "Evaluated function and gradient in");
auto timingScope = std::make_unique<ROOT::Math::Util::TimingScope>([&print](std::string const &s) { print.Info(s); },
"Evaluated function and gradient in");
MinimumParameters pa(x, fcn(x));
FunctionGradient dgrad = gc(pa);
timingScope.reset();
Expand Down
4 changes: 3 additions & 1 deletion math/minuit2/src/NegativeG2LineSearch.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
#include "Minuit2/VariableMetricEDMEstimator.h"
#include "Minuit2/MnPrint.h"

#include "Math/Util.h"

#include <cmath>

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

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

bool negG2 = HasNegativeG2(st.Gradient(), prec);
if (!negG2)
Expand Down
4 changes: 3 additions & 1 deletion math/minuit2/src/VariableMetricBuilder.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
#include "Minuit2/MnHesse.h"
#include "Minuit2/MnPrint.h"

#include "Math/Util.h"

#include <cmath>
#include <cassert>

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

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

AddResult(result, seed.State());

Expand Down
1 change: 1 addition & 0 deletions math/minuit2/src/math/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ set(MATH_SOURCES
Minimizer.cxx
MinimizerOptions.cxx
ParameterSettings.cxx
Util.cxx
)

copy_standalone(SOURCE ../../../mathcore/inc/Fit DESTINATION ../../inc/Fit
Expand Down
17 changes: 0 additions & 17 deletions roofit/roofitcore/res/RooFitImplHelpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@
#include <RooAbsArg.h>
#include <RooAbsReal.h>

#include <chrono>
#include <functional>
#include <sstream>
#include <string>
#include <string_view>
Expand Down Expand Up @@ -107,21 +105,6 @@ void replaceAll(std::string &inOut, std::string_view what, std::string_view with

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

// Similar to ROOT::Minuit2::MnPrint::TimingScope from the Minuit2
// implementation details.
class TimingScope {

public:
TimingScope(std::function<void(std::string const&)> printer, std::string const &message);

~TimingScope();

private:
std::chrono::steady_clock::time_point fBegin;
std::function<void(std::string const&)> fPrinter;
const std::string fMessage;
};

} // namespace Detail
} // namespace RooFit

Expand Down
3 changes: 2 additions & 1 deletion roofit/roofitcore/src/FitHelpers.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#include <RooFormulaVar.h>

#include <Math/CholeskyDecomp.h>
#include <Math/Util.h>

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

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

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