有在这里的几个问题。首先是你明显切换到diffclock()
函数时的开始和结束时间。第二个问题是优化。任何启用了优化的合理智能编译器都会将整个循环丢弃,因为它没有任何副作用。但即使你解决了上述问题,程序仍然可以打印0.如果你试图想象每秒钟做数十亿次操作,那么抛出先进的乱序执行,预测和现代CPU所采用的大量其他技术,甚至是CPU优化你的循环。但即使不这样做,为了使其运行时间更长,您也需要10K以上的迭代次数。你可能需要你的程序运行一两秒钟才能得到clock()
反映任何东西。
但最重要的问题是clock()
本身。该功能不适用于任何性能测量的任何时间。它所做的是给你一个程序使用的处理器时间的近似值。除了任何给定实现可能使用的近似方法的模糊性质(因为标准并不要求它具体具体),POSIX标准还要求CLOCKS_PER_SEC
等于1000000
,与实际分辨率无关。换句话说 - 无论时钟的精确程度如何,CPU的运行频率无关紧要。简单地说 - 这是一个完全无用的数字,因此是一个完全无用的功能。它仍然存在的唯一原因可能是历史原因。所以,请不要使用它。
为了达到您的要求,人们用来读取CPU Time Stamp也被称为“RDTSC”的对应CPU指令的名称来读取它。然而,这些日子大多也没用,因为:
- 现代操作系统可以轻松地将程序从一个CPU迁移到另一个CPU。你可以想象,在另一个CPU上运行一秒钟之后读取时间戳并没有多大意义。只有在最新的英特尔CPU中,计数器才能跨CPU核心进行同步。总而言之,仍然有可能做到这一点,但必须特别小心(即一旦可以为流程设置亲和度等)。
- 测量程序的CPU指令通常不会提供实际使用时间的精确图片。这是因为在实际的程序中,可能会有一些系统调用,其中OS内核代表进程执行工作。在那种情况下,那个时间不包括在内。
- 也可能发生OS长时间挂起进程的执行。即使只需要执行几条指令,对于用户来说也只是一秒钟。所以这样的性能测量可能是无用的。
那该怎么办?
说到分析,必须使用像perf
这样的工具。它可以跟踪多个CPU时钟,缓存未命中,采取的分支,错过的分支,进程从一个CPU移动到另一个CPU的次数等等。它可以用作工具,也可以嵌入到应用程序中(如PAPI)。
如果问题是关于实际花费的时间,人们使用挂钟。最好是高精度的,也不受NTP调整(单调)的影响。无论发生什么事,这都表明已经过了多长时间。为此可以使用clock_gettime()
。它是SUSv2,POSIX.1-2001标准的一部分。鉴于使用你getch()
保持终端打开,我假设你正在使用Windows。在那里,不幸的是,你不必clock_gettime()
和最近的事情将是性能计数器API:
BOOL QueryPerformanceFrequency(LARGE_INTEGER *lpFrequency);
BOOL QueryPerformanceCounter(LARGE_INTEGER *lpPerformanceCount);
对于便携式解决方案,最好的办法是在std::chrono::high_resolution_clock()
。它是在C++ 11中引入的,但得到了大多数工业级编译器(GCC,Clang,MSVC)的支持。
下面是如何使用它的一个例子。请注意,因为我知道我的CPU会以比1毫秒快的整数方式执行10000个增量,所以我已将其更改为微秒。我还宣布计数器为volatile
,希望编译器不会优化它。
#include <ctime>
#include <chrono>
#include <iostream>
int main()
{
volatile int i = 0; // "volatile" is to ask compiler not to optimize the loop away.
auto start = std::chrono::steady_clock::now();
while (i < 10000) {
++i;
}
auto end = std::chrono::steady_clock::now();
auto elapsed = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
std::cout << "It took me " << elapsed.count() << " microseconds." << std::endl;
}
当我编译并运行它,它打印:
$ g++ -std=c++11 -Wall -o test ./test.cpp && ./test
It took me 23 microseconds.
希望它能帮助。祝你好运!
你的优化器会抛出你的for循环,因为它什么都不做?也许在全球范围内增加一项任务。阿洛斯,即使它确实有效,你的开始和结束都会倒退,这样时间会变成负面的。 – 2013-03-05 22:18:21
即使循环未被优化,计数到10000的机会也不会超过1毫秒。现代电脑速度非常快。 – 2013-03-05 22:19:52
你为什么这样做?如果你试图进行基准测试,那么循环可能不是一个好的测试。 – Richard 2013-03-05 22:20:39