如何分析程序运行时间

How to analyze program running time

本文关键字:程序 运行时间      更新时间:2023-10-16

我正在努力优化c++程序的性能并减少其运行时间。然而,我很难弄清楚瓶颈在哪里。

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

CPU探查器(gcc探查器和googleperftool)显示,函数调用总共只需要60秒的CPU时间。我还尝试使用探查器来实时采样,而不是cpu时间,它给了我类似的结果。

I/O探查器(我使用过ioapps)还显示,I/O只需要大约30秒的程序运行时间。

因此,基本上我有3.5分钟(程序运行时间的最大部分)没有计算在内,我相信这就是瓶颈所在

我错过了什么?我如何知道那段时间会去哪里?

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

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

如果你这样做几次,你就会确切地看到是哪条线造成了瓶颈。一旦你在两(2)个样本上看到它,你就已经把它钉住了。然后修复它,然后再做一遍,找到下一个瓶颈,以此类推。你可以很容易地发现,你可以通过这种方式获得巨大的加速。

<火焰>

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

如果您实际查看堆栈样本,它们确实会显示自己。因此,好的轮廓仪的问题不在于样本的收集,而在于结果的呈现。统计和测量无法告诉你,经过仔细检查的一小部分样本确实告诉了你什么。

样本数量少与样本数量大的问题如何?不是更好吗?好吧,假设你有一个无限循环,或者如果不是无限的,它只是运行的时间比你知道的要长得多?1000个堆叠样本会比单个样本更好吗?(不是。)如果你在调试器下看它,你就会知道你在循环中,因为它基本上需要100%的时间。它在堆栈的某个地方——只需向上扫描堆栈,直到找到它。即使循环只需要50%或20%的时间,这也是每个样本看到它的概率。所以,如果你在两个样本上看到了可以去除的东西,那么这是值得的。那么,1000个样品给你买了什么?

也许有人会想:"如果我们错过了一两个问题怎么办?也许这已经足够好了。"好吧,是吗?假设代码有三个问题,P占用50%的时间,Q占用25%的时间,R占用12.5%的时间。这显示了如果你修复其中一个、两个或全部三个,你会得到加速。

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

这是否说明了为什么那些"逃跑"的人真的很受伤?如果你错过了任何一个,你能做的最好的是慢一倍。

如果你检查样品,它们很容易找到。P在一半的样本上。如果你修正了P,然后再做一次,Q在一半的样本上。一旦你确定了Q,R就在一半的样本上。修复R,您就可以获得8倍的加速。你不必就此止步。你可以一直坚持下去,直到你真的找不到任何可以解决的问题。

问题越多,潜在的加速就越高,但你不能错过任何一个。评测器(即使是好的评测器)的问题是,通过剥夺你查看和研究单个样本的机会,它们隐藏了你需要发现的问题。更多内容对于有统计学倾向的人来说,以下是它的工作原理

有很好的剖析者。最好的是壁时堆栈采样器,它可以报告单个行的包含百分比,让您可以通过热键打开和关闭采样。Zoom(wiki)就是这样一个探查器。

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

<火焰>