(インテルとAMDのCPUの)三角関数は不要


インテルとAMDのCPUには,三角関数を数値的に計算するための命令が備えられていますが,その結果は正しくありません。たとえば,CPUの命令FCOSの結果とstd::cosでソフトウェア的に計算した結果を比べると,後者の方が真の値に近くなります。

再現のためのコード(FCOSを使う部分だけインラインアセンブラを使っています。)

Core i5 6600とg++ 4.8.4で試した結果はこんな感じです。

x = 0.98233490762409514385
c1 = fcos(x)     = 0.55508189550073283591
c2 = std::cos(x) = 0.55508189550073294694
c  = mp::cos(x)  = 0.555081895500732891425063460345544265145531916268
abs(c - c1) = 5.5512e-17
abs(c - c2) = 5.551e-17

c1 is better: 0
c2 is better: 25
total: 100000

(その正しさをどうやって確かめるのかという問題はありますが)Boost.Multiprecisionで計算した結果と比較すると,命令`FCOS`より`std::cos`の方が正確なようです(Visual Studioの場合はまた違った結果になるようです)。

Pentiumが割り算を間違うといって大騒ぎになったことがありましたが(Pentium FDIV バグ),数値計算はどうせ近似値だからでしょうか,この問題は,ドキュメントに注意書きが追記されただけで,根本的な解決はされないままのようです。

おまけ:

結論:CUDAのcos,FCOS,gccのstd::cos(double)の順に正確になります。もちろん,gccのcos(long double), gccのcos(__float128), boost/multiprecisionは,さらに正確です。

JavaではMath.cosとStrictMath.cosがどっちもどっちだったり,数値計算は難しいです。

参考:サイン、コサインをインテルの CPU で計算すると少しバグっているらしい

(インテルとAMDのCPUの)三角関数は不要” への2件のコメント

    • 佐久田先生,そういう他人を信用しない方のおかげで,他人を信用できる社会ができていくんですね。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です