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%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'が消えることです。ただし、合計時間で測定すると、アプリケーションの速度は上がりません。全体の速度は1%未満です。

私は何が欠けていますか?

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

合計: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%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を使用してタイミングを調整し、プロファイラーの開始位置から開始して終了位置で終了します。私はスレッドや派手なものは使いません。

4

3 に答える 3

3

私のコメントから:

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

ただし、実行時間はほぼ同じままです。

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

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

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

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

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

私のポイントは、 内部測定時間は、出力を無効にしても何も得られないことを示しています。Google Perf Tools はそうすべきだと言っています。誰が間違っていますか?

于 2009-06-16T20:06:13.453 に答える
1

_write$UNIX2003 はおそらくwrite、端末に出力する POSIX システム コールを参照しています。I/O は他のほとんどのものに比べて非常に遅いため、かなりの量の出力を作成している場合、プログラムが I/O に多くの時間を費やしていることは理にかなっています。

出力を削除してもプログラムの速度が向上しない理由はわかりませんが、提供された情報だけでは推測できません。コードの一部、または cout ステートメントが削除されたときの perftools の出力を確認できれば幸いです。

于 2009-06-16T19:04:00.620 に答える
1

Google perftools はコール スタックのサンプルを収集するため、必要なのはそれらをある程度可視化することです。

ドキュメントによると、ステートメントまたはアドレスの粒度でコールグラフを表示できます。それはあなたが知る必要があることを教えてくれるはずです。

于 2009-06-18T18:14:54.020 に答える