c++ - 如何分析程序运行时间

标签 c++ performance profiling gprof

我正在尝试优化 C++ 程序的性能并减少其运行时间。但是,我无法弄清楚瓶颈在哪里。

time命令显示程序本身运行大约需要5分钟,大约5分钟,用户cpu时间需要4.5分钟。

CPU 分析器(gcc 分析器和 google perftool)显示该函数调用在 CPU 时间中总共只需要 60 秒。我还尝试使用分析器来实时采样而不是 CPU 时间,它给了我类似的结果。

I/O 分析器(我使用 ioapps)也显示 I/O 只需要大约 30 秒的程序运行时间。

所以基本上我有 3.5 分钟(程序运行时间的最大部分)下落不明,我相信这就是瓶颈所在。

我错过了什么,我如何知道时间去哪儿了?

最佳答案

正如 Öö Tiib 建议的那样,只需在调试器中中断程序即可。我这样做的方法是让程序运行,切换到输出窗口,键入 Ctrl-C 中断程序,切换回 GDB 窗口,键入“线程 1”以便在主程序的上下文中,并键入“bt”以查看堆栈跟踪。

现在,查看堆栈跟踪并理解它,因为虽然程序计数器上的指令负责所花费的特定周期,但堆栈上的每次调用也是如此。

如果你这样做几次,你会看到到底是哪条生产线造成了瓶颈。
当您在两 (2) 个 sample 上看到它时,您就成功了。
然后修复它,再做一遍,找到下一个瓶颈,依此类推。
您会很容易发现通过这种方式获得了巨大的加速。

<火焰>

有人说这正是分析器所做的,只是他们做得更好。
这就是你在演讲厅和博客上听到的,但这是交易:
有一些方法可以加速您的代码,这些方法不会将自己显示为“慢功能”或“热路径”,例如 - 重新组织数据结构。
每个函数看起来或多或少都是无辜的,即使它具有很高的包含时间百分比。

如果您实际查看堆栈示例,它们确实会显示出来。
因此,好的分析器的问题不在于样本的收集,而在于结果的呈现。统计和测量无法告诉您,仔细检查的一小部分样本确实可以告诉您什么。

小样本与大样本的问题呢?不是越多越好吗?
好吧,假设你有一个无限循环,或者如果不是无限循环,它运行的时间比你知道的要长得多? 1000 个堆栈样本会比单个样本更好吗? (不。)如果您在调试器下查看它,您就会知道您处于循环中,因为它基本上需要 100% 的时间。它在堆栈中的某个地方 - 只需扫描堆栈直到找到它。
即使循环只占用 50% 或 20% 的时间,这也是每个样本看到它的概率。
因此,如果您看到可以在少至两个样本上摆脱的东西,那就值得去做。
那么,这 1000 个 sample 会给您带来什么?

也许有人会想:“那如果我们错过了一两个问题怎么办?也许这已经足够了。”嗯,是吗?
假设代码有三个问题,P 占 50%,Q 占 25%,R 占 12.5%。好东西叫做A。
这显示了修复其中一个、两个或所有三个时获得的加速。

PRPQPQPAPQPAPRPQ original time with avoidable code P, Q, and R all mixed together
RQQAQARQ         fix P           - 2 x   speedup
PRPPPAPPAPRP     fix Q           - 1.3 x    "
PPQPQPAPQPAPPQ   fix R           - 1.14 x   "
RAAR             fix P and Q     - 4 x      "
QQAQAQ           fix P and R     - 2.7 x    "
PPPPAPPAPP       fix Q and R     - 1.6 x    "
AA               fix P, Q, and R - 8 x   speedup

这是否说明了为什么“逃脱”的人真的会受伤?
如果你错过任何一个,你能做的最好的事情就是慢两倍。

如果您检查 sample ,它们很容易找到。 P 在一半的样本上。
如果您修复 P 并再次执行,则 Q 位于一半的样本上。一旦你修复了 Q,R 就在一半的样本上。
修复 R,你就获得了 8 倍的加速。
你不必停在那里。你可以继续前进,直到你真的找不到任何东西可以解决。

问题越多,潜在的加速就越高,
但你不能错过任何一个。
分析器(即使是好的分析器)的问题在于,通过剥夺您查看和研究单个样本的机会,它们隐藏了您需要查找的问题。
More on all that.
For the statistically inclined, here's how it works.

有很好的分析器。
最好的是挂墙时间堆栈采样器,它报告单个行的包含百分比,让您可以使用热键打开和关闭采样。
Zoom ( wiki ) 就是这样一个分析器。

但即使是那些假设您需要大量样本的错误。
你没有,你为它们付出的代价是你实际上看不到任何东西,所以你看不到为什么要花时间,所以你不能轻易判断是否有必要,
除非你知道你不需要它,否则你无法摆脱它。
结果是你错过了瓶颈,它们最终会阻碍你的加速。

关于c++ - 如何分析程序运行时间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18194577/

相关文章:

c++ - const(但不是 constexpr)用作内置数组大小

c++ - 解释为什么在 C++ 中应该首选 int 而不是 long/short?

lambda 表达式的 Java 堆转储分析

java - 内存分析 : How to detect which application/package is consuming too much memory

postgresql - 如何分析 plpgsql 程序

C++在类函数中和类外写入文件

c++ - FFTW输入输出显示DSP?

C++ - 全局静态对象和局部静态对象的构造函数调用是否不同?

android - 在 ListView 中点击打开一个android Activity 需要很长时间

sql - 用于在数据库中查找用户的 SQL 查询的性能