为什么每次执行此程序时CPU时间都不同?

时间:2013-05-02 13:20:02

标签: c++ performance clock

我很难理解处理器时间。该计划的结果:

#include <iostream>
#include <chrono>

// the function f() does some time-consuming work
void f()
{
    volatile long double d;
    int size = 10000;
    for(int n=0; n<size; ++n)
       for(int m=0; m<size; ++m)
           d = n*m;
}

int main()
{
    std::clock_t start = std::clock();
    f();
    std::clock_t end = std::clock();

    std::cout << "CPU time used: "
              << (end - start)
              << "\n";
}

似乎在210 000,220 000和230 000之间随机波动。起初我很惊讶,为什么这些离散值。然后我发现std::clock()仅返回approximate processor time。因此,std::clock()返回的值可能会舍入到10 000的倍数。这也可以解释为什么CPU时间之间的最大差异为20 000(10 000 ==第一次调用{{1时的舍入误差第二个和10 000个。)

但是如果我在std::clock()的身体中改为int size = 40000;,我会在3 400 000到3 500 000的范围内出现波动,这无法用四舍五入来解释。

根据我在维基百科上看到的clock rate

  

CPU需要固定数量的时钟周期(或时钟周期)   执行每条指令。时钟越快,指令越多   CPU可以每秒执行一次。

也就是说,如果程序是确定性的(我希望是我的),那么完成所需的CPU时间应该是:

  1. 始终相同
  2. 略高于执行的指令数
  3. 我的实验也没有显示,因为我的程序需要执行至少f()条指令。你能解释一下我做错了吗?

4 个答案:

答案 0 :(得分:7)

首先,您从维基百科中引用的陈述完全是假的。 20年前可能是真的(但并非总是如此) 然后),但今天完全是假的。有很多事情 这会影响你的时间:

  • 第一个:如果您在Windows上运行,clock已损坏, 并且完全不可靠。它返回经过的差异 时间,而不是CPU时间。经过的时间取决于各种各样的 处理器可能正在做的其他事情。

  • 除此之外:缓存未命中等问题非常重要 对时间的影响。并且是否有特定的数据 是否缓存取决于您的程序是否 在最后一次访问和此访问之间中断。

一般来说,任何低于10%的东西都很容易归因于 缓存问题。而且我已经看到了10倍的差异 在Windows下,取决于是否正在运行构建或 不

答案 1 :(得分:3)

您没有说明您正在运行二进制文件的硬件。

是否有中断驱动的CPU?

它是一个多任务操作系统吗?

你错误地将CPU的周期时间(维基百科所指的CPU时钟)与从头到尾执行特定代码所需的时间以及可怜的CPU必须做的所有其他事情搞错了同时。

另外......是你在1级缓存中执行的所有代码,或者是2级或主内存中的某些代码,还是磁盘上的代码...下次运行它时会怎么样?

答案 2 :(得分:2)

您的程序不具有确定性,因为它使用了不确定的库和系统函数。

作为一个特例,当您分配内存时,这是虚拟内存,必须映射到物理内存。虽然这是一个系统调用,运行内核代码,但它会在您的线程上进行,并将计入您的时钟时间。执行此操作所需的时间取决于总体内存分配情况。

答案 3 :(得分:1)

对于给定的一组环境,CPU时间确实是“固定的”。但是,在现代计算机中,系统中还会发生其他事情,这会干扰代码的执行。当您的电子邮件软件醒来检查是否有新的电子邮件,或HP打印机软件检查更新时,或者当防病毒软件决定运行以进行一些检查时,可能会消除缓存你的记忆包含任何病毒等等,等等。

部分原因还在于任何系统中的CPU时间记帐不是100%准确的问题 - 它适用于“时钟滴答”和类似的事情,因此例如中断用于服务网络的时间进入的数据包,或硬盘服务中断,或定时器中断说“另一个毫秒勾选”这些全部帐户进入“当前正在运行的进程”。假设这是Windows,还有一个“功能”,即由于历史和其他原因,std::clock()只是返回现在的时间,而不是实际上是您的进程使用的时间。所以例如:

t = clock();
cin >> x;
t = clock() - t;
如果输入t的值需要十秒钟,

将使x的时间为10秒,即使这些十秒中的9.999花费在空闲进程中,而不是您的程序。