IAP GITLAB

Skip to content
Snippets Groups Projects
Commit c84760b5 authored by Dominik Baack's avatar Dominik Baack Committed by ralfulrich
Browse files

Added Analytic functions to framework

parent 8b62c42c
No related branches found
No related tags found
No related merge requests found
/*
* (c) Copyright 2020 CORSIKA Project, corsika-project@lists.kit.edu
*
* This software is distributed under the terms of the GNU General Public
* Licence version 3 (GPL Version 3). See file LICENSE for a full version of
* the license.
*/
// Another possibility:
// https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Execute-Around_Pointer
// for a more global approach
//
// In this case here only a single function is measured via member function pointer.
#pragma once
#include <chrono>
#include <utility>
namespace corsika {
// Common
template <typename TClass, typename TRet, typename... TArgs,
TRet (TClass::*TFuncPtr)(TArgs...)>
ClassTimer<TRet (TClass::*)(TArgs...), TFuncPtr>::ClassTimer(TClass& obj)
: obj_(obj) {}
template <typename TClass, typename TRet, typename... TArgs,
TRet (TClass::*TFuncPtr)(TArgs...)>
TRet ClassTimer<TRet (TClass::*)(TArgs...), TFuncPtr>::call(TArgs... args) {
start_ = TClock::now();
auto tmp = (obj_.*TFuncPtr)(std::forward<TArgs>(args)...);
timeDiff_ = std::chrono::duration_cast<TDuration>(TClock::now() - start_);
return tmp;
}
template <typename TClass, typename TRet, typename... TArgs,
TRet (TClass::*TFuncPtr)(TArgs...)>
inline typename ClassTimer<TRet (TClass::*)(TArgs...), TFuncPtr>::TDuration
ClassTimer<TRet (TClass::*)(TArgs...), TFuncPtr>::getTime() const {
return timeDiff_;
}
// Specialisation 1
template <typename TClass, typename... TArgs, void (TClass::*TFuncPtr)(TArgs...)>
ClassTimer<void (TClass::*)(TArgs...), TFuncPtr>::ClassTimer(TClass& obj)
: obj_(obj) {}
template <typename TClass, typename... TArgs, void (TClass::*TFuncPtr)(TArgs...)>
void ClassTimer<void (TClass::*)(TArgs...), TFuncPtr>::call(TArgs... args) {
start_ = TClock::now();
(obj_.*TFuncPtr)(std::forward<TArgs>(args)...);
timeDiff_ = std::chrono::duration_cast<TDuration>(TClock::now() - start_);
return;
}
template <typename TClass, typename... TArgs, void (TClass::*TFuncPtr)(TArgs...)>
inline typename ClassTimer<void (TClass::*)(TArgs...), TFuncPtr>::TDuration
ClassTimer<void (TClass::*)(TArgs...), TFuncPtr>::getTime() const {
return timeDiff_;
}
/// Specialisation 2
template <typename TClass, typename TRet, typename... TArgs,
TRet (TClass::*TFuncPtr)(TArgs...) const>
ClassTimer<TRet (TClass::*)(TArgs...) const, TFuncPtr>::ClassTimer(TClass& obj)
: obj_(obj) {}
template <typename TClass, typename TRet, typename... TArgs,
TRet (TClass::*TFuncPtr)(TArgs...) const>
TRet ClassTimer<TRet (TClass::*)(TArgs...) const, TFuncPtr>::call(TArgs... args) {
start_ = TClock::now();
auto tmp = (obj_.*TFuncPtr)(std::forward<TArgs>(args)...);
timeDiff_ = std::chrono::duration_cast<TDuration>(TClock::now() - start_);
return tmp;
}
template <typename TClass, typename TRet, typename... TArgs,
TRet (TClass::*TFuncPtr)(TArgs...) const>
inline typename ClassTimer<TRet (TClass::*)(TArgs...) const, TFuncPtr>::TDuration
ClassTimer<TRet (TClass::*)(TArgs...) const, TFuncPtr>::getTime() const {
return timeDiff_;
}
/// Specialisation 3
template <typename TClass, typename... TArgs, void (TClass::*TFuncPtr)(TArgs...) const>
ClassTimer<void (TClass::*)(TArgs...) const, TFuncPtr>::ClassTimer(TClass& obj)
: obj_(obj) {}
template <typename TClass, typename... TArgs, void (TClass::*TFuncPtr)(TArgs...) const>
void ClassTimer<void (TClass::*)(TArgs...) const, TFuncPtr>::call(TArgs... args) {
start_ = TClock::now();
(obj_.*TFuncPtr)(std::forward<TArgs>(args)...);
timeDiff_ = std::chrono::duration_cast<TDuration>(TClock::now() - start_);
return;
}
template <typename TClass, typename... TArgs, void (TClass::*TFuncPtr)(TArgs...) const>
inline typename ClassTimer<void (TClass::*)(TArgs...) const, TFuncPtr>::TDuration
ClassTimer<void (TClass::*)(TArgs...) const, TFuncPtr>::getTime() const {
return timeDiff_;
}
} // namespace corsika
\ No newline at end of file
/*
* (c) Copyright 2020 CORSIKA Project, corsika-project@lists.kit.edu
*
* This software is distributed under the terms of the GNU General Public
* Licence version 3 (GPL Version 3). See file LICENSE for a full version of
* the license.
*/
#pragma once
#include <chrono>
#include <utility>
namespace corsika {
template <typename TFunc, typename TClock, typename TDuration>
FunctionTimer<TFunc, TClock, TDuration>::FunctionTimer(TFunc f)
: function_(f) {}
template <typename TFunc, typename TClock, typename TDuration>
template <typename... TArgs>
auto FunctionTimer<TFunc, TClock, TDuration>::operator()(TArgs&&... args)
-> std::invoke_result_t<TFunc, TArgs...> {
start_ = TClock::now();
auto tmp = function_(std::forward<TArgs>(args)...);
timeDiff_ = std::chrono::duration_cast<TDuration>(TClock::now() - start_);
return tmp;
}
template <typename TFunc, typename TClock, typename TDuration>
inline TDuration FunctionTimer<TFunc, TClock, TDuration>::getTime() const {
return timeDiff_;
}
} // namespace corsika
/*
* (c) Copyright 2020 CORSIKA Project, corsika-project@lists.kit.edu
*
* This software is distributed under the terms of the GNU General Public
* Licence version 3 (GPL Version 3). See file LICENSE for a full version of
* the license.
*/
// Another possibility:
// https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Execute-Around_Pointer
// for a more global approach
//
// In this case here only a single function is measured via member function pointer.
#pragma once
#include <chrono>
#include <utility>
namespace corsika {
template <class TClass>
class ClassTimerImpl {
protected:
/// Default clock used for time measurement
using TClock = std::chrono::high_resolution_clock;
/// Internal resolution of the time measurement
using TDuration = std::chrono::microseconds;
/// Reference to the class object on which the function should be called
TClass& obj_;
/// Startpoint of time measurement
typename TClock::time_point start_;
/// Measured runtime of the function
TDuration timeDiff_;
};
/// Measure the runtime of a single class function
/**
* @tparam TClassFunc Type of the member function pointer that should be wrapped
* @tparam TFunc Actual function of the type defined in TClass
*/
template <typename TClassFunc, TClassFunc TFunc>
class ClassTimer;
/// Measure the runtime of a single class function
/** Specialisation to capture exact information about the composition of the member
* function pointer used.
*
* This class wrapes a single function and allowes the measureing of its runtime if it
* called via the "call(...)" function
*
* @tparam TClass Class of the function that should be wrapped
* @tparam TRet Return value of the wrapped function
* @tparam TArgs Arguments passed to the wrapped function
* @tparam TFuncPtr Actual function of the type defined by TRet
* TClass::TFuncPtr(TArgs...)
*/
template <typename TClass, typename TRet, typename... TArgs,
TRet (TClass::*TFuncPtr)(TArgs...)>
class ClassTimer<TRet (TClass::*)(TArgs...), TFuncPtr> : ClassTimerImpl<TClass>{
private:
public:
ClassTimer(TClass& obj);
/// Executes the wrapped function
/** This function executes and measure the runtime of the wrapped function with the
* highest precision available (high_resolution_clock).
*
* @param args Arguments are perfect forwarded to the wrapped function.
* @return Returns the return value of the wrapped function. This value get copied
* during the process and therefore must be copy constructible!
*/
TRet call(TArgs... args);
/// returns the last runtime of the wraped function accessed via call
inline TDuration getTime() const;
};
/// Specialisation for member functions without return value
template <typename TClass, typename... TArgs, void (TClass::*TFuncPtr)(TArgs...)>
class ClassTimer<void (TClass::*)(TArgs...), TFuncPtr> : ClassTimerImpl<TClass> {
private:
using TClock = std::chrono::high_resolution_clock;
using TDuration = std::chrono::microseconds;
public:
ClassTimer(TClass& obj);
void call(TArgs... args);
inline TDuration getTime() const;
};
/// Specialisation for const member functions
template <typename TClass, typename TRet, typename... TArgs,
TRet (TClass::*TFuncPtr)(TArgs...) const>
class ClassTimer<TRet (TClass::*)(TArgs...) const, TFuncPtr> : ClassTimerImpl<TClass>{
public:
ClassTimer(TClass& obj);
TRet call(TArgs... args);
inline TDuration getTime() const;
};
/// Specialisation for const member functions without return value
template <typename TClass, typename... TArgs, void (TClass::*TFuncPtr)(TArgs...) const>
class ClassTimer<void (TClass::*)(TArgs...) const, TFuncPtr> : ClassTimerImpl<TClass> {
public:
ClassTimer(TClass& obj);
void call(TArgs... args);
inline TDuration getTime() const;
};
} // namespace corsika
#include <corsika/detail/framework/analytics/ClassTimer.inl>
\ No newline at end of file
/*
* (c) Copyright 2020 CORSIKA Project, corsika-project@lists.kit.edu
*
* This software is distributed under the terms of the GNU General Public
* Licence version 3 (GPL Version 3). See file LICENSE for a full version of
* the license.
*/
#pragma once
#include <chrono>
#include <utility>
namespace corsika {
/// Wraps and measures the runtime of a single function type object
/**
*
* @tparam TFunc funtion pointer that should be wrapped
* @tparam TClock type of the clock that should be used for measurements, default is
* high_resolution_clock
* @tparam TDuration type of std::duration to measure the elapsed time, default is
* microseconds
*/
template <typename TFunc, typename TClock = std::chrono::high_resolution_clock,
typename TDuration = std::chrono::microseconds>
class FunctionTimer {
public:
/** Constructs the wrapper with the given functionpointer
* @param f Function or functor whose runtime should be measured
**/
FunctionTimer(TFunc f);
/** Functor for calling the wrapped function
* This functor calls the wrapped function and measures the elapsed time between call
*and return. The return value needs to be copy constructible.
* @tparam TArgs Parameter types that are forwarded to the function. The use of
*correct types is the responsibility of the user, no checks are done.
* @param args Arguments are forwarded to the wrapped function. This method does not
*support overloaded function resolution.
* @return The return value of the wrapped function is temporarily copied and then
*returned by value
**/
template <typename... TArgs>
auto operator()(TArgs&&... args) -> std::invoke_result_t<TFunc, TArgs...>;
/**
* Returns the runtime of the last call to the wrapped function
* @return Returns the measured runtime of the wrapped function/functor in the unit
*given by TDuration
**/
inline TDuration getTime() const;
private:
typename TClock::time_point start_;
TDuration timeDiff_;
TFunc function_;
};
} // namespace corsika
#include <corsika/detail/framework/analytics/FunctionTimer.inl>
\ No newline at end of file
set (test_framework_sources
# testCascade.cpp this is most important, but whole content of former Processes folder missing yet
testClassTimer.cpp
testCombinedStack.cpp
testCOMBoost.cpp
#testCorsikaFenv.cpp # does not work because of use of exceptions in catch2
testFourVector.cpp
testFunctionTimer.cpp
testGeometry.cpp
testLogging.cpp
TestMain.cpp
......
/*
* (c) Copyright 2020 CORSIKA Project, corsika-project@lists.kit.edu
*
* This software is distributed under the terms of the GNU General Public
* Licence version 3 (GPL Version 3). See file LICENSE for a full version of
* the license.
*/
#include <corsika/framework/analytics/ClassTimer.hpp>
#include <catch2/catch.hpp>
#include <chrono>
#include <iostream>
#include <thread>
using namespace corsika;
class _foo2 {
public:
int inside(int) { return 123; }
int inside(char) { return 312; }
};
class _foo1 : public _foo2 {
public:
int inside(int) { return 123; }
};
class foo : public _foo1 {
public:
int bar() {
std::this_thread::sleep_for(std::chrono::milliseconds(100));
return 31415;
}
void bar2(int) {
std::this_thread::sleep_for(std::chrono::milliseconds(100));
return;
}
inline void bar_const() const {
std::this_thread::sleep_for(std::chrono::milliseconds(100));
return;
}
int inside() {
auto tc = corsika::ClassTimer<int (_foo1::*)(int), &_foo1::inside>(*this);
auto r = tc.call(1);
return r;
}
};
template <typename TType, TType>
class timeMin;
template <typename TType, typename TRet, typename... TArgs,
TRet (TType::*TFuncPtr)(TArgs...)>
class timeMin<TRet (TType::*)(TArgs...), TFuncPtr> {
private:
TType& obj_;
public:
timeMin(TType& obj)
: obj_(obj) {}
TRet call(TArgs... args) { return (obj_.*TFuncPtr)(std::forward<TArgs>(args)...); }
};
// quasi processor
class fooT1 {
public:
template <typename T1, typename T2>
int inside_t(T1 a, T2 b, T2 c) {
return 123;
}
};
// exec_time_impl
template <typename T>
class fooT2 : public T {
public:
using _T = T;
};
// exec_time_impl
template <typename T>
class fooT3 : public fooT2<T> {
public:
template <typename T1, typename T2>
int inside_t(T1 a, T2 b, T2 c) {
auto tc =
timeMin<int (fooT2<T>::_T::*)(T1, T2, T2),
&fooT2<T>::_T::template inside_t<T1, T2>>(*this); // <- dependent template
auto r = tc.call(a, b, c);
return r;
}
};
TEST_CASE("ClassTimer", "[Timer]") {
SECTION("Measure runtime of a function without arguments") {
auto test = foo();
auto tc = corsika::ClassTimer<decltype(&foo::bar), &foo::bar>(test);
tc.call();
CHECK(tc.getTime().count() == Approx(100000).margin(10000));
}
SECTION("Measure runtime of a function with arguments") {
auto test = foo();
auto tc = corsika::ClassTimer<decltype(&foo::bar2), &foo::bar2>(test);
tc.call(1);
CHECK(tc.getTime().count() == Approx(100000).margin(10000));
}
SECTION("Measure runtime of a const function without arguments") {
auto test = foo();
auto tc =
corsika::ClassTimer<decltype(&foo::bar_const), &foo::bar_const>(test);
tc.call();
CHECK(tc.getTime().count() == Approx(100000).margin(10000));
}
SECTION("Measure runtime of function inside class") {
auto test = foo();
CHECK(test.inside() == 123);
}
SECTION("Measure runtime of function inside class") {
auto test = fooT3<fooT1>();
CHECK(test.inside_t(1, 'a', 'b') == 123);
}
}
/*
* (c) Copyright 2020 CORSIKA Project, corsika-project@lists.kit.edu
*
* This software is distributed under the terms of the GNU General Public
* Licence version 3 (GPL Version 3). See file LICENSE for a full version of
* the license.
*/
#include <corsika/framework/analytics/FunctionTimer.hpp>
#include <catch2/catch.hpp>
#include <chrono>
#include <iostream>
#include <thread>
using namespace corsika;
int testFunc() {
std::this_thread::sleep_for(std::chrono::milliseconds(100));
return 31415;
}
class TestClass {
public:
int operator()() {
std::this_thread::sleep_for(std::chrono::milliseconds(100));
return 31415;
}
};
TEST_CASE("FunctionTimer", "[Timer]") {
SECTION("Measure runtime of a free function") {
auto test = corsika::FunctionTimer(testFunc);
std::cout << test() << std::endl;
std::cout << test.getTime().count() << std::endl;
}
SECTION("Measure runtime of a class functor") {
TestClass testC;
auto test = corsika::FunctionTimer(testC);
std::cout << test() << std::endl;
std::cout << test.getTime().count() << std::endl;
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment