verschiedene Funktionen benchmarken
-
Dieser Beitrag wurde gelöscht!
-
ja cool
via Destruktor kann man das auch machen. Google Benchmark wäre für meine Quick&Dirty tests doch ein kleiner Overhead, den ich vermeiden möchte. Ich hatte dann noch irgendwie eine Überlegung Richtung Funktionspointer, aber nichts konkretes.Habe hier noch eine Lösung:
#define TEST(X) \ { \ int iter = 1000; \ auto start = high_resolution_clock::now(); \ for (int i = 0; i < iter; i++) \ { \ X; \ } \ auto stop = high_resolution_clock::now(); \ auto duration = duration_cast<nanoseconds>(stop - start); \ double time = (double)duration.count() / (double)(iter * 1000); \ std::cout << "time: " << std::fixed << std::setprecision(2) << time << " us" << std::endl; \ } void main() { TEST(meine_tolle_Funktion_A(123, 234, 345)); TEST(meine_tolle_Funktion_B(ABC, DEF)); TEST(meine_tolle_Funktion_C(XYZ)); }
zugegeben, nicht sehr elegant. ...aber es funktioniert xD
Außerdem noch parametrierbareuch allen nochmals danke.
habt ein schönes Wochenende
-
Ich kann dir noch eine C++ Lösung ohne Makros anbieten:
#include <chrono> #include <iomanip> #include <iostream> #include <string> #include <thread> template<typename Callable, typename ...Params> void benchmark( Callable callable, Params&&... p ) { auto const start = std::chrono::high_resolution_clock::now(); callable( std::forward<Params>( p )... ); auto const stop = std::chrono::high_resolution_clock::now(); auto const duration = std::chrono::duration_cast<std::chrono::microseconds>( stop - start ); std::cout << "time: " << std::fixed << std::setprecision(2) << duration.count() << "µs" << std::endl; } void f() { std::this_thread::sleep_for( std::chrono::milliseconds( 100 ) ); } void g( unsigned int duration ) { std::this_thread::sleep_for( std::chrono::milliseconds( duration ) ); } void h( std::size_t count, std::string const& message ) { for( size_t i = 0; i < count; ++i ) { std::cout << i << ": " << message << "\n"; } } int main() { benchmark( f ); benchmark( g, 20 ); benchmark( h, 4, "Hello World" ); return 0; }
-
Oder leicht angepasst mit lambda syntax
#include <chrono> #include <iomanip> #include <iostream> #include <string> #include <thread> #include <functional> void benchmark(const std::function<void()>& callable_wrapper) { auto const start = std::chrono::high_resolution_clock::now(); callable_wrapper(); auto const stop = std::chrono::high_resolution_clock::now(); auto const duration = std::chrono::duration_cast<std::chrono::microseconds>( stop - start ); std::cout << "time: " << std::fixed << std::setprecision(2) << duration.count() << "µs" << std::endl; } void f() { std::this_thread::sleep_for( std::chrono::milliseconds( 100 ) ); } void g( unsigned int duration ) { std::this_thread::sleep_for( std::chrono::milliseconds( duration ) ); } void h( std::size_t count, std::string const& message ) { for( size_t i = 0; i < count; ++i ) { std::cout << i << ": " << message << "\n"; } } int main() { benchmark([]{ f(); }); benchmark([]{ g(20); }); benchmark([]{ h(4, "Hello World"); }); return 0; }
Bisschen mehr Schreibarbeit, aber dafür der normale funktionsaufruf sichtbar.
Oder wahlweise:
benchmark(std::bind(h, 4, "Hello World"));
was auch etwas expliziter ist und mir deswegen besser gefällt (als die Lösung von DocShoe, persönlich würde ich eher lambda als std::bind nutzen)
-
Jau, gefällt mir auch besser
-
vielen Dank
wieder was gelernt
-
@Leon0402 sagte in verschiedene Funktionen benchmarken:
void benchmark(const std::function<void()>& callable_wrapper)
geht das auch irgendwie so?:
void benchmark(const std::function<int()>& callable_wrapper)
bekomme dann immer diesen Fehler in visual studio
Fehler C2664 "void benchmark(const std::function<int (void)> &)" : Konvertierung von Argument 1 von "execute2::<lambda_65e5234ff049377ee7d6eeabbe858357>" in "const std::function<int (void)> &" nicht möglich
-
@SBond sagte in verschiedene Funktionen benchmarken:
geht das auch irgendwie so?:
void benchmark(const std::function<int()>& callable_wrapper)bekomme dann immer diesen Fehler in visual studio
Das sollte gehen. Aber dann musst du deine Lamdas natürlich ändern (z.B.
[](int){}
) und den Aufruf voncallable_wrapper()
logischerweise auch durchcallable_wrapper(irgendein_int)
ändern.std::function
hat auch overhead im Gegensatz zur getemplateten Funktion. Falls du micro-Benchmarking machst, könnte das u.U. relevant sein, wenn du eine Loop um dencallable_wrapper
bauen willst.PS: warum eigentlich die
std::function
alsconst&
? Ich würde die normalerweise per value nehmen, aber kommt wahrscheinlich alles immer darauf anPS2: ACH VERDAMMT! ES IST ZU FRÜH FÜR MICH!
Ich habe stattvoid benchmark(const std::function<int()>& callable_wrapper)
irgendwievoid benchmark(const std::function<void(int)>& callable_wrapper)
gelesen. Sorry.Aber auch
void benchmark(const std::function<int()>& callable_wrapper)
geht natürlich, dann musst du in deinem Lambda aber einen int oder irgendwas in-int-konvertierbares returnen. Wie sieht denn dein Lambda aus?
-
vielen Dank! ...und ich kam gestern selbst nach vielen Stunden einfach nicht darauf.
Hier mal der angepasste code von Leon0402:
#include <chrono> #include <iomanip> #include <iostream> #include <string> #include <thread> #include <functional> void benchmark(const std::function<int()>& callable_wrapper) { int retVal = 0; auto const start = std::chrono::high_resolution_clock::now(); retVal = callable_wrapper(); auto const stop = std::chrono::high_resolution_clock::now(); auto const duration = std::chrono::duration_cast<std::chrono::microseconds>( stop - start ); std::cout << "time: " << std::fixed << std::setprecision(2) << duration.count() << "µs" << " retVal:" << retVal << std::endl; } void f() { std::this_thread::sleep_for( std::chrono::milliseconds( 100 ) ); return 1; } void g( unsigned int duration ) { std::this_thread::sleep_for( std::chrono::milliseconds( duration ) ); return 2; } void h( std::size_t count, std::string const& message ) { for( size_t i = 0; i < count; ++i ) { std::cout << i << ": " << message << "\n"; } return 3; } int main() { benchmark([]{ return f(); }); benchmark([]{ return g(20); }); benchmark([]{ return h(4, "Hello World"); }); return 0; }
...ist nur noch ein nice to have....
Wenn man in der benchmark-funktion noch einen Parameter anpassen will geht so etwas auch? Ein beispiel wäre hier benchm_v2(), dass natürlich so nicht geht:int test_func(int A, int B) { return A + B; } void benchm(const std::function<int()>& fkt, std::string testStr) { // [...] int retval = fkt(); // [...] std::cout << testStr << " --> " << retval << std::endl; } void benchm_v2(const std::function<int()>& fkt, int paramA, int paramB, std::string testStr) { // [...] int retval = fkt(paramA+123, paramB); // [...] std::cout << testStr << " --> " << retval << std::endl; } int main(int argc, char* argv[]) { int myA = 3; int myB = 5; std::string testStr = "A + B"; benchm([&] {return test_func(myA, myB);}, testStr); // --> geht benchm_v2([&] {return test_func();}, myA, myB, testStr); // --> geht nicht return 0; }
Bzw gibt es Funktionszeiger, bei der die Parameterliste nicht angegeben werden muss? ...ich kenne von damals noch solche Konstrukte:
int (*fptr)(int, int) = &test_func; fptr(myA, myB);
..aber da gebe ich ja auch die Parameterliste bereits an.
....erstmal einen Kaffee.
-
@SBond sagte in verschiedene Funktionen benchmarken:
benchm_v2([&] {return test_func();}, myA, myB, testStr); // --> geht nicht
Du kannst doch die getemplatete Lösung von @DocShoe ohne std::function dafür verwenden. Was ist denn überhaupt der Sinn deines Lambdas in dem "geht nicht"-Fall?!
Oder ändere
void benchm_v2(const std::function<int()>& fkt, int paramA, int paramB, std::string testStr)
in
void benchm_v2(const std::function<int(int, int)>& fkt, int paramA, int paramB, std::string testStr)
und
benchm_v2([&] {return test_func();}, myA, myB, testStr); // --> geht nicht
in
benchm_v2(test_func, myA, myB, testStr); // --> geht
-
ahh..... vielen Dank. Stimmt geht beides
vielen Dank.Wegen dem Lambda.... Das hat im Beispiel keine nähere Bedeutung. Ich bin gerade dabei mich wieder etwas einzuüben.
Nochmals vielen Dank für die Hilfe