C++ C++;剖析和优化

C++ C++;剖析和优化,c++,optimization,profiling,C++,Optimization,Profiling,我的应用程序的性能有一些问题。我在Stackoverflow上找到了这个答案: 我喜欢。有一点我不太明白,代码优化和评测之间的关系是什么。因为很明显,我们想要分析优化的代码,但同时在优化过程中会丢失很多信息。那么,在调试器中运行优化的代码并按照引用的答案中的建议打断它是否可行呢 如果这有什么不同的话,我在Linux下将CMake与gcc结合使用。一般规律称为帕累托定律: 20%的原因产生80%的后果 通过分析,您将确定20%的最重要原因,这些原因使您的应用程序缓慢/消耗内存,或其他后果。如

我的应用程序的性能有一些问题。我在Stackoverflow上找到了这个答案:

我喜欢。有一点我不太明白,代码优化和评测之间的关系是什么。因为很明显,我们想要分析优化的代码,但同时在优化过程中会丢失很多信息。那么,在调试器中运行优化的代码并按照引用的答案中的建议打断它是否可行呢


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

一般规律称为帕累托定律:

  • 20%的原因产生80%的后果
通过分析,您将确定20%的最重要原因,这些原因使您的应用程序缓慢/消耗内存,或其他后果。如果你解决了20%的原因,你将解决80%的缓慢/内存消耗等问题

当然,这些数字只是数字。只是为了让你感受到它的精神:

  • 您必须只关注真正的主要原因,以便改进优化,直到您满意为止
从技术上讲,对于linux下的gcc,您提到的问题“”的答案建议使用,简而言之:


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


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

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

换句话说,当你在调试器中停止程序时,考虑它所做的任何事情,就像它是一个bug一样。 试着找到一种不做那件事的方法。 但是,在你取下另一个样本并看到它做同样的事情之前,不要这样做——不管你如何描述它。 现在你知道这需要很长时间。 多少时间?没关系,修好后你会发现的。 你知道这是很多。在看两遍之前,你必须采集的样本越少,它就越大

然后是“放大效应”。在你修复了这个“速度错误”之后,这个程序将花费更少的时间——但是——这不是唯一的一个。 还有其他的,现在它们占用了更多的时间。 所以,再来一次。 当你完成这项工作时,如果程序比玩具大,你会惊讶于它的速度有多快。

你看,工具的问题是,你为取样的方便付出了代价。 因为您将其视为度量,所以您没有关注代码执行其操作的原因——可疑的原因。 这会导致您错过加快代码速度的机会, 使您错过放大效果, 使您的速度远远低于最终可能的加速

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

先评测,然后再优化。评测的作用是帮助您识别“热点”,在这里您可以研究优化。您所做的优化是在您编写的实际代码中进行的,因此调试器或进一步的评测都没有问题。@JoachimPileborg,但是我怎么知道瓶颈不是由假定代码将被优化而编写的库造成的呢?例如,根据我以前的经验,STL在调试构建中的行为非常糟糕。在这种特殊情况下,瓶颈似乎是一些矩阵操作(使用特征库)@Grzenio不评测调试版本!您只需要调试信息,而不是编译调试版本。您应该在上配置优化。如果适用,首先使用
时间运行程序。user/system/real的比率应该表明您的程序是否将大部分时间花在系统调用或等待I/O完成。也称为“最低挂果”,即以最小的努力获得最大的回报。我100%同意!不过,从技术角度来看,我该怎么做呢?@PeterWood-thx,我不知道这个,这个比喻真的很好:-)谢谢你的回答!如何使gcc在优化的构建中保留符号信息?在调试构建中,我发现Eigen(线性代数包)似乎需要永远乘以小向量和矩阵([2x1]*[2x2][1x2]),但这应该是立即的。这就是为什么我想看看优化构建是否有帮助。@Grzenio:1)对不起,我很少用gcc及其链接器来做这件事,但如果你花一点时间