他の質問に関連して、SOR(Successive Over-Relaxation)法を使用するようにスパース行列ソルバーを変更しました。コードは次のようになります。
void SORSolver::step() {
float const omega = 1.0f;
float const
*b = &d_b(1, 1),
*w = &d_w(1, 1), *e = &d_e(1, 1), *s = &d_s(1, 1), *n = &d_n(1, 1),
*xw = &d_x(0, 1), *xe = &d_x(2, 1), *xs = &d_x(1, 0), *xn = &d_x(1, 2);
float *xc = &d_x(1, 1);
for (size_t y = 1; y < d_ny - 1; ++y) {
for (size_t x = 1; x < d_nx - 1; ++x) {
float diff = *b
- *xc
- *e * *xe
- *s * *xs - *n * *xn
- *w * *xw;
*xc += omega * diff;
++b;
++w; ++e; ++s; ++n;
++xw; ++xe; ++xs; ++xn;
++xc;
}
b += 2;
w += 2; e += 2; s += 2; n += 2;
xw += 2; xe += 2; xs += 2; xn += 2;
xc += 2;
}
}
奇妙なことにomega
、(緩和係数を)増やすと、実行速度はさまざまな配列内の値に劇的に依存し始めます。
の場合omega = 1.0f
、実行時間はほぼ一定です。初めてomega = 1.8
、これを10回実行するのに通常5ミリ秒かかりますがstep()
、シミュレーション中に徐々に100ミリ秒近くまで増加します。を設定omega = 1.0001f
すると、それに応じて実行時間がわずかに増加します。値が高いomega
ほど、シミュレーション中の実行時間が速くなります。
これらはすべて流体ソルバー内に埋め込まれているため、スタンドアロンの例を思い付くのは困難です。しかし、私は初期状態を保存し、タイムステップごとにその状態でソルバーを再実行し、実際のタイムステップを解きました。初期状態では高速でしたが、後続のタイムステップでは徐々に遅くなりました。他のすべてが等しいので、それはこのコードの実行速度がそれらの6つの配列の値に依存していることを証明します。
これは、g ++を使用するUbuntuで再現可能であり、VS2008で32ビット用にコンパイルする場合は64ビットのWindows7でも再現可能です。
NaNとInfの値は浮動小数点の計算では遅くなる可能性があると聞きましたが、NaNまたはInfsは存在しません。フロート計算の速度が入力数値の値に依存する可能性はありますか?