C++评测和优化

C++ profiling and optimization

本文关键字:优化 评测 C++      更新时间:2023-10-16

我的应用程序的性能有一些问题。我在Stackoverflow上找到了这个答案:https://stackoverflow.com/a/378024/5363

这是我喜欢的。有一点我真的不明白,代码优化和评测之间的关系是什么。因为很明显,人们想要评测优化的代码,但同时在优化过程中会丢失很多信息。那么,在调试器中运行优化的代码并按照引用的答案中的建议对其进行破解是否实用呢?

如果这有什么不同的话,我在Linux下使用CMake和gcc。

一般定律被称为帕累托定律,80/20:定律

  • 20%的原因产生80%的后果

通过分析,您将确定导致应用程序速度慢/占用内存或其他后果的20%最重要的原因。如果你解决了20%的原因,你将解决80%的缓慢/内存消耗等问题

当然,这些数字只是数字。只是为了给你它的精神:

  • 您必须只关注真正的主要原因,以便改进优化,直到您满意为止

从技术上讲,对于linux下的gcc,你提到的"我如何评测在linux中运行的C++代码?"这个问题的答案建议使用,简而言之:

  • gprof
  • 谷歌性能工具
  • Valgrind
  • 英特尔VTune
  • Sun DTrace

如果您需要收集堆栈样本,为什么要通过调试器来收集呢。定期运行pstack。您可以为每次运行将输出重定向到不同的文件,并在以后分析这些文件。通过查看这些文件的调用堆栈,您可以了解hot函数。您不需要调试二进制文件,可以在完全优化的二进制文件上执行上述操作。

我更喜欢使用探查器工具来执行上述操作或执行您引用的线程中列出的操作。它们可以快速定位最热门的函数,您可以通过查看调用方-被调用方图来了解调用堆栈。我会花时间理解调用者-被调用者堆栈,而不是使用上面的方法分析随机堆栈。

正如Schumi所说,您可以使用类似pstack的东西来获取堆栈样本。然而,您真正需要知道的是为什么程序会在采样的瞬间花费时间。也许你可以从一堆函数名中找到答案。如果您还可以看到调用发生的代码行,那就更好了。如果您能看到参数值和数据上下文,那就更好了。原因是,与人们普遍认为的"热点"、"慢方法"、"瓶颈"(即基于测量的视角(相反,最有价值的东西是可以消除的事情。

换句话说,当您在调试器中停止程序时,会将它所做的一切视为一个错误。尽量想办法不要做那件事。然而,在你取另一个样本并看到它做同样的事情之前,不要这样做——无论你如何描述它。现在你知道这需要相当长的时间。多少时间?没关系,你修好后会发现的。你知道这是很多。你在看到它两次之前必须采集的样本越少,它就越大。

然后是"放大效应"。在你修复了"速度错误"后,程序将花费更少的时间,但这并不是唯一的一个。还有其他的,现在它们占用了更多的时间。所以再做一遍。当你完成这个程序时,如果这个程序比玩具还大,你可能会惊讶于它的速度有多快。这是一个43倍的加速这是一个730倍的加速下面是它背后沉闷的数学。

你看,工具的问题是你要为采样的方便性付出代价。由于您将其视为度量,因此您并没有集中于代码正在做的事情的原因——可疑的原因。这会导致您错过使代码更快的机会,导致您错过放大效果,导致你远远没有达到最终可能的加速。

编辑:为火焰道歉。现在回答你的问题——我直到最后才打开编译器优化,因为它可以掩盖更大的问题。然后,我尝试进行一个启用了优化的构建,但仍然有符号信息,这样调试器就可以获得合理的堆栈跟踪并检查变量。当我遇到加速回报递减的情况时,我可以通过测量总体时间来看到优化器产生了多大的差异——不需要分析器。