这里有几个问题。首先是您在传递给diffclock()
函数时显然切换了开始和停止时间。第二个问题是优化。任何启用优化的合理智能编译器都会简单地丢弃整个循环,因为它没有任何副作用。但即使你解决了上述问题,程序很可能仍会打印 0。如果你试图想象每秒执行数十亿次操作,抛出复杂的乱序执行、预测和现代 CPU 采用的大量其他技术,即使是 CPU 也可能优化你的循环。但即使没有,您也需要超过 10K 次迭代才能使其运行更长时间。您可能需要您的程序运行一两秒钟才能clock()
反映任何内容。
但最重要的问题是clock()
它本身。该功能不适用于任何时间的性能测量。它的作用是为您提供程序使用的处理器时间的近似值。除了任何给定实现可能使用的近似方法的模糊性质(因为标准不需要任何特定的东西),POSIX 标准还要求CLOCKS_PER_SEC
等于1000000
独立于实际分辨率。换句话说——时钟有多精确并不重要,你的 CPU 以什么频率运行并不重要。简而言之——它是一个完全无用的数字,因此是一个完全无用的功能。它仍然存在的唯一原因可能是出于历史原因。所以,请不要使用它。
为了实现您要查找的内容,人们习惯于通过用于读取它的相应 CPU 指令的名称来读取CPU 时间戳,也称为“RDTSC”。然而,这些天来,这也大多是无用的,因为:
- 现代操作系统可以轻松地将程序从一个 CPU 迁移到另一个 CPU。您可以想象在另一个 CPU 上运行一秒钟后读取另一个 CPU 上的时间戳没有多大意义。只有在最新的 Intel CPU 中,计数器才会跨 CPU 内核同步。总而言之,仍然可以这样做,但必须格外小心(即一旦可以设置进程的亲和力等)。
- 经常测量程序的 CPU 指令并不能准确地了解它实际使用了多少时间。这是因为在实际程序中可能存在一些系统调用,其中工作由操作系统内核代表进程执行。在这种情况下,该时间不包括在内。
- 操作系统也可能长时间暂停进程的执行。尽管执行只需要几条指令,但对用户来说似乎只是一秒钟。所以这样的性能测量可能是无用的。
那么该怎么办?
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 将以比毫秒快的速度执行 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.
希望能帮助到你。祝你好运!