From 8ab149dc49251362a227aaf9242a6882531a445a Mon Sep 17 00:00:00 2001 From: Dominik Baack <dominik.baack@tu-dortmund.de> Date: Fri, 18 Sep 2020 14:22:30 +0200 Subject: [PATCH] fixed template class stuff added missing unit test --- Processes/DevTools/Analytics/CMakeLists.txt | 31 ++-- Processes/DevTools/Analytics/ExecTime.cc | 113 ++++++++----- Processes/DevTools/Analytics/ExecTime.h | 157 ++++++++++--------- Processes/DevTools/Analytics/testExecTime.cc | 48 +++++- 4 files changed, 220 insertions(+), 129 deletions(-) diff --git a/Processes/DevTools/Analytics/CMakeLists.txt b/Processes/DevTools/Analytics/CMakeLists.txt index 422175428..9818a5cca 100644 --- a/Processes/DevTools/Analytics/CMakeLists.txt +++ b/Processes/DevTools/Analytics/CMakeLists.txt @@ -13,11 +13,11 @@ set ( corsika/process/devtools ) -add_library (ProcessDevTools STATIC ${MODEL_SOURCES}) -CORSIKA_COPY_HEADERS_TO_NAMESPACE (ProcessDevTools ${MODEL_NAMESPACE} ${MODEL_HEADERS}) +add_library (DevTools_Analytic STATIC ${MODEL_SOURCES}) +CORSIKA_COPY_HEADERS_TO_NAMESPACE (DevTools_Analytic ${MODEL_NAMESPACE} ${MODEL_HEADERS}) set_target_properties ( - ProcessDevTools + DevTools_Analytic PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION 1 @@ -25,32 +25,39 @@ set_target_properties ( # target dependencies on other libraries (also the header onlys) target_link_libraries ( - ProcessDevTools - CORSIKAsetup + DevTools_Analytic + CORSIKAprocesssequence + CORSIKAunits + CORSIKAthirdparty ) target_include_directories ( - ProcessDevTools + DevTools_Analytic INTERFACE $<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include> $<INSTALL_INTERFACE:include/include> ) install ( - TARGETS ProcessDevTools + TARGETS DevTools_Analytic LIBRARY DESTINATION lib - ARCHIVE DESTINATION lib - PUBLIC_HEADER DESTINATION include/${MODEL_NAMESPACE} + ARCHIVE DESTINATION lib ) # -------------------- # code unit testing -CORSIKA_ADD_TEST (testExecTime testExecTime.cc) +CORSIKA_ADD_TEST (testExecTime + SOURCES + testExecTime.cc + ${MODEL_HEADERS} +) + target_link_libraries ( - testExecTime ProcessDevTools - CORSIKAsetup + testExecTime + DevTools_Analytic DevTools_Dummy + CORSIKAtesting CORSIKAthirdparty # for catch2 ) diff --git a/Processes/DevTools/Analytics/ExecTime.cc b/Processes/DevTools/Analytics/ExecTime.cc index 18c31b5a1..8b7199e68 100644 --- a/Processes/DevTools/Analytics/ExecTime.cc +++ b/Processes/DevTools/Analytics/ExecTime.cc @@ -14,51 +14,90 @@ namespace corsika::process { namespace devtools { - template <class T> - void ExecTime<T>::start() { - fStart = std::chrono::steady_clock::now(); - } + - template <class T> - void ExecTime<T>::stop() { - auto end = std::chrono::steady_clock::now(); - std::chrono::microseconds timeDiv = - std::chrono::duration_cast<std::chrono::microseconds>(end - start); - - fElapsedSum += timeDiv; - fN++; - - if (fMax < timeDiv) fMax = timeDiv; - - if (timeDiv < fMin) fMin = timeDiv; - - auto delta = timeDiv - fMean; - fMean += delta / fN; - - auto delta2 = timeDiv - fMean; + } // namespace devtools +} // namespace corsika::process - fMean2 += delta * delta2; - } +/* + template <typename T, bool> + class ExecTime_BoundaryCrossing {}; template <typename T> - double ExecTime<T>::mean() { - return fMean; - } + class ExecTime_BoundaryCrossing<T, true> : protected T { + public: + template < + typename Particle, typename VTNType, + typename std::enable_if_t< + std::is_base_of<BoundaryCrossingProcess<typename T::_TDerived>, T>::value, + int> = 0> + EProcessReturn DoBoundaryCrossing(Particle& p, VTNType const& from, + VTNType const& to) { + + return T::DoBoundaryCrossing(p, from, to); + } + }; + + template <typename T, bool> + class ExecTime_Continuous {}; template <typename T> - double ExecTime<T>::var() { - return fMean2 / count; - } + class ExecTime_Continuous<T, true> : protected T { + public: + template <typename Particle, typename Track> + EProcessReturn DoContinuous(Particle& p, Track const& t) const { + return T::DoContinous(p, t); + } + + template <typename Particle, typename Track> + units::si::LengthType MaxStepLength(Particle const& p, Track const& track) const { + return T::MaxStepLength(p, track); + } + }; + + template <typename T, bool> + class ExecTime_Decay {}; template <typename T> - double ExecTime<T>::min() { - return fMin; - } + class ExecTime_Decay<T, true> : protected T { + public: + template <typename Particle> + EProcessReturn DoDecay(Particle& p) { + return T::DoDecay(p); + } + + template <typename Particle> + corsika::units::si::TimeType GetLifetime(Particle& p) { + return T::GetLifetime(p); + } + }; + + template <typename T, bool> + class ExecTime_Interaction {}; template <typename T> - double ExecTime<T>::max() { - return fMax; - } + class ExecTime_Interaction<T, true> : protected T { + public: + template <typename Particle> + EProcessReturn DoInteraction(Particle& p) { + return T::DoInteraction(p); + } + + template <typename Particle> + corsika::units::si::GrammageType GetInteractionLength(Particle& p) { + return T::GetInteractionLength(p); + } + }; + + template <typename T, bool> + class ExecTime_Secondaries {}; - } // namespace devtools -} // namespace corsika::process \ No newline at end of file + template <typename T> + class ExecTime_Secondaries<T, true> : protected T { + public: + template <typename Secondaries> + inline EProcessReturn DoSecondaries(Secondaries& sec) { + return T::DoSecondaries(sec); + } + }; + */ \ No newline at end of file diff --git a/Processes/DevTools/Analytics/ExecTime.h b/Processes/DevTools/Analytics/ExecTime.h index aef2c588d..25524c03e 100644 --- a/Processes/DevTools/Analytics/ExecTime.h +++ b/Processes/DevTools/Analytics/ExecTime.h @@ -21,117 +21,118 @@ namespace corsika::process { namespace devtools { - template <typename T, bool> - class ExecTime_BoundaryCrossing {}; - template <typename T> - class ExecTime_BoundaryCrossing<T, true> : protected T { + class ExecTime : private T { + private: + std::chrono::high_resolution_clock::time_point fStart; + std::chrono::duration<double,std::micro> fElapsedSum; + double fMean; + double fMean2; + double fMin; + double fMax; + long long fN; + + protected: public: - template < - typename Particle, typename VTNType, - typename std::enable_if_t< - std::is_base_of<BoundaryCrossingProcess<typename T::_TDerived>, T>::value, - int> = 0> + ExecTime() { + fMin = std::numeric_limits<long long>::max(); + fMax = 0; + fMean = 0; + fMean2 = 0; + fN = 0; + } + + void start() { fStart = std::chrono::high_resolution_clock::now(); } + void stop() { + auto end = std::chrono::high_resolution_clock::now(); + std::chrono::duration<double,std::micro> timeDiv = + std::chrono::duration_cast< std::chrono::duration<double,std::micro> >(end - fStart); + + fElapsedSum += timeDiv; + fN = fN + 1; + + if (fMax < timeDiv.count()) fMax = timeDiv.count(); + + if (timeDiv.count() < fMin) fMin = timeDiv.count(); + + double delta = timeDiv.count() - fMean; + fMean += delta / static_cast<double>(fN); + + double delta2 = timeDiv.count() - fMean; + + fMean2 += delta * delta2; + } + + double mean() const { return fMean; } + double min() const { return fMin; } + double max() const { return fMax; } + double var() const { return fMean2 / fN; } + double sumTime() const { return fElapsedSum.count(); } + + template <typename Particle, typename VTNType> EProcessReturn DoBoundaryCrossing(Particle& p, VTNType const& from, VTNType const& to) { - return T::DoBoundaryCrossing(p, from, to); + this->start(); + auto r = T::DoBoundaryCrossing(p, from, to); + this->stop(); + return r; } - }; - - template <typename T, bool> - class ExecTime_Continuous {}; - template <typename T> - class ExecTime_Continuous<T, true> : protected T { - public: template <typename Particle, typename Track> EProcessReturn DoContinuous(Particle& p, Track const& t) const { - return T::DoContinous(p, t); + this->start(); + auto r = T::DoContinous(p, t); + this->stop(); + return r; } template <typename Particle, typename Track> units::si::LengthType MaxStepLength(Particle const& p, Track const& track) const { - return T::MaxStepLength(p, track); + this->start(); + auto r = T::MaxStepLength(p, track); + this->stop(); + return r; } - }; - template <typename T, bool> - class ExecTime_Decay {}; - - template <typename T> - class ExecTime_Decay<T, true> : protected T { - public: template <typename Particle> EProcessReturn DoDecay(Particle& p) { - return T::DoDecay(p); + this->start(); + auto r = T::DoDecay(p); + this->stop(); + return r; } template <typename Particle> corsika::units::si::TimeType GetLifetime(Particle& p) { - return T::GetLifetime(p); + this->start(); + auto r = T::GetLifetime(p); + this->stop(); + return r; } - }; - - template <typename T, bool> - class ExecTime_Interaction {}; - template <typename T> - class ExecTime_Interaction<T, true> : protected T { - public: template <typename Particle> EProcessReturn DoInteraction(Particle& p) { - return T::DoInteraction(p); + this->start(); + auto r = T::DoInteraction(p); + this->stop(); + return r; } template <typename Particle> corsika::units::si::GrammageType GetInteractionLength(Particle& p) { - return T::GetInteractionLength(p); + this->start(); + auto r = T::GetInteractionLength(p); + this->stop(); + return r; } - }; - template <typename T, bool> - class ExecTime_Secondaries {}; - - template <typename T> - class ExecTime_Secondaries<T, true> : protected T { - public: template <typename Secondaries> inline EProcessReturn DoSecondaries(Secondaries& sec) { - return T::DoSecondaries(sec); + this->start(); + auto r = T::DoSecondaries(sec); + this->stop(); + return r; } - }; - - template <typename T> - class ExecTime - : public ExecTime_BoundaryCrossing< - T, - std::is_base_of<BoundaryCrossingProcess<typename T::_TDerived>, T>::value>, - public ExecTime_Continuous< - T, std::is_base_of<ContinuousProcess<typename T::_TDerived>, T>::value>, - public ExecTime_Decay< - T, std::is_base_of<DecayProcess<typename T::_TDerived>, T>::value>, - public ExecTime_Interaction< - T, std::is_base_of<InteractionProcess<typename T::_TDerived>, T>::value>, - public ExecTime_Secondaries< - T, std::is_base_of<SecondariesProcess<typename T::_TDerived>, T>::value> { - private: - std::chrono::microseconds fStart; - std::chrono::microseconds fElapsedSum; - std::chrono::microseconds fMean; - std::chrono::microseconds fMean2; - std::chrono::microseconds fMin; - std::chrono::microseconds fMax; - long long fN; - - void start(); - void stop(); - - protected: - public: - double mean(); - double min(); - double max(); - double var(); /* // Stack diff --git a/Processes/DevTools/Analytics/testExecTime.cc b/Processes/DevTools/Analytics/testExecTime.cc index 853ccd2d2..f5cd643f7 100644 --- a/Processes/DevTools/Analytics/testExecTime.cc +++ b/Processes/DevTools/Analytics/testExecTime.cc @@ -18,12 +18,14 @@ #include <corsika/process/devtools/DummyInteractionProcess.h> #include <corsika/process/devtools/DummySecondariesProcess.h> +#include <random> + using namespace corsika::process; using namespace corsika::process::devtools; TEST_CASE("ContinuousProcess interface", "[proccesses][DevTools ExecTime]") { - ExecTime<DummyBoundaryCrossingProcess<100>> execTime; + ExecTime<DummyBoundaryCrossingProcess<50>> execTime; int tmp = 0; SECTION("BoundaryCrossing") { @@ -31,6 +33,48 @@ TEST_CASE("ContinuousProcess interface", "[proccesses][DevTools ExecTime]") { REQUIRE(execTime.DoBoundaryCrossing(tmp, 0, 0) == EProcessReturn::eOk); auto end = std::chrono::steady_clock::now(); REQUIRE(std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() == - Approx(100).margin(1)); + Approx(50).margin(1)); + + for (int i = 0; i < 100; i++) execTime.DoBoundaryCrossing(tmp, 0, 0); + + REQUIRE(execTime.mean() == Approx(50 * 1000).margin(1 * 1000)); + + REQUIRE(execTime.sumTime() == Approx(50 * 100 * 1000).margin(100 * 1000)); + + REQUIRE(execTime.var() == Approx(0).margin(20000)); + } + + SECTION("TestMeanAlgo") { + std::default_random_engine generator; + std::normal_distribution<double> distribution(10000.0, 200.0); + + double fStart; + double fElapsedSum; + double fMean; + double fMean2; + long long fMin; + long long fMax; + long long fN; + + for (int i = 0; i < 1000000; i++) { + auto timeDiv = distribution(generator); + + fElapsedSum += timeDiv; + fN = fN + 1; + + if (fMax < timeDiv) fMax = timeDiv; + + if (timeDiv < fMin) fMin = timeDiv; + + double delta = timeDiv - fMean; + fMean += delta / static_cast<double>(fN); + + double delta2 = timeDiv - fMean; + + fMean2 += delta * delta2; + } + + REQUIRE(fMean2 / fN == Approx(200*200).margin(200)); // Varianz + REQUIRE(fMean == Approx(10000).margin(10)); } } -- GitLab