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

Total: 857 samples
     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% std::transform
      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”消失了。然而,从总时间来看,我的应用程序并没有加速。整个过程的速度加快了不到百分之一。

我缺少什么?

添加:pprof 输出不带 outfile << 陈述是:

Total: 790 samples
     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% std::transform
      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 进行计时,从探查器开始的地方开始,到结束的地方结束。我不使用线程或任何花哨的东西。

有帮助吗?

解决方案

从我的评论来看:

从分析器获得的数据表明,如果没有 print 语句,程序的速度应该提高 40% 左右。

然而,运行时间几乎保持不变。

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

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

如果结果仍然不是结论性的,您需要一个更好的测试用例:

  • 使用更大的问题
  • 测量前先进行热身。进行一些循环并随后开始任何测量(在同一过程中)。

蒂里斯坦:一切都在用户中。我认为我正在做的事情很简单...文件一直打开的事实有什么意义吗?

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

使用 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

我的观点是:您的内部测量值 时间显示您不会从禁用输出中获得任何好处。Google Perf Tools 说你应该这样做。谁错了?

其他提示

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

我不确定为什么你的程序在删除输出时不会加速,但我不能真正猜测你给出的信息。很高兴看到一些代码,甚至在删除cout语句时输出的perftools。

Google perftools会收集调用堆栈的示例,因此您需要了解这些内容。

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top