8

我尝试开始使用 Google Perf Tools 来分析一些 CPU 密集型应用程序。这是一种统计计算,使用“ofstream”将每个步骤转储到文件中。我不是 C++ 专家,所以我很难找到瓶颈。我的第一遍给出了结果:

总计:857 个样本
     357 41.7% 41.7% 357 41.7% _write$UNIX2003
     134 15.6% 57.3% 134 15.6% _exp$fenv_access_off
     109 12.7% 70.0% 276 32.2% scythe::dnorm
     103 12.0% 82.0% 103 12.0% _log$fenv_access_off
      58 6.8% 88.8% 58 6.8% scythe::const_matrix_forward_iterator::operator*
      37 4.3% 93.1% 37 4.3% scythe::matrix_forward_iterator::operator*
      15 1.8% 94.9% 47 5.5% 标准::转换
      13 1.5% 96.4% 486 56.7% SliceStep::DoStep
      10 1.2% 97.5% 10 1.2% 0x0002726c
       5 0.6% 98.1% 5 0.6% 0x000271c7
       5 0.6% 98.7% 5 0.6% _write$NOCANCEL$UNIX2003

这是令人惊讶的,因为所有真正的计算都发生在 SliceStep::DoStep 中。“_write$UNIX2003”(我在哪里可以找到这是什么?)似乎来自写入输出文件。现在,让我感到困惑的是,如果我注释掉所有outfile << "text"语句并运行 pprof,95% 就在SliceStep::DoStep其中,而 `_write$UNIX2003' 消失了。但是,按总时间衡量,我的应用程序并没有加快速度。整个过程的速度不到 1%。

我错过了什么?

补充:没有语句的 pprof 输出outfile <<是:

总计:790 个样本
     205 25.9% 25.9% 205 25.9% _exp$fenv_access_off
     170 21.5% 47.5% 170 21.5% _log$fenv_access_off
     162 20.5% 68.0% 437 55.3% scythe::dnorm
      83 10.5% 78.5% 83 10.5% scythe::const_matrix_forward_iterator::operator*
      70 8.9% 87.3% 70 8.9% scythe::matrix_forward_iterator::operator*
      28 3.5% 90.9% 78 9.9% 标准::转换
      26 3.3% 94.2% 26 3.3% 0x00027262
      12 1.5% 95.7% 12 1.5% _write$NOCANCEL$UNIX2003
      11 1.4% 97.1% 764 96.7% SliceStep::DoStep
       9 1.1% 98.2% 9 1.1% 0x00027253
       6 0.8% 99.0% 6 0.8% 0x000274a6

这看起来像我所期望的,除了我没有看到性能的明显提升(10 秒计算中的 0.1 秒)。代码本质上是:

ofstream outfile("out.txt");
for loop:
  SliceStep::DoStep()
  outfile << 'result'
outfile.close()

更新:我使用 boost::timer 计时,从分析器开始的地方开始,到结束的地方结束。我不使用线程或任何花哨的东西。

4

3 回答 3

3

从我的评论:

您从分析器获得的数字表明,如果没有打印语句,该程序应该快 40% 左右。

但是,运行时几乎保持不变。

显然其中一个测量值一定是错误的。这意味着您必须进行更多更好的测量。

首先,我建议从另一个简单的工具开始:时间命令。这应该让您大致了解您的时间都花在了哪里。

如果结果仍然没有定论,您需要一个更好的测试用例:

  • 使用更大的问题
  • 测量前进行预热。做一些循环,然后开始任何测量(在同一过程中)。

Tiristan:一切都在用户中。我正在做的事情很简单,我认为......文件一直打开的事实是否意味着什么?

这意味着分析器是错误的。

使用 python 将 100000 行打印到控制台会产生如下结果:

for i in xrange(100000):
    print i

安慰:

time python print.py
[...]
real    0m2.370s
user    0m0.156s
sys     0m0.232s

相对:

time python test.py > /dev/null

real    0m0.133s
user    0m0.116s
sys     0m0.008s

我的观点是: 您的内部测量时间表明您不会从禁用输出中获得任何收益。谷歌性能工具说你应该。谁错了?

于 2009-06-16T20:06:13.453 回答
1

_write$UNIX2003 可能是指write输出到终端的 POSIX 系统调用。与几乎其他任何东西相比,I/O 都非常慢,因此如果您正在编写相当多的输出,那么您的程序在此花费大量时间是有道理的。

我不确定为什么您的程序在删除输出时不会加速,但我无法仅凭您提供的信息做出猜测。很高兴看到一些代码,甚至是删除 cout 语句后的 perftools 输出。

于 2009-06-16T19:04:00.620 回答
1

Google perftools 收集调用堆栈的样本,因此您需要了解这些样本。

根据文档,您可以在语句或地址粒度上显示调用图。这应该告诉你你需要知道什么。

于 2009-06-18T18:14:54.020 回答