『数値計算ガイド』のセクション D.11 で説明しているように、標準規格に準拠した IEEE 演算の実装でも結果が異なる場合があります。ほとんどの場合、これらの結果はほぼ等しく適切ですが、同様にほとんどの場合、その証明は冗漫であるか困難になります。ほとんどの目的に対しては、ある程度パフォーマンスを犠牲にして、結果の検証に必要なエラー解析の量を減らすことをお勧めします。出力上のわずかな差異、あるいは大きな差異がどちらも同様に適切になるタイミングと、その相違の原因がユーザープログラムのエラー、コンパイラ最適化エラー、またはハードウェアエラーのどれであるかは明らかではありません。
IEEE 浮動小数点演算の結果が異なる主な根本原因は複数あります。次にこれらの原因を示し、Oracle Developer Studio のリリースおよびサポートされているプラットフォーム間での無意味なバリエーションを減らすいくつかのアプローチについて説明します。それぞれのアプローチは再現性を高めますが、パフォーマンスを低下させる可能性があることに注意してください。場合によっては、パフォーマンスの低下が著しくなります。
指数関数、対数関数、三角関数など、プログラミング言語で標準化された一般的な数学ライブラリ関数のほとんどは、有理数演算や、平方根 (sqrt()) などの代数関数と比べ、正しく丸めるにはコストがかかります。ほぼ正しく丸められる関数は、ほとんどの目的に適しており、非常に高速です。ただし、もっとも高速でほぼ正しく丸められる関数は、プラットフォームによって異なります。
アプリケーションが使用する関数に応じた移植可能なコードを使用してください。このようなコードのソースの 1 つが、自由に配布可能な数学ライブラリである fdlibm です。これは Netlib ソフトウェアリポジトリから入手できます。
–xvector オプションは使用しないでください。超越関数のベクトル化バージョンは、特定のプラットフォームに最適化されており、別のプラットフォームでは生成される結果がわずかに異なります。
x86 ハードウェア超越命令を使用しないでください。これらの命令でエラーバウンドをできるかぎり小さくしたとしても、完全に正しくは丸められません。また、Intel バージョンと AMD バージョンでは、どちらも非常に適切であったとしても、異なる場合があります。Oracle Developer Studio C/C++ コンパイラでは、特に –fast に続けて –xbuiltin=%default を使用して、どの超越命令も、コンパイラによって組み込み超越関数の代わりにインラインが使用されていないことを確認することができます。同様に、–fast に続けて –xnolibmilオプションを使用すると、インラインテンプレートが無効になります。Oracle Developer Studio の libm.il には、超越命令を呼び出す複数のテンプレートが含まれています。
加算および乗算は実数演算で連想型になり、和と積はどの順序でも計算できます。ただし、丸めがある場合は、評価の順序が計算結果に影響します。
–xreduction 並列化オプションを使用しないでください。Oracle Developer Studio は、予測できない方法でリダクションを最適化します。
Fortran の DOT および MATMUL 演算は使用しないでください。Fortran 90 以降のこれらの組み込み関数は、異なるプラットフォームに別々の方法で実装され、その丸め結果も異なります。並列化も有効になっている場合、結果はリダクションの最適化によって予測できない可能性があります。内積と行列乗算の演算は、Netlib ソフトウェアリポジトリの LAPACK ライブラリで使用可能なものなど、移植可能な Fortran でコード化できます。
ほとんどの言語では、外部式の評価の順序を言語によって指定していません。したがって、ranf(x)() が乱数ジェネレータである場合、式 ranf(x) * a + ranf(x) * b() は、2 つの ranf(x)() の呼び出しの評価順序が変更された場合、異なるコンパイラでは、または同じコンパイルの異なる最適化レベルでは別々の結果を算出します。
2 つの外部参照を含む式を使用しないでください。このような式は、それぞれ含まれる外部参照を 1 つ以下にするように複数のステートメントに分割します。このため、
z = ranf(x) * a + ranf(x) * b()
は、次のコマンドに置き換えることができます。
t = ranf(x) * a()
z = t + ranf(x) * b()
C/C++ の long double は、SPARC および x86 の Studio では、それぞれ 113 の有効ビットと 64 の有効ビットで実装されます。このため、明示的に long double 変数を含むプログラムは、SPARC と x86 では動作が異なることになります。
一部の状況では、式は、ソースコードに明示されているより高い精度で評価される場合があります。これは、単精度または倍精度変数を含む式の評価に x87 拡張精度レジスタが使用される場合に発生します。また、融合型積和演算が乗算と加算のペアに置き換えられるときにも起こります。
乗算と加算のペアは、融合型積和演算として最適化しないでください。–fast に続けて –fma=none を使用してください。
–xarch=386 を使用する必要があり、long double 型を明示的に使用していない場合は、すべての変数が float である場合には –fprecision=single を、すべての変数が double である場合には –fprecision=double を使用してコンパイルすることによって、拡張精度式評価の影響を軽減することができます。ただし、Fortran complex*8 変数が –xarch=386 で使用されている場合は、確実にすべての式評価を単精度で行う方法はありません。–m32 より –m64 を使用することをお勧めします。関数の値が、その関数と同じ精度のレジスタで渡されます。