diff --git a/math/mathcore/CMakeLists.txt b/math/mathcore/CMakeLists.txt index 19256b328f0f2..d10ffd0c00e37 100644 --- a/math/mathcore/CMakeLists.txt +++ b/math/mathcore/CMakeLists.txt @@ -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} diff --git a/math/mathcore/inc/Math/Util.h b/math/mathcore/inc/Math/Util.h index 421f71a5d5327..e30e05f9cd995 100644 --- a/math/mathcore/inc/Math/Util.h +++ b/math/mathcore/inc/Math/Util.h @@ -13,12 +13,13 @@ #ifndef ROOT_Math_Util #define ROOT_Math_Util -#include -#include - +#include #include +#include #include #include +#include +#include // This can be protected against by defining ROOT_Math_VecTypes @@ -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 printer, std::string const &message); + + ~TimingScope(); + +private: + std::chrono::steady_clock::time_point fBegin; + std::function fPrinter; + const std::string fMessage; +}; /** Utility function for conversion to strings diff --git a/math/mathcore/src/Util.cxx b/math/mathcore/src/Util.cxx new file mode 100644 index 0000000000000..7e06866a89c2c --- /dev/null +++ b/math/mathcore/src/Util.cxx @@ -0,0 +1,62 @@ +#include "Math/Util.h" + +ROOT::Math::Util::TimingScope::TimingScope(std::function printer, std::string const &message) + : fBegin{std::chrono::steady_clock::now()}, fPrinter{printer}, fMessage{message} +{ +} + +namespace { + +template +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(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()); +} diff --git a/math/minuit2/inc/Minuit2/MnPrint.h b/math/minuit2/inc/Minuit2/MnPrint.h index 8fd2ff2c08b7f..4044fc2364888 100644 --- a/math/minuit2/inc/Minuit2/MnPrint.h +++ b/math/minuit2/inc/Minuit2/MnPrint.h @@ -13,12 +13,12 @@ #include "Minuit2/MnConfig.h" #include -#include #include #include #include #include #include +#include namespace ROOT { namespace Minuit2 { @@ -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 diff --git a/math/minuit2/src/MnHesse.cxx b/math/minuit2/src/MnHesse.cxx index f988bfe106188..ed7543669a8c0 100644 --- a/math/minuit2/src/MnHesse.cxx +++ b/math/minuit2/src/MnHesse.cxx @@ -25,6 +25,8 @@ #include "./MnFcnCaller.h" +#include "Math/Util.h" + namespace ROOT { namespace Minuit2 { @@ -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(); @@ -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}; diff --git a/math/minuit2/src/MnPrint.cxx b/math/minuit2/src/MnPrint.cxx index 80703b826d237..0ad27bff5ba58 100644 --- a/math/minuit2/src/MnPrint.cxx +++ b/math/minuit2/src/MnPrint.cxx @@ -419,64 +419,5 @@ std::ostream &operator<<(std::ostream &os, const std::pair &poin return os; } -MnPrint::TimingScope::TimingScope(MnPrint &mnPrint, std::string const &message) - : fBegin{std::chrono::steady_clock::now()}, fMnPrint{mnPrint}, fMessage{message} -{ -} - -namespace { - -template -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(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 diff --git a/math/minuit2/src/MnSeedGenerator.cxx b/math/minuit2/src/MnSeedGenerator.cxx index bf6b944a9f6cd..e668c6c3d09a3 100644 --- a/math/minuit2/src/MnSeedGenerator.cxx +++ b/math/minuit2/src/MnSeedGenerator.cxx @@ -32,6 +32,8 @@ #include "Minuit2/HessianGradientCalculator.h" #include "Minuit2/MnPrint.h" +#include "Math/Util.h" + #include namespace ROOT { @@ -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(print, "Evaluated function and gradient in"); + auto timingScope = std::make_unique([&print](std::string const &s) { print.Info(s); }, + "Evaluated function and gradient in"); MinimumParameters pa(x, fcn(x)); FunctionGradient dgrad = gc(pa); timingScope.reset(); diff --git a/math/minuit2/src/NegativeG2LineSearch.cxx b/math/minuit2/src/NegativeG2LineSearch.cxx index 28fad4a5d6c98..4fb3f45e93bc7 100644 --- a/math/minuit2/src/NegativeG2LineSearch.cxx +++ b/math/minuit2/src/NegativeG2LineSearch.cxx @@ -17,6 +17,8 @@ #include "Minuit2/VariableMetricEDMEstimator.h" #include "Minuit2/MnPrint.h" +#include "Math/Util.h" + #include namespace ROOT { @@ -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) diff --git a/math/minuit2/src/VariableMetricBuilder.cxx b/math/minuit2/src/VariableMetricBuilder.cxx index 6c70b89702505..226378e1205cc 100644 --- a/math/minuit2/src/VariableMetricBuilder.cxx +++ b/math/minuit2/src/VariableMetricBuilder.cxx @@ -23,6 +23,8 @@ #include "Minuit2/MnHesse.h" #include "Minuit2/MnPrint.h" +#include "Math/Util.h" + #include #include @@ -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()); diff --git a/math/minuit2/src/math/CMakeLists.txt b/math/minuit2/src/math/CMakeLists.txt index 6039c067457d0..b3589a66af55e 100644 --- a/math/minuit2/src/math/CMakeLists.txt +++ b/math/minuit2/src/math/CMakeLists.txt @@ -30,6 +30,7 @@ set(MATH_SOURCES Minimizer.cxx MinimizerOptions.cxx ParameterSettings.cxx + Util.cxx ) copy_standalone(SOURCE ../../../mathcore/inc/Fit DESTINATION ../../inc/Fit diff --git a/roofit/roofitcore/res/RooFitImplHelpers.h b/roofit/roofitcore/res/RooFitImplHelpers.h index 9b13686b2db73..80404053d8d37 100644 --- a/roofit/roofitcore/res/RooFitImplHelpers.h +++ b/roofit/roofitcore/res/RooFitImplHelpers.h @@ -15,8 +15,6 @@ #include #include -#include -#include #include #include #include @@ -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 printer, std::string const &message); - - ~TimingScope(); - -private: - std::chrono::steady_clock::time_point fBegin; - std::function fPrinter; - const std::string fMessage; -}; - } // namespace Detail } // namespace RooFit diff --git a/roofit/roofitcore/src/FitHelpers.cxx b/roofit/roofitcore/src/FitHelpers.cxx index 7cfc8ab1e93d0..15838b896b857 100644 --- a/roofit/roofitcore/src/FitHelpers.cxx +++ b/roofit/roofitcore/src/FitHelpers.cxx @@ -38,6 +38,7 @@ #include #include +#include #include "ConstraintHelpers.h" #include "RooEvaluatorWrapper.h" @@ -591,7 +592,7 @@ std::unique_ptr minimize(RooAbsReal &pdf, RooAbsReal &nll, RooAbsD std::unique_ptr createNLL(RooAbsPdf &pdf, RooAbsData &data, const RooLinkedList &cmdList) { - auto timingScope = std::make_unique( + auto timingScope = std::make_unique( [&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(); diff --git a/roofit/roofitcore/src/RooFitImplHelpers.cxx b/roofit/roofitcore/src/RooFitImplHelpers.cxx index 170530445a86a..18a104f6f2c05 100644 --- a/roofit/roofitcore/src/RooFitImplHelpers.cxx +++ b/roofit/roofitcore/src/RooFitImplHelpers.cxx @@ -335,65 +335,6 @@ std::string makeSliceCutString(RooArgSet const &sliceDataSet) return cutString.str(); } -TimingScope::TimingScope(std::function printer, std::string const &message) - : fBegin{std::chrono::steady_clock::now()}, fPrinter{printer}, fMessage{message} -{ -} - -namespace { - -template -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(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 - -TimingScope::~TimingScope() -{ - std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now(); - std::stringstream ss; - ss << fMessage << " " << printTime(end - fBegin); - fPrinter(ss.str()); -} - } // namespace Detail } // namespace RooFit diff --git a/roofit/roofitcore/src/RooFuncWrapper.cxx b/roofit/roofitcore/src/RooFuncWrapper.cxx index 93d932a32e2e8..a82aea345cf17 100644 --- a/roofit/roofitcore/src/RooFuncWrapper.cxx +++ b/roofit/roofitcore/src/RooFuncWrapper.cxx @@ -28,6 +28,8 @@ #include #include +#include + #include #include @@ -98,7 +100,7 @@ RooFuncWrapper::RooFuncWrapper(const char *name, const char *title, RooAbsReal & // Declare the function and create its derivative. auto print = [](std::string const &msg) { oocoutI(nullptr, Fitting) << msg << std::endl; }; - RooFit::Detail::TimingScope timingScope(print, "Function JIT time:"); + ROOT::Math::Util::TimingScope timingScope(print, "Function JIT time:"); _funcName = ctx.buildFunction(obj, nodeOutputSizes); _func = reinterpret_cast(gInterpreter->ProcessLine((_funcName + ";").c_str())); @@ -178,7 +180,7 @@ void RooFuncWrapper::createGradient() bool cladSuccess = false; { - RooFit::Detail::TimingScope timingScope(print, "Gradient generation time:"); + ROOT::Math::Util::TimingScope timingScope(print, "Gradient generation time:"); cladSuccess = !gInterpreter->Declare(requestFuncStrm.str().c_str()); } if (cladSuccess) { @@ -192,7 +194,7 @@ void RooFuncWrapper::createGradient() // resolve to the one that we want. Without the static_cast, getting the // function pointer would be ambiguous. std::stringstream ss; - RooFit::Detail::TimingScope timingScope(print, "Gradient IR to machine code time:"); + ROOT::Math::Util::TimingScope timingScope(print, "Gradient IR to machine code time:"); ss << "static_cast(" << gradName << ");"; _grad = reinterpret_cast(gInterpreter->ProcessLine(ss.str().c_str())); _hasGradient = true; diff --git a/tutorials/roofit/roofit/rf101_basics.C b/tutorials/roofit/roofit/rf101_basics.C index 969fed87b0ce1..cf12e5a9137b6 100644 --- a/tutorials/roofit/roofit/rf101_basics.C +++ b/tutorials/roofit/roofit/rf101_basics.C @@ -64,7 +64,8 @@ void rf101_basics() // ----------------------------- // Fit pdf to data - gauss.fitTo(*data, PrintLevel(-1)); + //gauss.fitTo(*data, PrintLevel(-1)); + gauss.fitTo(*data); // Print values of mean and sigma (that now reflect fitted values and errors) mean.Print();