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

Ope*_*way 2 c++ profiling gprof kcachegrind

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

Mik*_*vey 7

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

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

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

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

假设你有一个程序,其中一组函数相互调用,总共需要10秒钟.此外,还有一个采样器是样品,不只是程序计数器,而是整个调用堆栈,它确实这一切的时候以恒定的速率,如每秒100次.(暂时忽略其他进程.)

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

那些样品会发生什么?

由于该行代码L现在(基本上)没有时间,所以没有样本可以点击它,因此这些样本将消失,减少样本总数,从而减少总时间!实际上,总时间将减少L在堆栈上的时间分数,这大致是包含它的样本的分数.

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

顺便说一句,它不受上述所有其他问题的影响.

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


Mat*_*Mat 5

gprof的计时数据是统计数据(在分析文档的详细信息中阅读)。

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

因此,KCacheGrind可以“更准确”(在更大的开销为代价),如果通过建模的CPUvalgrind是接近您的真实CPU。

选择哪一个还取决于您可以处理的开销类型。根据我的经验,gprof增加较少的运行时开销(即执行时间),但它更具侵入性(即为-pg您的每一个函数添加代码)。所以要视情况而定,on or other更合适。

要获得“更好”的gprof数据,请更长时间地运行代码(并在尽可能广泛的测试数据上运行)。您拥有的越多,测量结果的统计效果就越好。