现在,我基本上有一个程序,使用时钟来测试我的程序做某些操作所花费的时间,通常精确到几毫秒。我的问题是这样的:如果CPU负载很重,我还会得到同样的结果吗?
时钟只在CPU处理我的进程时才计算吗?
让我们假设:多核CPU,但进程没有利用多线程
根据您实际想要实现的目标,经过的时间或CPU时间可能是您想要测量的。
在有其他进程运行的系统中,运行时间和CPU使用率之间的差异可能很大(当然,如果CPU不忙于运行应用程序,例如等待网络数据包通过线路或文件数据从硬盘传输),那么运行时间对于其他应用程序是“可利用的”。
当其他进程在同一系统中运行时,还存在大量的错误因素/干扰因素:
>
在操作系统切换到“将此作为中断时间计算”之前,当处理网络或硬盘I/O上的数据包时,其他进程可能会使用“你的”cpu进行部分中断处理(通常不是大量的,但在非常繁忙的系统中,它可能是总时间的百分之几),并且如果其他进程在“你的”cpu上运行,则在其他进程加载其数据之后,用“你的”进程的数据重新加载缓存的时间将被计算在“你的时间”上。这种“干扰”可能会很好地影响你的测量--有多大程度上取决于系统中正在发生的“其他什么”。
如果您的进程[通过共享内存]与另一个进程共享数据,那么当您的进程无法执行时,您的进程与另一个进程之间也会有一些时间(通常是很少的时间,但在极端情况下,可能是很大的时间)花在处理“缓存探听请求”上。
如果操作系统正在切换任务,切换到/从您的任务所花费的时间的“一半”将计入您的进程,另一半计入正在切换到/退出的进程。同样,这通常是很小的数量,但如果您有一个非常繁忙的系统和许多进程开关,它可以加起来。
某些处理器类型,例如Intel's的超线程,也与您的实际核心共享资源,因此只有该核心上的部分时间花在您的进程中,并且您进程的缓存内容现在与其他一些进程的数据和指令共享--这意味着您的进程可能会被运行在同一CPU-core上的其他线程从缓存中“逐出”。
同样,多核CPU通常有一个共享的L3缓存,该缓存会受到CPU其他内核上运行的其他进程的影响。
文件缓存和其他“系统缓存”也会受到其他进程的影响--因此,如果您的进程正在读取一些文件,而其他进程也在访问文件,则缓存内容将比系统不太忙时“更不属于您”。
为了准确测量进程使用系统资源的程度,您需要处理器性能计数器(以及可复制的测试用例,因为您可能需要多次运行相同的设置以确保获得性能计数器的“正确”组合。当然,这些计数器中的大多数也是系统范围内的,并且某些类型的处理(例如中断和其他随机干扰)会影响测量,因此,如果系统中没有许多其他(繁忙)进程运行,则会得到最精确的结果。
当然,在许多情况下,只需测量应用程序的总体时间就足够了。同样,只要您有一个可复制的测试用例,它每次在特定场景中运行时都给出相同(或至少相似)的时间。
每个应用都不一样,每个系统都不一样。性能测量是一个巨大的课题,很难涵盖所有内容--当然,我们在这里并不是要回答关于“当其他进程在同一系统中运行时,如何使我的百万小数位的PI运行得更快”或其他问题的极其具体的问题。
除了同意指出计时取决于许多因素的答复之外,我还想提请您注意自C++11以来可用的
#include <chrono>
#include <iostream>
int main() {
auto beg = std::chrono::high_resolution_clock::now();
std::cout << "*** Displaying Some Stuff ***" << std::endl;
auto end = std::chrono::high_resolution_clock::now();
auto dur = std::chrono::duration_cast<std::chrono::microseconds>(end - beg);
std::cout << "Elapsed: " << dur.count() << " microseconds" << std::endl;
}
根据标准,此程序将利用您的系统提供的最高精度时钟,并将以微秒分辨率运行(还有其他分辨率可用;请参阅文档)。
示例运行:
$ g++ example.cpp -std=c++14 -Wall -Wextra -O3
$ ./a.out
*** Displaying Some Stuff ***
Elapsed: 29 microseconds
虽然它比依赖C-style的
CPU中有共享组件,比如最后一级缓存,执行单元(在一个内核内的硬件线程之间),所以在重载下你会得到抖动,因为即使你的应用程序执行了完全相同数量的指令,每个指令可能需要更多的周期(等待内存,因为数据被从缓存,可用的执行单元中逐出),更多的周期意味着更多的执行时间(假设Turbo Boost不会补偿)。
如果你想要精密仪器,就看硬件柜台。
考虑物理CPU上可用内核的数量,超线程和其他BIOS设置(如Intel CPU上的Turbo Boost),以及在查看CPU密集型任务的时序指标时编码时使用的线程技术等因素也很重要。
像OpenMP这样的并行化工具提供了用于计算计算和墙时间的内置函数,比如