提问者:小点点

C++中的clock()是否与高CPU负载一致


现在,我基本上有一个程序,使用时钟来测试我的程序做某些操作所花费的时间,通常精确到几毫秒。我的问题是这样的:如果CPU负载很重,我还会得到同样的结果吗?

时钟只在CPU处理我的进程时才计算吗?

让我们假设:多核CPU,但进程没有利用多线程


共3个答案

匿名用户

的功能取决于操作系统。在windows中,从一个远距离的决定中给出了经过的时间,而在大多数其他OSS中(当然是Linux,MacOS和其他与UNIX相关的OSS)。

根据您实际想要实现的目标,经过的时间或CPU时间可能是您想要测量的。

在有其他进程运行的系统中,运行时间和CPU使用率之间的差异可能很大(当然,如果CPU不忙于运行应用程序,例如等待网络数据包通过线路或文件数据从硬盘传输),那么运行时间对于其他应用程序是“可利用的”。

当其他进程在同一系统中运行时,还存在大量的错误因素/干扰因素:

> 如果我们假设您的操作系统支持作为CPU-time的度量,那么这里的精度并不总是那么高--例如,它可能很好地按照CPU-timer节拍来计算,并且您的进程可能不会运行到“完整节拍”(例如,如果它在执行I/O)。

在操作系统切换到“将此作为中断时间计算”之前,当处理网络或硬盘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这样的并行化工具提供了用于计算计算和墙时间的内置函数,比如,在使用这类并行化的程序中,这些函数通常比精确几倍。

相关问题


MySQL Query : SELECT * FROM v9_ask_question WHERE 1=1 AND question regexp '(c++|中|clock|高|cpu|负载)' ORDER BY qid DESC LIMIT 20
MySQL Error : Got error 'repetition-operator operand invalid' from regexp
MySQL Errno : 1139
Message : Got error 'repetition-operator operand invalid' from regexp
Need Help?