-1

我很难理解处理器时间。这个程序的结果:

#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()只返回近似的处理器时间。所以可能返回的值std::clock()被四舍五入到 10 000 的倍数。这也可以解释为什么 CPU 时间之间的最大差异是 20 000 (第一次调用时 10 000 == 舍入误差,第二次调用时为std::clock()10 000)。

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

根据我在维基百科上读到的关于时钟频率的内容:

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

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

  1. 总是一样
  2. 略高于执行的指令数

我的实验都没有显示,因为我的程序至少需要执行3 * size * size指令。你能解释一下我做错了什么吗?

4

4 回答 4

8

首先,您从维基百科引用的陈述完全是错误的。20 年前它可能是正确的(但并非总是如此,即使在那时),但今天它完全是错误的。有很多事情会影响你的时间安排:

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

  • 除此之外:诸如缓存未命中之类的事情对时间有非常重要的影响。并且特定数据是否在缓存中取决于您的程序在上次访问和这次访问之间是否被中断。

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

于 2013-05-02T13:29:52.767 回答
3

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

它有中断驱动的CPU吗?

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

您将 CPU 的周期时间(维基百科所指的 CPU 时钟)与从开始到结束执行特定代码段所需的时间以及糟糕的 CPU 必须同时执行的所有其他事情混淆了.

另外...您的所有执行代码都在 1 级缓存中,还是在 2 级或主内存中,或在磁盘上...下次运行时呢?

于 2013-05-02T13:26:38.133 回答
2

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

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

于 2013-05-02T13:44:42.413 回答
1

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

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

t = clock();
cin >> x;
t = clock() - t;

t如果输入 的值需要 10 秒,则将离开10 秒x,即使这 10 秒中有 9.999 秒用于空闲进程,而不是您的程序。

于 2013-05-02T13:31:45.567 回答