现在,我基本上有一个使用时钟测试程序执行某些操作所需时间的程序,通常准确到几毫秒。我的问题是:如果CPU负载很高,我仍然会得到相同的结果吗?
时钟只在CPU处理我的进程时计数吗?
假设:多核CPU但进程不利用多线程。
现在,我基本上有一个使用时钟测试程序执行某些操作所需时间的程序,通常准确到几毫秒。我的问题是:如果CPU负载很高,我仍然会得到相同的结果吗?
时钟只在CPU处理我的进程时计数吗?
假设:多核CPU但进程不利用多线程。
clock
函数的功能取决于操作系统。在Windows中,clock
函数提供了经过时间,而在大多数其他操作系统(如Linux、MacOS和其他类Unix操作系统)中,它提供了CPU时间。clock
作为CPU时间的度量,那么这里的精度并不总是那么高-例如,它可能会以CPU计时器滴答声的形式计算,并且如果进程正在执行I/O,则其进程可能不会运行“完整的滴答声”。
其他进程可能会在操作系统切换到“将此视为中断时间”之前使用“您”的CPU处理部分中断处理,在处理网络数据包或硬盘I/O等一定百分比的时间内[通常不是巨大的数量,但在非常繁忙的系统中,可以占总时间的几个百分点],如果其他进程在“您”的CPU上运行,则重新加载缓存以在其他进程加载其数据后加载“您”的进程数据所需的时间将计入“您的时间”。这种“干扰”可能会影响您的测量结果-影响程度取决于系统中正在发生的“其他事情”。
如果您的进程通过共享内存与另一个进程共享数据,则还将花费一些时间(再次,通常是微小的数量,但在极端情况下,可能会很显着)处理您的进程和其他进程之间的“高速缓存嗅探请求”,当您的进程无法执行时。
如果操作系统正在切换任务,则“一半”切换到/从您的任务所花费的时间将计入您的进程,而另一半则计入正在切换进/出的其他进程。同样,这通常是微小的数量,但如果您有一个非常繁忙的系统,并且有大量进程切换,则可能会累加。
某些处理器类型(例如Intel的HyperThreading)还与实际核心共享资源,因此该核心上仅有一部分时间用于执行您的进程,并且缓存内容与某些其他进程的数据和指令共享-这意味着您的进程可能会被同一CPU核心上运行的其他线程从高速缓存中“驱逐”出来。
同样,多核CPU通常具有共享的L3缓存,其受到在CPU的其他核心上运行的其他进程的影响。
文件缓存和其他“系统缓存”也会受到其他进程的影响-因此,如果您的进程正在读取某些文件,并且其他进程也访问文件,则缓存内容将比系统不那么繁忙时“不属于您”的更少。
要准确测量您的进程使用系统资源的程度,您需要处理器性能计数器(以及可重复的测试用例,因为您可能需要运行相同的设置多次以确保获得“正确”的性能计数器组合)。当然,大多数这些计数器也是系统范围的,并且例如中断和其他随机干扰中的某些处理将影响测量结果,因此如果您在系统中没有许多其他(繁忙)进程运行,则最准确的结果将是。除了同意那些表示时间取决于许多因素的回答之外,我想向您介绍自C++11以来可用的std::chrono
库:
#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
std::clock()
更冗长,但我认为它提供了更多的表现力,而且你可以在一个漂亮的接口后面隐藏冗长(例如,看看我对之前帖子的回答,在那里我使用std::chrono
来构建一个函数计时器)。clock
将给出 CPU 使用时间 - 对于使用一个 CPU 100% 的应用程序,使用哪个函数都没有多大区别;对于具有多个线程的应用程序,在其中多个线程使用 100% 或使用少于 100% 的 CPU 时,可能会有(潜在的大)差异。 - Mats Peterssonomp_get_wtime( );
,这些函数在使用此类型的并行化的程序中通常比clock()
更准确。