0

プログラムのプロファイルを作成しましたが、基本的に次の式の評価に CPU 時間の 20% を費やしています。

abs(x) > abs(y)

ここで、x、y は倍精度浮動小数点変数です。

式をより高速なバリアントにリファクタリングする方法はありますか?

次の行 (2 つの異なる場所で呼び出されます) は、各行で 10% 近くの CPU 時間を消費します。

(これは関数 Image_3::TestGradientAtPoint からの抜粋です)

       if (abs(maxx[ch]) < abs(a)) maxx[ch] = a; 
01187AC9  mov         eax,dword ptr [ch]  
01187ACC  sub         esp,8  
01187ACF  fld         qword ptr [ebp+eax*8-68h]  
01187AD3  fstp        qword ptr [esp]  
01187AD6  call        abs (11305F9h)  
01187ADB  fld         qword ptr [ebp-70h]  
01187ADE  fstp        qword ptr [esp]  
01187AE1  fstp        qword ptr [ebp-0F8h]  
01187AE7  call        abs (11305F9h)  
01187AEC  add         esp,8  
01187AEF  fcomp       qword ptr [ebp-0F8h]  
01187AF5  fnstsw      ax  
01187AF7  test        ah,41h  
01187AFA  jne         Image_3::TestGradientAtPoint+176h (1187B06h)
01187AFC  mov         eax,dword ptr [ch]  
01187AFF  fld         qword ptr [ebp-70h]  
01187B02  fstp        qword ptr [ebp+eax*8-68h]  

プロファイラーは、abs() の呼び出しに 20% の CPU 時間がかかったと述べています。私は10 ^ 8回の反復でメソッドを呼び出しています-私は大きな画像を扱っています。

編集

言い忘れましたが、コードはデバッグ モードで実行されます。ここで少し最適化する必要があります。MSVC デバッガーを適切な時間内に使用できるようにしたいからです。

4

5 に答える 5

6

これは速くはないかもしれませんが、算術式がより速く評価される場合:

if ((x - y) * (-x - y) < 0)
    // then abs(x) > abs(y)

これにより、abs メソッドの 3 つの式ではなく、式の数が 3 (2 の算術式とゼロとの比較) に修正されると思います (各 abs は負かどうかをチェックし、符号を反転し、それ以外の場合は値を返し、各 abs を比較します)。

編集:

アンドレが言ったように、フロートをいつでも明示的に二乗できます。振り返ってみると、はるかに理にかなっています。

if (x * x > y * y)
    // then abs(x) > abs(y)

(xy)(-xy) = y^2-x^2 なので

于 2013-03-05T18:06:13.927 に答える
5

コンパイラに最適化を指示します。GCC または clang では、-O2または-O3フラグを使用してこれを行います。後者はより積極的です。/O2MSVC では、フラグまたはフラグを使用できます/Ox(IIRC; 私はめったにそのコンパイラを使用しません)。最適化を有効にしないと、100000000 回の反復がすぐに実行されるとは期待できません。

最適化をオンにせずに妥当な時間枠内でデバッグしたい場合は、より小さいデータ セットを試してください。または、Mysticial が述べたように、最適化をオンにしてデバッグし、デバッガーでランダムに変化する値やその他の難解な観察結果を受け入れます。

于 2013-03-05T17:56:49.977 に答える
4

順序がmaxx[]重要でない場合は、並べ替えることができ、より高速になると思います。

もう1つのことは、「a」maxx[]ができることすべてが同じである場合a= abs(a);、直接aと比較することです。

もっと役立つようにするには、もっとコードを見る必要があります。

于 2013-03-05T17:42:36.890 に答える
2

これはこれ以上速くはないかもしれませんが、別の論理バージョンは次のようになります。

// logical replacement for abs(x) > abs(y)
x >= 0 ? 
    y >= 0 && x > y :
    y <= 0 && x < y ;

コンパレータとブランチのみを使用しているため、高速になる可能性がありますが、保証はありません...

そうでない場合は、fabs浮動小数点数用に設計されているため、代わりに使用してみてください。

于 2013-03-05T17:50:32.403 に答える
2

最初に確認することは、実際に最適化を有効にしていることです。そうでない場合は、おそらくコンパイラが呼び出しをインライン化していないため、十分なオーバーヘッドが発生していることがわかります。

実際に最適化が有効になっていると思われる場合は、アルゴリズムのアプローチを採用する必要があります。absそれを速くするためにあなたができることは何も考えられません。

したがって、次のようなことを考慮する必要があります。

  • 元の負の数を気にしますか、それともデータを事前にフィルター処理してそれをabs修正できますか?
  • 順番気になりますか?アルゴリズムを改善するためにデータをソートできますか
  • absループ内で何度も変化しない値を計算していますか?
于 2013-03-05T17:52:14.973 に答える