在执行相同代码之间,CPU时间是否应始终相同?

问题描述 投票:1回答:2

我对CPU时间的理解是,同一台计算机上每次执行之间的时间应该始终相同。每次都需要相同数量的cpu周期。

但是我现在正在运行一些测试,以执行基本的回显“ Hello World”,这给了我0.003至0.005秒。

我对CPU时间的理解是否错误,或者我的测量存在问题?

performance cpu benchmarking cpu-time
2个回答
3
投票

您的理解是完全错误的。在现代CPU上运行现代OS的实际计算机不是简单的理论抽象。有多种因素可以影响执行代码所需的CPU时间。

考虑内存带宽。在典型的现代计算机上,在计算机内核上运行的所有任务都在争夺对系统内存的访问。如果代码同时运行,则另一个内核上的代码正在使用大量内存带宽,这可能导致访问RAM需要更多时钟周期。

也共享许多其他资源,例如缓存。假设代码经常被打断,以使其他代码在内核上运行。这意味着代码经常会发现缓存很冷,并会导致很多缓存未命中。这也将导致代码花费更多的时钟周期。

我们也讨论页面错误。代码本身可能在内存中,也可能不在代码开始运行时。即使代码在内存中,也可能会或可能不会发生软页面错误(以更新操作系统对正在使用的内存的跟踪),具体取决于该页面上次发生软页面错误的时间或加载该页面的时间。进入RAM。

您的基本hello world程序正在对终端执行I / O。花费的时间可能取决于当时与终端交互的内容。


0
投票

对现代系统的最大影响包括:

  • 如果虚拟内存在页面缓存中不热,则虚拟内存会懒惰地从磁盘中分页代码和数据。 (程序的第一次运行往往会产生更多的启动开销。)
  • CPU频率不固定。(怠速/加速速度。grep MHz /proc/cpuinfo
  • CPU缓存可能很热
  • ((非常短的间隔)中断在您的定时区域内随机发生或不在您的定时区域内。

因此,即使周期是固定的(它们不是很大),您也不会看到相等的时间。

您的假设并非total错误,但是它仅适用于各个循环的核心时钟周期,并且仅适用于不涉及任何内存访问的情况。(例如,L1d缓存中已经很热的数据,代码已经在CPU内核内部的L1i缓存中很热)。并且假设定时循环运行时没有中断发生。

运行整个程序的操作规模更大,并且将涉及共享资源(以及可能的争用),例如对主存储器的访问。就像@David指出的那样,一个write系统调用来打印字符串在终端仿真器上-与另一个进程的通信可能很慢,并且如果程序最终等待它,则需要唤醒另一个进程。重定向到/dev/null或常规文件将删除该文件,或者仅关闭./hello >&-这样的stdout会使write系统调用返回-EBADF(在Linux上)。

现代CPU是非常复杂的野兽。您大概拥有一个乱序执行的Intel或AMD x86-64 CPU,以及用于传入/传出高速缓存行的十几个缓冲区,从而使它能够跟踪许多未解决的高速缓存未命中(内存级并行性)。每个内核有2个级别的专用缓存,以及一个共享的L3缓存。祝您好运,除了可以控制的条件外,还能预测其他任何时间的准确时钟周期数。

但是,如果您do控制条件,则同一小循环通常将在每次迭代中以相同数量的核心时钟周期运行。

但是,即使that也并非总是如此。我已经看到过这样的情况,对于CPU如何调度指令,同一循环似乎具有两个稳定状态。不同的进入条件怪癖可能导致数百万次循环迭代中持续的速度差异。

我在Sandybridge和Skylake等现代Intel CPU上进行微基准测试时,偶尔会看到这种情况。即使在性能计数器和https://agner.org/optimize

的帮助下,通常也不清楚到底两个稳定状态是什么,到底是什么导致了瓶颈

在一种情况下,我记得,中断往往会使循环进入有效的执行模式。 @BeeOnRope正在使用RDPMC在较短的时间间隔内(或可能是固定了核心时钟= TSC参考时钟的RDTSC)来测量慢周期/迭代,而我通过使用非常大的重复计数并仅在其上使用perf stat来测量其运行速度更快整个程序(这是一个静态可执行文件,只有一个循环用asm手工编写)。 @Bee可以通过增加迭代次数来复制我的结果,以便在定时区域内发生中断,而从中断返回往往会使CPU脱离非最优的uop调度模式,无论它是什么。 >

© www.soinside.com 2019 - 2024. All rights reserved.