程序执行时间计数器

3
什么是C++中计算经过时间最准确的方法?我使用了clock()函数进行计算,但我有一种感觉这是错误的,因为我90%的时间得到的结果是0毫秒,其余时间得到的是15毫秒,这对我来说没有多少意义。即使它非常小并且非常接近0毫秒,是否有更准确的方法可以给我精确的值而不是四舍五入为0毫秒?
clock_t tic = clock();

/*
  main programme body
*/

clock_t toc = clock();
double time = (double)(toc-tic);
cout << "\nTime taken: " << (1000*(time/CLOCKS_PER_SEC)) << " (ms)";

谢谢


1
你应该添加正在运行你的代码的操作系统,因为更高分辨率的计时器大多数依赖于操作系统。如果你使用C++11,你应该考虑查看<chrono>头文件,它提供了更高分辨率的计时器,并封装了操作系统的依赖关系。 - ogni42
2
@huseyintugrulbuyukisik:RDTSC在今天的计算机上实际上不是一个很好的用于测量墙钟时间的来源。首先,它在多个核心之间不一定同步,因此如果您的进程被重新调度到不同的核心上,减去两个值就没有意义了。此外,现代CPU具有根据负载响应的动态时钟频率。对于算法复杂度的测量,将线程固定到单个CPU并使用RDTSC是有帮助的。但对于时间戳和测量墙钟时间来说,绝对不适用。 - Ben Voigt
@Ben Voigt 例如,我想了解dot-product avx/sse内部序列的性能如何,我可以使用带有原子锁定或将线程限制为单个核心的RDTSC吗?我知道rdtsc需要近50个周期。 - huseyin tugrul buyukisik
@huseyintugrulbuyukisik:动态频率可能仍会影响CPU周期和内存延迟之间的关系。但在这种情况下,RDTSC将给出合理的结果。要做得更好,您需要使用英特尔自己的分析器,该分析器可以将CPU、缓存行为和内存访问作为单独报告的指标进行监控。 - Ben Voigt
1
@huseyintugrulbuyukisik:就RDTSC而言,它是一个耗费资源的操作,很可能是因为你的平台在多核之间进行了同步。读取HPET也很慢。 - Ben Voigt
显示剩余2条评论
3个回答

8

使用C++11,我会使用

#include <chrono>
auto t0 = std::chrono::high_resolution_clock::now();
...
auto t1 = std::chrono::high_resolution_clock::now();
auto dt = 1.e-9*std::chrono::duration_cast<std::chrono::nanoseconds>(t1-t0).count();

获取已过时间的秒数。


对于2011年以前的C++,可以在Windows上使用QueryPerformanceCounter()或在Linux/OSX上使用gettimeofday()。例如(实际上这是C而不是C++):

timeval oldCount,newCount;
gettimeofday(&oldCount, NULL);
...
gettimeofday(&newCount, NULL);
double t = double(newCount.tv_sec -oldCount.tv_sec )
         + double(newCount.tv_usec-oldCount.tv_usec) * 1.e-6;

用于计算已流逝的时间(秒)。


1
除了在Visual Studio上要小心之外。 - Bartek Banachewicz
这个注释说的很明白。 - Bartek Banachewicz
@BartekBanachewicz那个评论只是一个陈述。证据在哪里? - Walter
2
@Walter:如果你不知道的话,那个评论是由一位微软DevDiv员工留下的。这里是错误链接 - Ben Voigt
@BartekBanachewicz 谢谢,我确实不知道(就像我说的,我不使用Visual Studio,而是使用最新版本的gcc、clang和icpc)。 - Walter
显示剩余5条评论

3

std::chrono::high_resolution_clock是最具可移植性的解决方案,但它可能不比你已经看到的时钟分辨率更高。

几乎所有返回系统时间的函数都会在定时器中断处理程序更新系统时间时向前跳跃,而现代操作系统上的典型间隔为10毫秒。

为了获得更好的精度定时,您需要访问CPU周期计数器或高精度事件计时器(HPET)。编译器库供应商应该使用这些来实现high_resolution_clock,但并非所有供应商都这样做。因此,您可能需要使用特定于操作系统的API。

(注意:具体来说,Visual C++ high_resolution_clock使用低分辨率系统时钟。但可能还有其他情况。)

例如,在Win32上,QueryPerformanceFrequency()QueryPerformanceCounter()函数是一个不错的选择。对于符合C++11计时器接口并使用这些函数的包装器,请参见


您可能想要在此答案中添加一个链接到这个回答 - Bartek Banachewicz

0
如果您有C++11可用,可以使用chrono库。
此外,不同的平台提供了访问高精度时钟的方法。
例如,在Linux中,使用clock_gettime。在Windows中,使用high performance counter api
示例:
C++11:
auto start=high_resolution_clock::now();
...  // do stuff
auto diff=duration_cast<milliseconds>(high_resolution_clock::now()-start);
clog << diff.count() << "ms elapsed" << endl;

谢谢您的快速回复。我不认为我有C++11,因为我无法编译那段代码。chrono是仅适用于C++11吗? - user2550888
你使用的是哪个编译器?你可能需要启用C++11支持。例如,如果使用g++,你需要使用-std=c++11-std=c++0x来调用。 - jsp

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接