私はかなり複雑な関数を持っており、緯度と経度がラジアンと角度である形式(大きさ、緯度、経度)の3空間で2つのベクトルを表すいくつかのdouble値を取ります。この関数の目的は、最初のベクトルを2番目のベクトルの周りで指定された角度だけ回転させ、結果のベクトルを返すことです。コードが論理的に正しく、機能することをすでに確認しました。
この関数の期待される目的はグラフィックスであるため、倍精度は必要ありません。ただし、ターゲットプラットフォームでは、floatを受け取るtrig(およびsqrt)関数(具体的にはsinf、cosf、atan2f、asinf、acosf、sqrtf)は、floatよりもdoubleで高速に動作します(おそらく、このような値を計算するための命令で実際にdouble; floatが渡された場合、値をdoubleにキャストする必要があります。これには、より多くのメモリがある領域(つまりオーバーヘッド)に値をコピーする必要があります。その結果、関数に含まれるすべての変数は倍精度になります。
問題は次のとおりです。1秒間に何度も呼び出すことができるように関数を最適化しようとしています。したがって、sin、cos、sqrtなどの呼び出しを、これらの関数の浮動小数点バージョンの呼び出しに置き換えました。これにより、全体で3〜4倍の速度が向上します。これはほとんどすべての入力で機能します。ただし、入力ベクトルが標準の単位ベクトル(i、j、またはk)とほぼ平行である場合、さまざまな関数の丸めエラーが蓄積され、後でsqrtfまたは逆三角関数(asinf、acosf、 atan2f)これらの関数のドメインのほんの少し外にある引数を渡すため。
したがって、このジレンマが残ります。倍精度関数を呼び出して問題を回避することしかできない(そして、1秒あたり約1,300,000のベクトル演算の制限になってしまう)か、別のことを考え出すことができます。最終的には、逆三角関数への入力をサニタイズしてエッジケースを処理する方法が必要です(sqrtの場合は簡単です。absを使用するだけです)。単一の条件ステートメントでさえ非常に多くのオーバーヘッドを追加するため、パフォーマンスの向上が失われるため、分岐はオプションではありません。
それで、何かアイデアはありますか?
編集:誰かが、doubleと浮動小数点演算の使用について混乱を表明しました。すべての値を実際にdoubleサイズのコンテナー(つまり、double型変数)に格納する場合は、floatサイズのコンテナーに格納する場合よりも、関数の方がはるかに高速です。ただし、明らかな理由により、浮動小数点精度の三角関数の演算は倍精度の三角関数の演算よりも高速です。