インテル® C++ コンパイラー 17.0 デベロッパー・ガイドおよびリファレンス

浮動小数点アプリケーションのプログラミング・トレードオフ

一般に、浮動小数点アプリケーションのプログラミングの目標は、次のカテゴリーに分けられます。

アプリケーションの目標に基づいて、これらの要素のトレードオフを行う必要があります。例えば、3D グラフィック・エンジンを開発していれば、パフォーマンスが最も重要な考慮事項であり、再現性と精度は、2 番目になるかもしれません。

インテル® C++ コンパイラーは、特定の目標に合わせてアプリケーションをチューニングできるコンパイラー・オプションを提供します。 オプションには、-fp-model (Linux* および OS X*) または /fp (Windows®) のように浮動小数点固有のものや、[Q]imf-max-error のように高速ですが精度の低いものがあります。 コンパイラーは、指定されたコンパイラー・オプションによって、異なる最適化をコードに適用します。プログラミング目標を調整し、適切なコンパイラー・オプションを選択して、各要素間のトレードオフを行ってください。一部のオプションは、呼び出される数学ルーチンの種類に影響します。

libirclibm、および svml ライブラリーの多くのルーチンは、互換マイクロプロセッサーよりもインテル製マイクロプロセッサーでより高度に最適化されます。

浮動小数点オプションの使用

次にコード例を示します。

float t0, t1, t2;
 ...
t0=t1+t2+4.0f+0.1f;

精度を優先して、-fp-model extended オプション (Linux* および OS X*) または /fp:extended オプション (Windows®) を指定すると、コンパイラーは次のアセンブリー・コードを生成します。

fld       DWORD PTR _t1 
fadd      DWORD PTR _t2 
fadd      DWORD PTR _Cnst4.0 
fadd      DWORD PTR _Cnst0.1 
fstp      DWORD PTR _t0

上記のコードは、ターゲット・プラットフォームで可能な最高の仮数の精度を利用するため、最大限の精度をもたらします。しかし、x87 スタックの管理による負荷のため、パフォーマンスが低下する可能性があります。また、同等の拡張精度型を持たない他のプラットフォームで再現できない結果を招くかもしれません。

再現性と移植性を優先して、-fp-model source オプション (Linux* および OS X*) または /fp:source オプション (Windows®) を指定すると、コンパイラーは次のアセンブリー・コードを生成します。

movss     xmm0, DWORD PTR _t1 
addss     xmm0, DWORD PTR _t2 
addss     xmm0, DWORD PTR _Cnst4.0 
addss     xmm0, DWORD PTR _Cnst0.1 
movss     DWORD PTR _t0, xmm0

上記のコードは、元の順序の計算を維持し、明確な IEEE の単精度型をすべての計算に使用することにより、最大限の移植性をもたらします。ただし、中間式の丸め誤差が拡張精度に比べて多いため、最初の例ほどの精度はありません。また、1.4.0f + 0.1f の事前計算を活用しないため、パフォーマンスも最大ではありません。

パフォーマンスを優先して、-fp-model fast オプション (Linux* および OS X*) または /fp:fast オプション (Windows®) を指定すると、コンパイラーは次のアセンブリー・コードを生成します。

movss     xmm0, DWORD PTR _Cnst4.1 
addss     xmm0, DWORD PTR _t1 
addss     xmm0, DWORD PTR _t2 
movss     DWORD PTR _t0, xmm0

上記のコードは、インテル® SSE 命令を使用し、4.0f + 0.1f を事前計算することにより、最大限のパフォーマンスをもたらします。 ただし、中間式の丸め誤差が多いため、最初の例ほどの精度はありません。また、4.0f + 0.1f を事前計算するために加算の順序を変更するため、2 つ目の例のように再現性のある結果をもたらしません。すべてのコンパイラー、すべてのプラットフォーム、すべての最適化レベルで同じように加算の再配置が行われるとは限りません。

多くのアプリケーションでは、このような考慮事項がより複雑になるでしょう。

高速であるが精度の低いオプションの使用

高速ですが精度の低いオプションは、数学関数の精度を制御し、インテルの数学ライブラリーによるパフォーマンス/精度のトレードオフを簡単に利用できるようにします。コマンドライン・インターフェイスで、すべての数学関数または選択した数学関数セットの精度を、high、medium、low よりも細かいレベルで指定できます。

コンパイラーが数学ライブラリーから適切な関数実装を選択するのに使用する関数属性のセットを指定することで、精度を制御します。属性 max-error を使用する例を以下に示します。 例えば、次のオプションを使用します。

-fimf-max-error=2
これは、すべての single、double、long double、および quad の関数の相対誤差を 2 ulps (unit in the last place: 最後の桁の単位) に指定します。

sin 関数の精度を 12 ビットにする場合は、次のように指定します。

-fimf-sin-accuracy-bits=12

sin 関数の相対誤差を 10 ulps、コンパイルするソースファイルで呼び出される他の数学関数の相対誤差を 4 ulps にする場合は、次のように指定します。

-fimf-sin-max-error=10 -fimf-max-error=4

インテル® C++ コンパイラーは max-error 属性のデフォルト値を、/fp オプションと /Qfast-transcendentals 設定によって定義します。 /fp:fast モード、または高速で少し精度が低い数学関数が /Qfast-transcendentals- で明示的に有効になると、インテル® C++ コンパイラーは呼び出しに対して max-error=4.0 を設定します。 それ以外の場合は、max-error=0.6 を設定します。

関連情報