C ++プロファイリング(google cpu perf tools)は正確に何を測定しますか?

StackOverflow https://stackoverflow.com/questions/1003309

  •  05-07-2019
  •  | 
  •  

質問

CPUを集中的に使用するアプリケーションのプロファイルを作成するために、Google Perf Toolsの使用を開始しようとしています。 「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で行われるため、これは驚くべきことです。 <!> quot; _write $ UNIX2003 <!> quot; (これがどこにあるのかはどこで確認できますか?)出力ファイルの書き込みから来ているようです。今、私を混乱させているのは、すべてのoutfile << "text"ステートメントをコメントアウトしてpprofを実行すると、95%がSliceStep::DoStepにあり、「_ write $ UNIX2003」がなくなるということです。ただし、合計時間で測定すると、アプリケーションは高速化されません。全体の速度は1%未満です。

不足しているものは何ですか?

追加: outfile <<ステートメントなしのpprof出力は次のとおりです。

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秒の計算で.1秒)ことを除いて、私が期待するもののように見えます。コードは基本的に次のとおりです。

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

更新:boost :: timerを使用して、プロファイラーの開始位置から終了位置までのタイミングを計ります。私はスレッドや派手なものを使用しません。

役に立ちましたか?

解決

私のコメントから:

プロファイラーから得た数字は、printステートメントを使用しない場合、プログラムは約40%高速になるはずだと言っています。

ただし、ランタイムはほぼ同じです。

明らかに、測定値の1つが間違っている必要があります。つまり、より多くのより良い測定を行う必要があります。

まず、もう1つの簡単なツールであるtimeコマンドから始めることをお勧めします。これにより、時間を費やしている場所の大まかなアイデアが得られます。

結果がまだ決定的でない場合、より良いテストケースが必要です:

  • より大きな問題を使用する
  • 測定前にウォームアップを行います。ループを実行し、その後測定を開始します(同じプロセスで)。

  

ティリスタン:すべてユーザーです。私がやっていることは非常に簡単です、私は思う...ファイルが常に開いているという事実は何を意味しますか?

これは、プロファイラーが間違っていることを意味します。

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