1

C++ で 2D 配列の複素数を計算しようとしています。コードの実行が非常に遅く、主な原因を exp 関数に絞り込みました (ネストされたループが 4 つあるにもかかわらず、その行をコメントアウトすると、プログラムはすぐに実行されます)。

int main() {

    typedef vector< complex<double> > complexVect;
    typedef vector<double> doubleVect;

    const int SIZE = 256;
    vector<doubleVect> phi_w(SIZE, doubleVect(SIZE));
    vector<complexVect> phi_k(SIZE, complexVect(SIZE));
    complex<double> i (0, 1), cmplx (0, 0);
    complex<double> temp;
    int x, y, t, k, w;
    double dk = 2.0*M_PI / (SIZE-1);
    double dt = M_PI / (SIZE-1);
    int xPos, yPos;
    double arg, arg2, arg4;
    complex<double> arg3;
    double angle;
    vector<complexVect> newImg(SIZE, complexVect(SIZE));

    for (x = 0; x < SIZE; ++x) {
        xPos = -127 + x;
        for (y = 0; y < SIZE; ++y) {
            yPos = -127 + y;
            for (t = 0; t < SIZE; ++t) {
                temp = cmplx;
                angle = dt * t;
                arg = xPos * cos(angle) + yPos * sin(angle);
                for (k = 0; k < SIZE; ++k) {
                    arg2 = -M_PI + dk*k;
                    arg3 = exp(-i * arg * arg2);
                    arg4 = abs(arg) * M_PI / (abs(arg) + M_PI);
                    temp = temp + arg4 * arg3 * phi_k[k][t];
                }
            }
            newImg[y][x] = temp;
        }
    }
}

計算時間を改善する方法はありますか? 次のヘルパー関数を使用してみましたが、あまり役に立ちません。

complex<double> complexexp(double arg) {
    complex<double> temp (sin(arg), cos(arg));
    return temp;
}

コードをコンパイルするためにclang ++を使用しています

編集:問題は、複素数を計算しようとしているという事実だと思います。オイラーの公式を使用して実数部と虚数部を別々の配列で計算し、複雑なクラスを処理する必要がない場合は、より高速になりますか?

4

4 に答える 4

1

多分これはあなたのために働くでしょう:

http://martin.ankerl.com/2007/02/11/optimized-exponential-functions-for-Java/

于 2013-04-15T06:01:31.470 に答える
0

callgrind で調べてみました。私が見つけることができた唯一のわずかな改善 (サイズ = 50 で ~1.3%) は、変更することでした:

temp = temp + arg4 * arg3 * phi_k[k][t];

temp += arg4 * arg3 * phi_k[k][t];
于 2013-04-15T16:43:32.233 に答える
0

最もコストのかかる関数呼び出しは、sin()/cos() でした。複素数引数を指定して exp() を呼び出すと、これらの関数がバックグラウンドで呼び出されると思われます。

精度を維持するために、関数の計算は非常に遅くなり、それを回避する方法はないようです。ただし、精度と精度を交換することもできます。これは、ゲーム開発者が行うことのようです。sin と cos は遅いです。代替手段はありますか?

于 2013-04-27T16:36:14.610 に答える
-1

数値を定数として定義し、関数eを使用できますstd::pow()

于 2013-04-15T06:01:48.037 に答える