我在C ++中有一些代码,想测量各种函数的运行时间(cpu时间)。
我知道这已被多次询问,但是在所有问题中(一个可以找到here,另一个here )可以得到各种答案。有些使用时钟,有些使用gettimeofday,有些使用奇怪的函数,其他外部库。
哪种方法提供最佳的精度和可靠性?我希望能够达到最多纳秒?
我在Ubuntu 14.04下工作。
提前谢谢。
答案 0 :(得分:3)
TLDR:你可以对毫秒级分辨率的热点有一个很好的了解,但是由于各种原因,纳秒分辨率不起作用。
您可以找到或编写一些能够为您提供计算机所能提供的最佳分辨率的功能,但是,这仍然没有给您带来任何有意义的结果:
auto start = getBestPrecisionTime();
foo();
auto end = getBestPrecisionTime();
std::cout << "foo took " << to_nanoseconds(end - start) << "ns";
第一个问题是foo()
被另一个程序打断了,你实际上并没有测量foo()
而是foo()
+ some_random_service。解决这个问题的一种方法是进行1000次测量,希望其中至少有一次没有被中断并采取最小的测量。根据{{1}}实际花费的时间长短,你的机会从永远到永远。
类似地,foo()
可能会访问位于1/2/3/4级缓存,RAM或硬盘驱动器中的内存,因此您再次测量错误的内容。您需要获得真实世界数据,了解foo()
所需的内存在哪个内存中的可能性以及访问时间。
另一个主要问题是优化。测量调试版本的性能没有多大意义,因此您需要在启用最大优化的情况下进行测量。具有高优化级别,编译器将重新排序和内联代码。 foo()
函数有两个选项:允许编译器将代码移过它。如果它允许重新排序,编译器将执行此操作:
getBestPrecisionTime
然后进一步优化
foo();
auto start = getBestPrecisionTime();
auto end = getBestPrecisionTime();
std::cout << "foo took " << to_nanoseconds(end - start) << "ns";
显然,这会产生错误的结果,而且我遇到的所有计时功能都会增加禁止这种情况的障碍。
但替代方案并没有好多少。如果没有测量,编译器可能会优化此
std::cout << "foo took 0ns";
到
foo();
bar();
由于更好地利用寄存器/ SIMD指令/缓存/ ....这样做效率更高。但是一旦你测量了性能,你就禁用了这个优化并测量了错误的版本。通过大量工作,您可以提取code_that_does_foo_bar;
内部code_that_does_foo_bar
内部的汇编程序指令,但由于您甚至无法准确判断汇编程序指令需要多长时间,而且时间也取决于周围环境汇编程序指令您没有机会获得优化代码的准确数字。
你能做的最好就是使用foo()
,因为它不会更准确。
答案 1 :(得分:1)
您可以尝试使用google:https://github.com/google/benchmark
中的基准测试库答案 2 :(得分:0)
您的问题过于宽泛,无法提供一个答案来统治所有问题。根据您的要求,如果您需要跨平台解决方案,那么std :: chrono :: high_resolution_clock可能符合要求。如果您无法访问支持C ++ 11编译器或更好的C ++ 11编译器,那么各种优秀的'ol C库时间函数可能就足够了。如果跨平台不是问题,而您只对Windows感兴趣,那么根据您的分辨率需求,可以使用QueryPerfomanceCounter或GetTickCount。
如果您有特定的需求,请在问题中提及。