1

私はいくつかのシミュレーション コードを書き、「GDB でランダムに中断する」方法のデバッグを使用しています。プログラムの時間の 99.9% がこのルーチンに費やされていることがわかりました (これは最小の画像規則です)。

inline double distanceSqPeriodic(double const * const position1, double const * const position2, double boxWidth) {
        double xhw, yhw, zhw, x, y, z;                                                                                 

        xhw = boxWidth / 2.0;                                                                                      
        yhw = xhw;                                                                                      
        zhw = xhw;                                                                                      

        x = position2[0] - position1[0];                                                                               
        if (x > xhw) 
                x -= boxWidth;                                                                                     
        else if (x < -xhw)
                x += boxWidth;                                                                                     


        y = position2[1] - position1[1];                                                                               
        if (y > yhw) 
                y -= boxWidth;                                                                                     
        else if (y < -yhw)
                y += boxWidth;                                                                                     


        z = position2[2] - position1[2];                                                                               
        if (z > zhw) 
                z -= boxWidth;                                                                                     
        else if (z < -zhw)
                z += boxWidth;                                                                                     

        return x * x + y * y + z * z;                                                                                  
}

これまでに実行した最適化 (あまり重要ではないかもしれません):

  • 平方根の代わりに距離の二乗を返します
  • インライン化する
  • 私ができることを主張する
  • 標準ライブラリの肥大化なし
  • 私が考えることができるすべてのg ++​​最適化フラグでコンパイルする

私はこれでできることを使い果たしています。double の代わりに float を使用できるかもしれませんが、それは最後の手段にしたいと思います。そして、どうにかしてこれにSIMDを使用できるかもしれませんが、それをやったことがないので、それは大変な作業だと思います. 何か案は?

ありがとう

4

4 に答える 4

1

fabs (ISO 90 C で標準化されている) を使用することをお勧めします。これは、単一の非分岐命令に減らすことができるはずだからです。

于 2013-02-25T16:11:54.507 に答える
0
Return the square of the distance instead of the square root

正方形を正方形と比較している限り、それは良い考えです。

Inline it

これは逆最適化である場合があります。インライン化されたコードは、分岐しているかどうかに関係なく、実行パイプライン/キャッシュのスペースを占有します。

多くの場合、コンパイラーがインライン化するかどうかの最終決定権を持っているため、違いはありません。

Const what I can

通常、まったく違いはありません。

No standard library bloat

何が膨満しますか?

Compiling with every g++ optimization flag I can think of

それは良いことです。ほとんどの最適化はコンパイラに任せてください。実際のボトルネックを測定し、そのボトルネックが重大であるかどうかを判断した場合にのみ、手元の最適化にお金を投資してください。

あなたができることあなたのコードをブランチフリーにすることです。ビットマスクを使用しない場合、これは次のようになります。

//if (z > zhw) 
//        z -= boxWidths[2];
//else if (z < -zhw)
//      z += boxWidths[2]; 

const auto z_a[] = {
    z,
    z - boxWidths[2]
};
z = z_a[z>zhw];
...

また

z -= (z>zhw) * boxWidths[2];

ただし、これが高速であるという保証はありません。これで、コンパイラがコード内のSIMDスポットを特定するのに苦労する可能性があります。または、分岐ターゲットバッファが適切に機能し、ほとんどの場合、関数を介して同じコードパスがあります。

于 2013-02-25T15:13:05.070 に答える
0

比較は予測が難しいため、それらを取り除く必要があります。

実装する機能は次のとおりです。

     /    /           /\  /\
    /    /           /  \/  \
    ----0-----  or ------------ , as (-x)^2 == x^2
       /    / 
      /    /  

後者は、2 つの ab​​s ステートメントの結果です。

 x = abs(half-abs(diff))+half;

コード

double tst(double a[4], double b[4], double half)
{
   double sum=0.0,t;
   int i;
   for (i=0;i<3;i++) { t=fabs(fabs(b[i]-a[i])-half)-half; sum+=t*t;}
   return sum;
}

元の実装を 4 倍 (+some) 上回っています。この時点では、完全な並列処理さえありません。xmm レジスタの下位半分のみが使用されています。

x && y の並列処理では、理論上約 50% のゲインが得られます。double の代わりに float を使用すると、理論的にはさらに約 3 倍速くなる可能性があります。

于 2013-02-25T15:39:28.187 に答える