最近、OProfileを使用してアプリケーションのプロファイリングを試みました。収集されたデータはすでに私にとって非常に貴重ですが、その正確な解釈に苦労しています。oprofileを設定して実行してアプリを実行した後、レポートを生成して次の情報を取得しました。
root @ se7xeon:src#opreport image:test -l -t 1
オーバーフロー統計は使用できません
CPU:P4 / Xeon、2つのハイパースレッド、速度3191.66 MHz(推定)
カウントされたGLOBAL_POWER_EVENTSイベント(プロセッサが停止していない時間) 0x01のユニットマスク(必須)カウント750000
サンプル%シンボル名
215522 84.9954 cci :: Image :: interpolate(unsigned char *、cci :: Matrix const&)const
17998 7.0979 cci :: Calc :: diff(unsigned char const *、unsigned char const *)
13171 5.1942 cci :: Image :: getIRect(unsigned char *、int、int)const
5519 2.1765 cci :: Image :: getFRect(unsigned char *、double、double)const
さて、私の補間関数は、アプリケーションの(長すぎる)実行時間の84%を占めています。それからそれを調べるのは良い考えのようです:
root @ se7xeon:src#opannotate image:test --source
[...]
/* cci::Image::interpolate(unsigned char*, cci::Matrix<cci::Point2DF> const&) const total: 215522 84.9954 */
1392 0.5529 :void Image::interpolate(CCIPixel *output, const Matrix<Point2DF> &inputPoints) const throw()
4 0.0016 :{
[...]
: col0 = static_cast<int>(point[idx].x);
3 0.0012 : col1 = col0+1;
629 0.2498 : row0 = static_cast<int>(point[idx].y);
385 0.1529 : row1 = row0+1;
56214 22.3266 : if (col0 < 0 || col1 >= m_width || row0 < 0 || row1 >= m_height)
: {
: col0 = row0 = col1 = row1 = 0;
: }
私が正しく理解していれば、if条件はプログラムの実行時間の22%以上を占めています。冒頭の中括弧と関数宣言には時間がかかるようですが、これは関数呼び出しのオーバーヘッド(「スタック、ジャンプ、ポップパラメーターのプッシュパラメーター」シーケンス)に対応するはずですか?
ソース内のいくつかの変更(ifを最適化する方法がわからなかったため、後のボトルネックに関連)、再コンパイル、oprofileの再実行(opcontrol --resetを忘れないでください)。これで、注釈付きのコードは同じ場所で次のようになります。
6 0.0024 : curPx = point[idx].x;
628 0.2477 : curPy = point[idx].y;
410 0.1617 : col0 = static_cast<int>(curPx);
57910 22.8380 : col1 = col0+1;
: row0 = static_cast<int>(curPy);
: row1 = row0+1;
: if (col0 < 0 || col1 >= m_width || row0 < 0 || row1 >= m_height)
: {
: col0 = row0 = col1 = row1 = 0;
: }
今回はifは基本的に全く時間がかからず(?)、最も高価な命令は「col1 = col0 + 1」であり、時間のかかるブロック全体が上にシフトしているようです。どうすればいいの?これは、ソースのボトルネックを特定するためにまったく信頼できますか?
もう1つの疑問点は、opcontrolを設定したときに、トレースされたイベントをGLOBAL_POWER_EVENTSとして入力し、サンプル数が750kであったことです。出力では、補間関数は84%を占めるように見えますが、その中に記録されたサンプルの数は200kを少し上回っています。それは要求された数の50%でもありません。残りの約500kのサンプルは、出力にリストされていないアプリケーション(カーネル、Xorgなど)によって取得されたことを理解していますか?