In Scott Meyers Buch habe ich ein Beispiel für einen universellen generischen Lambda-Ausdruck gefunden, mit dem die Ausführungszeit von Funktionen gemessen werden kann. (C ++ 14)
auto timeFuncInvocation =
[](auto&& func, auto&&... params) {
// get time before function invocation
const auto& start = std::chrono::high_resolution_clock::now();
// function invocation using perfect forwarding
std::forward<decltype(func)>(func)(std::forward<decltype(params)>(params)...);
// get time after function invocation
const auto& stop = std::chrono::high_resolution_clock::now();
return stop - start;
};
Das Problem ist, dass Sie nur eine Ausführung messen, sodass die Ergebnisse sehr unterschiedlich sein können. Um ein zuverlässiges Ergebnis zu erhalten, sollten Sie eine große Anzahl von Ausführungen messen. Laut Andrei Alexandrescu Vortrag auf der Code :: Dive 2015 Konferenz - Schreiben von Fast Code I:
Gemessene Zeit: tm = t + tq + tn + bis
wo:
tm - gemessene (beobachtete) Zeit
t - der tatsächliche Zeitpunkt des Interesses
tq - Zeit, die durch Quantisierungsrauschen hinzugefügt wird
tn - Zeit, die durch verschiedene Geräuschquellen hinzugefügt wird
zu - Overhead-Zeit (Messen, Schleifen, Aufrufen von Funktionen)
Nach dem, was er später in der Vorlesung sagte, sollten Sie ein Minimum dieser großen Anzahl von Ausführungen als Ergebnis nehmen. Ich ermutige Sie, sich die Vorlesung anzusehen, in der er erklärt, warum.
Es gibt auch eine sehr gute Bibliothek von Google - https://github.com/google/benchmark . Diese Bibliothek ist sehr einfach zu bedienen und leistungsstark. Sie können einige Vorträge von Chandler Carruth auf Youtube lesen, wo er diese Bibliothek in der Praxis nutzt. Zum Beispiel CppCon 2017: Chandler Carruth „Going Nowhere Faster“;
Anwendungsbeispiel:
#include <iostream>
#include <chrono>
#include <vector>
auto timeFuncInvocation =
[](auto&& func, auto&&... params) {
// get time before function invocation
const auto& start = high_resolution_clock::now();
// function invocation using perfect forwarding
for(auto i = 0; i < 100000/*largeNumber*/; ++i) {
std::forward<decltype(func)>(func)(std::forward<decltype(params)>(params)...);
}
// get time after function invocation
const auto& stop = high_resolution_clock::now();
return (stop - start)/100000/*largeNumber*/;
};
void f(std::vector<int>& vec) {
vec.push_back(1);
}
void f2(std::vector<int>& vec) {
vec.emplace_back(1);
}
int main()
{
std::vector<int> vec;
std::vector<int> vec2;
std::cout << timeFuncInvocation(f, vec).count() << std::endl;
std::cout << timeFuncInvocation(f2, vec2).count() << std::endl;
std::vector<int> vec3;
vec3.reserve(100000);
std::vector<int> vec4;
vec4.reserve(100000);
std::cout << timeFuncInvocation(f, vec3).count() << std::endl;
std::cout << timeFuncInvocation(f2, vec4).count() << std::endl;
return 0;
}
EDIT: Natürlich müssen Sie immer daran denken, dass Ihr Compiler etwas optimieren kann oder nicht. Werkzeuge wie perf können in solchen Fällen nützlich sein.
clock_gettime
.. gcc definiert andere Uhren als:typedef system_clock steady_clock; typedef system_clock high_resolution_clock;
unter Windows verwendenQueryPerformanceCounter
.