当对代码进行性能分析时,是否应该使用匹配(gcc)编译器优化标志?

4

我在编译代码时使用了 -O3,现在我需要对其进行分析。在分析方面,我发现有两个主要选择:valgrind --tool=callgrindgprof

Valgrind(callgrind)文档中提到:

与Cachegrind一样,您可能希望使用调试信息(-g选项)和启用优化来编译。

然而,在Agner Fog的C++优化书籍中,我读到了以下内容:

许多优化选项与调试不兼容。调试器可以逐行执行代码并显示所有变量的值。显然,当代码的某些部分已被重新排序、内联或优化掉时,这是不可能的。通常会制作两个可执行程序版本:一个具有完整调试支持的调试版本,用于程序开发,另一个是打开所有相关优化选项的发布版本。大多数IDE(集成开发环境)都有制作对象文件和可执行文件的调试版本和发布版本的工具。请确保区分这两个版本,并在优化版本的可执行文件中关闭调试和分析支持。

这似乎与callgrind指令编译代码时带上调试信息标志-g相冲突。如果我按以下方式启用调试:

-ggdb -DFULLDEBUG

我使用这个选项不是会与-O3优化标志冲突吗? 在我所阅读的内容中,同时使用这两个选项对我来说没有意义。

如果我使用 -O3 优化标志,我能否通过以下方式编译带有额外性能分析信息的代码:

-pg

您是否需要使用valgrind分析代码性能?

对于已经编译的代码进行分析,是否有意义?

-ggdb -DFULLDEBUG -O0

flags?这似乎很愚蠢-不内联函数和展开循环可能会转移代码中的瓶颈,因此这仅适用于开发,以使代码实际上正确地完成任务。

是否有意义使用一个优化标志编译代码,并使用另一个优化标志编译后对代码进行分析?


使用不同的优化标志进行剖析是没有意义的,因为你会得到不同的代码剖析结果。请注意,剖析与调试并不相同。 - juanchopanza
@juanchopanza:谢谢,我也猜到了。但是为什么callgrind要求使用“-g”标志呢?使用“-g”允许调试器提供有关堆栈的信息,这与“-O”选项冲突,对吗? - tmaric
3
-g-O 标志不会发生太多冲突。这里有一个很好的讨论:https://dev59.com/F3VD5IYBdhLWcg3wGXlI - juanchopanza
@juanchopanza:谢谢! - tmaric
1个回答

3
为什么要进行性能分析?只是为了获得测量数据还是为了找到加速方法?
一般认为只有在代码已经优化到接近极限时才需要进行性能分析,但如果存在很大的加速空间,这种做法就不适用了。
应该将查找加速方法视为查找错误一样对待。许多人使用这种方法来实现此目的。
如果您已经删除了不必要的计算,但仍然存在紧密的CPU循环,即您没有花费所有时间在系统、库或I/O例程中,而优化程序没有发现,请打开-O3选项,让它发挥其魔力。

我已经编写好了代码并且获得了预期的结果,使用 std::chrono 进行了自己的测量,以找出哪些全局算法子部分会导致最大的瓶颈。我只是想看看在优化某些子算法时我能获得多少收益。问题肯定存在于我自己编写的两个算法中,所以基本上我感兴趣的是量化新版本方法将快多少。感谢提供替代方法,我会去尝试一下。 - tmaric
我已经阅读了您在网上关于“随机暂停”的所有帖子,我认为我理解了分析器的测量和自己检查堆栈之间的区别。在一篇帖子中,您提到10个样本应该足以找到当前优化周期中罪魁祸首(我多次降落的代码部分)-这是来自您的经验吗? - tmaric
1
@tomislav-maric: 我在这个问题上一直很烦人 :-). 我早在性能分析器问世之前就一直在使用这种方法,令我惊讶的是它并不是普遍知识。普遍假设似乎是任何工具都比人类能做到的更好,在其他领域这是正确的,但在性能分析方面却不是。认为需要测量准确度(因此需要大量样本)的想法毫无根据,而为此付出的代价则是错失了可能的加速优化机会。除非性能分析器能像人一样理解代码,否则这种情况将继续存在。 - Mike Dunlavey
1
@tomislav-maric:可能不是重复的指令。比如,可能有多个地方将 new 放在堆栈上,或者有几个不同的容器类正在尝试增长。这些是分析器无法联系到一起的事情,但你可以立即看到它们。如果一个问题耗费了,比如说,10% 的时间,那么你需要看到它两次的平均样本数就是 2/0.1 = 20。通常问题比这还要大,所以只需要更少的样本就能看到它们两次。你只看到一次的东西可能很有趣,但你需要看到两次或更多次才能确定它值得修复。 - Mike Dunlavey
1
非常感谢您的建议!实际上,我正在编写一个进行几何计算的代码,并且数据结构经常会改变大小。到目前为止,我想到的唯一方法是切换数据结构并查看哪些最适合一组测试用例。使用您的方法,我可能能够了解发生这种情况的条件,并考虑更好的容器扩展策略。 - tmaric
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接