我在Scott Meyers的书中发现了一个通用泛型lambda表达式的例子,可以用来测量函数执行时间。(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;
};
问题在于只测量了一次执行,因此结果可能会有很大的差异。为了获得可靠的结果,您应该测量大量的执行。
根据Andrei Alexandrescu在code::dive 2015会议上的演讲 - Writing Fast Code I中所说:
测量时间:tm = t + tq + tn + to
其中:
tm-测量(观察)时间
t-感兴趣的实际时间
tq-由量化噪声添加的时间
tn-由各种噪声源添加的时间
to-开销时间(测量、循环、调用函数)
根据他在演讲后面所说的,你应该将这个大量的执行中的最小值作为你的结果。我鼓励您查看他解释原因的演讲。
此外,谷歌还有一个非常好的库-
https://github.com/google/benchmark。这个库非常简单易用且功能强大。您可以在YouTube上查看Chandler Carruth的一些讲座,他在实践中使用了这个库。例如CppCon 2017: Chandler Carruth “Going Nowhere Faster”;
示例用法:
#include <iostream>
#include <chrono>
#include <vector>
auto timeFuncInvocation =
[](auto&& func, auto&&... params) {
const auto& start = high_resolution_clock::now();
for(auto i = 0; i < 100000; ++i) {
std::forward<decltype(func)>(func)(std::forward<decltype(params)>(params)...);
}
const auto& stop = high_resolution_clock::now();
return (stop - start)/100000;
};
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;
}
编辑:
当然,您始终需要记住编译器可能会优化掉某些内容。在这种情况下,像perf这样的工具可能会有用。
clock_gettime
。gcc定义其他时钟为:typedef system_clock steady_clock; typedef system_clock high_resolution_clock;
在Windows上,使用QueryPerformanceCounter
。 - Brandon