哪个是最可靠的分析工具gprof或k​​cachegrind?

时间:2011-06-13 09:28:46

标签: c++ profiling gprof kcachegrind

使用gprofkcachegrind分析一些C ++数字运算代码,对于对执行时间贡献最大的函数(50-80%,取决于输入)给出类似的结果,但对于10-之间的函数这些工具中有30%会产生不同的结果。这是否意味着其中一个不可靠?你会在这做什么?

2 个答案:

答案 0 :(得分:7)

gprof 实际上非常原始。这是它的作用。 1)以恒定速率对程序计数器进行采样,并记录每个功能中有多少样本(独占时间)。 2)它计算任何函数A调用任何函数B的次数。 从中可以看出每个函数总共调用了多少次,以及它的平均独占时间是多少。 为了获得每个函数的平均包含时间,它在调用图中向上传播独占时间。

如果您希望这具有某种准确性,您应该了解一些问题。 首先,它只计算CPU进程中的时间,这意味着它对I / O或其他系统调用是盲目的。 其次,递归混淆了它。 第三,功能总是遵循平均运行时间的前提,无论何时被呼叫或者呼叫它们,都是非常可疑的。 第四,函数(和它们的调用图)是你需要知道的而不是代码行的概念,仅仅是一种流行的假设,仅此而已。 第五,测量精度甚至与发现“瓶颈”相关的概念也只是一种流行的假设,仅此而已。

Callgrind可以在线路上工作 - 这很好。不幸的是,它与其他问题有关。

如果您的目标是找到“瓶颈”(而不是进行常规测量),您应该看一下逐行报告的挂钟时间堆栈采样器,例如Zoom。 原因很简单,但可能不熟悉。

假设你有一个程序,其中有一堆函数相互调用,总共需要10秒钟。此外,还有一个采样器,它不仅对程序计数器进行采样,而且对整个调用堆栈进行采样,并且它以恒定速率进行采样,例如每秒100次。 (暂时忽略其他流程。)

所以最后你有1000个调用堆栈样本。 选择出现在多个代码中的任何代码行L. 假设您可以通过避免它,删除它或将其传递给真正非常快的处理器来以某种方式优化该行。

这些样品会发生什么?

由于那行代码L现在(基本上)没有时间,所以没有样本可以点击它,因此这些样本只会消失,从而减少了样本总数,因此减少了总数时间! 事实上,总时间将减少L在堆栈上的时间部分,这大约是包含它的样本的一小部分。

我不想太统计,但很多人认为你需要大量的样本,因为他们认为测量的准确性很重要。 它不是,如果你这样做的原因是要找出解决方法以获得加速。 重点是找到要修复的内容,而不是测量它。 L行在堆栈的某个F部分的时间,对吧? 所以每个样本都有一个击中它的概率F,对吧?就像掷硬币一样。 有一个理论,称为Rule of Succession。 它说(在简化但一般的假设下),如果你掷硬币N次,并看到“头”S次,你可以估计硬币F的公平性(平均)(S+1)/(N+2)。 因此,如果你只需要三个样本,并在两个中看到L,你知道F是什么吗? 当然不是。 但是你平均知道它是(2 + 1)/(3 + 2)或 60%。 那么你可以通过“优化远离”线L来节省(平均)多少时间。 当然,堆栈样本显示完全其中L行(“瓶颈”**)。 你没有把它测量到两位或三位小数真的很重要吗?

顺便说一句,它不受all the other problems mentioned above的影响。

**我一直在引用“瓶颈”,因为使大多数软件变慢的原因与瓶颈没有任何共同之处。 一个更好的比喻就是“消耗” - 只是不必要地浪费时间。

答案 1 :(得分:2)

gprof的时间数据是统计数据(在details of profiling文档中了解)。

另一方面,KCacheGrind使用valgrind实际解释所有代码。

因此KCacheGrind可以“更准确”(以更多开销为代价)如果valgrind建模的CPU接近您的真实CPU。

选择哪一个还取决于您可以处理的开销类型。根据我的经验,gprof增加了较少的运行时开销(执行时间),但它更具侵入性(即-pg为每个函数添加代码)。因此,根据具体情况,在另一方面更合适。

对于“更好”的gprof数据,请更长时间运行代码(并尽可能广泛地使用测试数据)。你拥有的越多,测量结果就越好。