gcc编译(有时)导致cpu欠载

时间:2012-12-12 22:52:02

标签: c++ linux gcc cpu-usage

我有一个更大的C ++程序,它首先将数千个小文本文件读入内存并将数据存储在stl容器中。这大约需要一分钟。定期编译将显示行为,其中程序的初始部分将以大约22-23%的CPU负载运行。一旦该步骤结束,它就会回到~100%CPU。在O2标志打开但更不一致的情况下更有可能发生。使用-p标志更常发生这种情况,这使得几乎不可能进行分析。我确实捕获了一次,但是gprof输出没有帮助 - 一切都以相同的相对速度运行,只是在低CPU使用率下。

我很确定这与多核无关。我有一个四核cpu,大多数代码是多线程的,但我测试了运行单个线程的这个问题。此外,当我在多个线程中运行有问题的步骤时,每个线程仅在~20%CPU运行。

我提前为这个问题的模糊性道歉,但我已经没有关于如何进一步排除故障的想法,所以任何提示都可能有所帮助。

更新:为了确保清楚,代码中有问题的部分有时(约30-40%的编译)以100%CPU运行,因此很难购买(或其他合理的)I / I O是瓶颈

3 个答案:

答案 0 :(得分:4)

这是缓冲区缓存


我的猜测是你看到了Linux buffer cache正在运行的结果。

这些数千个文件需要很长时间才能从磁盘读入,CPU将主要等待轮换和寻找延迟。报告的CPU使用时间将以百分比表示。 (但总体来说可能更大。)

但是一旦读完,那些小文件就完全缓存在内存中,并且访问每个文件(在后续运行中)变成纯粹的CPU绑定活动。

块是否保留在缓存中取决于干预活动,例如重新编译。当运行新程序并读取其他文件时,程序和文件将被缓存,旧块将被删除,显然,内存密集型工作负载也将清除缓冲区缓存。

答案 1 :(得分:3)

由于您正在阅读大量小文件,因此您的程序在大多数情况下都会在磁盘I / O上等待。由于CPU在等待磁盘将数据发送给它时不忙,因此您看到的负载远低于100%。一旦结束,现在你受CPU限制,你的程序将占用所有可用的CPU时间。

有时它工作得更快的事实是因为(正如Jarryd& DigitalRoss所提到的)一旦你将它们读入系统内存,它们就会在操作系统的缓存中,所以后续加载速度会快一个数量级,除非他们被其他磁盘I / O驱逐了。因此,如果您背靠背运行程序,第二次运行可能会快得多。如果你等待一段时间(并在此期间做其他事情),可能已经有足够的其他磁盘I / O从缓存中驱逐这些文件,在这种情况下,它将需要很长时间才能再次读取它们。

答案 2 :(得分:3)

除了提到缓冲区缓存的其他答案之外,如果你想了解编译过程中发生了什么,你可以将以下flags中的一些传递给GCC(即g++,可能作为CXXFLAGS中的Makefile设置:

  • -v要求g++显示所涉及的子流程(例如cc1plus以获取正确的C ++编译器)
  • -time要求g++报告每个子流程的时间
  • -ftime-report要求g++(实际上cc1plus)报告编制内部阶段或传递的时间。