【问题标题】:GPROF profiling tool is inaccurate execution timeGPROF 分析工具的执行时间不准确
【发布时间】:2019-07-13 19:53:35
【问题描述】:

我尝试在 ubuntu 上使用 gprof 测试我的 cpp 代码。

但我发现了一些错误。

gprof计算执行时间时,最小时间单位为0.01秒。

例如,如果我的函数在我的程序中的执行时间为 0.001 甚至更快,gprof 将识别为 0 秒。

即使我执行我的函数一千次,它也会这样计算:0/s + 0/s ...。 + 0/s = 0/s

但实际运行时间是 1 秒……

所以,我想知道如何修改最小时间单位或计算确切的执行时间。

请帮帮我:)

而且我不需要其他分析工具的任何推荐

【问题讨论】:

  • 我不需要其他分析工具的任何推荐,但我建议你看看valgrind(它不仅仅是一个内存检查器) Cachegrind/Callgrind/KCachegrind
  • gprof 因任何合理的时间分析而被破坏。它不切实际地假设每次调用foo(int N) 都需要相同的时间。因此,如果foo(N) 的复杂度是 pow(2, N),并且 foo(1) 从函数 fast 被调用 99 次(总共不到一秒)并且 foo(30) 从函数 slow 被调用 1 次(需要一分钟),那么 gprof 会错误地说 fast 需要一分钟,而 slow 需要 0.6 秒。

标签: c++ profiling profiler execution-time gprof


【解决方案1】:

这个问题几乎是inaccuracy in gprof output的重复,但有一点不同:看起来它试图在错误的地方找到性能瓶颈:

即使我执行我的函数一千次,它也会这样计算: 0/s + 0/s .... + 0/s = 0/s

这不是 gprof 的工作方式。 Gprof 在 T 中对程序计数器进行一次采样(通常为 0.01 秒)。它不只是总结时间测量,而是依赖于统计数据。一个占用 1.00 CPU 的程序永远不会从它应该获得的大约 100 个样本中采样出来的可能性非常低。 80 个样本是可能的,120 个是可能的,0 个几乎是不可能的。所以你的问题出在其他地方。

Gprof 有很多限制,如inaccuracy in gprof output 所示。真正的问题要么是时间花在 I/O 上,要么是复杂的相互递归,要么是在共享库中,或者它试图重用 gprof 用于对代码进行采样的相同信号。

如果你还是坚持要改变采样率,那理论上是可以的,但是太复杂了,不值得。 have been claims 重写了 profil()monstartup() 函数。您可以使用链接器工具(例如LD_PRELOAD)覆盖它们。鉴于 gprof 的局限性,这条路不值得走,而且我看不到任何对实际执行此操作的代码的引用。

这是尼克·克利夫顿对此事的引用:

所以你的选择是:

  1. 在您的操作系统中更改 profile() 函数。
  2. 编写您自己的 monstartup() 函数并找到其他方法来生成时间样本。

我试图通过修改 SIGPROF 间隔来修改间隔:

void set_interval(double seconds)                                                                                                                                              
{                                                                                                                                                                              
      if (seconds <= 0)                                                                                                                                                          
          return;                                                                                                                                                                
      itimerval prev, next;                                                                                                                                                      
      next.it_value.tv_sec = (uint64_t) seconds;                                                                                                                                 

      next.it_value.tv_usec = (uint64_t)(1000000 * (seconds - next.it_value.tv_sec));                                                                                            
      next.it_interval = next.it_value;                                                                                                                                          
      setitimer(ITIMER_PROF, &next, &prev);                                                                                                                                      
}

在我尝试过的 Linux 上,来自 main 的 set_interval(0.1) 确实将时间间隔更改为 1/10 秒(但在 gprof 输出中报告错误)。但是运行set_interval(0.001) 对我的机器没有影响,因为最精细的粒度设置为 10 毫秒。任何低于 10 毫秒的时间都会在内部增加到 10 毫秒。要克服这个限制,请阅读1ms resolution timer under linux recommended way

这太荒谬了,我强烈建议你放弃这条路线并寻找不同的分析器,或者找出 gprof 不适合你的原因。

【讨论】:

    猜你喜欢
    • 2011-06-29
    • 2011-02-17
    • 1970-01-01
    • 2011-09-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多