【问题标题】:How to analyze program running time如何分析程序运行时间
【发布时间】:2013-08-14 05:05:51
【问题描述】:

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

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

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

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

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

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

【问题讨论】:

  • 根据您给我们的信息,我最好的猜测是您没有正确读取分析器的输出。贴出 gprof/perf/strace 的输出(至少前 15 行左右)。
  • 你不能在调试器中破坏程序几次看看它在哪里吗?通常它是大部分时间去的地方。
  • 我读对了吗? find_first_zero() 的 24.8 次 十亿 次调用?
  • 是的,但是这个函数是高度优化和内联的。跑起来只需要4秒,我比较在意4分钟。
  • 你能把你的代码附在你的帖子后面吗?

标签: c++ performance profiling gprof


【解决方案1】:

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

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

如果您这样做几次,您将确切地看到哪条线路是造成瓶颈的原因。 只要您在两 (2) 个样品上看到它,您就已经掌握了它。 然后修复它并再次执行所有操作,找到下一个瓶颈,依此类推。 您很容易发现通过这种方式获得了巨大的加速。

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

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

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

也许有人会想:“如果我们错过了一两个问题怎么办?也许这已经足够了。”嗯,是吗? 假设代码有三个问题,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

这是否说明了为什么“逃跑”的人真的很受伤? 最好的如果你错过任何一个,你可以做到的速度是原来的两倍。

如果您检查样本,很容易找到它们。 P 在一半的样本上。 如果您修复 P 并再次执行此操作,则 Q 在一半的样本上。一旦你修复了 Q,R 就在一半的样本上。 修复 R,你的加速是 8 倍。 你不必停在那里。你可以继续下去,直到你真的找不到任何可以解决的问题。

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

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

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

【讨论】:

    猜你喜欢
    • 2019-01-26
    • 1970-01-01
    • 1970-01-01
    • 2012-06-03
    • 2015-07-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多