インテル® Xeon® プロセッサーとインテル® Xeon Phi™ コプロセッサーの浮動小数点演算の違い
この記事は、インテル® デベロッパー・ゾーンに掲載されている「Differences in Floating-Point Arithmetic Between Intel® Xeon® Processors and the Intel® Xeon Phi™ Coprocessor」の日本語参考訳です。
インテル® コンパイラーとインテル® Xeon® プロセッサー向けアプリケーションで使用される浮動小数点モデルについての詳細は、「インテル® コンパイラーの浮動小数点演算における結果の一貫性」を参照してください。適切な設定を選択すると、コンパイラーはバイナリー浮動小数点演算について ANSI 言語規格と IEEE-754 規格に完全に準拠したコードを生成します。コンパイラー・オプションにより、パフォーマンス、精度、結果の再現性、これらの規格への厳密な準拠など、最適化のトレードオフを制御することができます。
同じ浮動小数点モデルはインテル® Xeon Phi™ コプロセッサーにも適用されますが、インテル® Xeon® プロセッサーとのアーキテクチャーの違いにより、結果が多少異なります。この記事では、その違いについて説明します。
基本情報
インテル® Xeon Phi™ コプロセッサーは、インテル® Xeon® プロセッサーと同じ浮動小数点データ型をサポートしています。単精度 (32 ビット) および倍精度 (64 ビット) はハードウェアで、4 倍精度 (128 ビット) はソフトウェアで、拡張倍精度 (80 ビット) は x87 命令セットでそれぞれサポートされています。デノーマル数と漸次アンダーフローはサポートされていますが、-O0 を除くすべての最適化レベルでは突発アンダーフローがデフォルトです。同じセットの丸めモードはインテル® Xeon® プロセッサーと同様にサポートされます。
浮動小数点例外
最も大きな違いは浮動小数点例外の処理です。インテル® Xeon Phi™ コプロセッサーのベクトル浮動小数点ユニットはフラグをセットしますが、浮動小数点例外のトラップはサポートしません。VXCSR レジスターの対応するビットは保護されています。このビットを変更しようとするとセグメンテーション・フォルトが発生します。インテル® Xeon® プロセッサーの浮動小数点例外をマスク解除する -fp-trap (C/C++) や -fpe0 (Fortran) などのコンパイラー・オプションは、インテル® メニー・インテグレーテッド・コア・アーキテクチャー (インテル® MIC アーキテクチャー) ではサポートされていません。
-fp-model except または -fp-model strict オプションは、浮動小数点例外の規格に厳密に準拠したセマンティクスを要求します。これには、インテル® Initial Many Core Instructions (インテル® IMCI) を利用するコードの代わりに浮動小数点演算用の x87 コードを生成します。これらのコードはベクトル化できないため、パフォーマンスに大きく影響する可能性があります。しかし、これらのオプションはアプリケーションのデバッグには役立ちます。同様の理由により、-ansi および -fmath-errno オプションを指定すると、インテル® IMCI ではなく x87 を使用して実装された数学関数が呼び出されます。
Fortran コンパイラー 13.0 の IEEE_FEATURES、IEEE_ARITHMETIC および IEEE_EXCEPTIONS モジュールは、インテル® Xeon Phi™ コプロセッサー用にまだ更新されていません。
-fp-model オプション
-fp-model オプションの設定はインテル® Xeon® プロセッサーと同様にサポートされます。どちらもデフォルト設定は -fp-model fast=1 です。インテル® MIC アーキテクチャーの広いベクトル幅と、リダクション・ループおよび超越関数、平方根、除算を含むループのベクトル化によるパフォーマンス向上のため、パフォーマンスへの影響はインテル® Xeon Phi™ コプロセッサーでは多少大きくなる可能性がありますが、-fp-model precise オプションの動作は同じです。上記の理由により、-fp-model except および -fp-model strict のパフォーマンスへの影響は大きくなるでしょう。
-fp-model fast=2 に設定すると、-fimf-domain-exclusion オプションがセットされ、インテル® Xeon Phi™ コプロセッサー向けの、インライン展開された高速な数学関数が有効になります。詳細は、この後の「数学関数の精度」セクションを参照してください。
-fp-model precise オプションは、デノーマル数を用いる演算を有効にして、突発アンダーフローを無効にします。突発 [漸次] アンダーフローは -[no-]ftz を指定して明示的に有効にできます (必須ではありません)。この動作はインテル® Xeon® プロセッサーと同じです。
積和演算
インテル® Xeon® プロセッサー (第 3 世代までのインテル® Core™ プロセッサーを含む) は積和演算 (FMA) 命令をサポートしていません。インテル® Xeon Phi™ コプロセッサーの FMA 命令は最終結果で 1 つの丸めを実行するため、加算命令と乗算命令を個別に実行した場合の結果とわずかに異なります。
原則として、-fp-model strict オプションは積和演算 (FMA) 命令を無効にします。しかし、上記で説明したように、-fp-model strict ではインテル® IMCI の代わりに従来の x87 浮動小数点命令が使用されるため、この動作には意味がありません。FMA 演算はデフォルトで有効ですが、-no-fma オプションで無効にできます。FMA 演算は、-fp-model precise では無効になりません。
数学関数の精度
インテル® Composer XE 2013 に含まれる、インテル® Xeon Phi™ コプロセッサー向けインテル® コンパイラーは、スカラーコードとベクトルコードの両方で中精度 (< 4 ulp) の超越関数をデフォルトで呼び出します (ほとんどの場合、libsvml)。インテル® Xeon® プロセッサーでは、デフォルトでスカラーコードでは libm (< 0.55 ulp)、ベクトルコードでは中精度の libsvml (< 4 ulp) を呼び出します。インテル® Xeon Phi™ コプロセッサーでは、除算はデフォルトで逆数命令を用いる中精度のインラインコードを呼び出します。コンパイラー 13.0 初期リリースでは、平方根はデフォルトで中精度の SVML 関数を呼び出します (次回のアップデートでインラインコードに変更される予定です)。平方根のインラインバージョンは、-fimf-domain-exclusion=15:sqrt (倍精度) または -fimf-domain-exclusion=15:sqrtf (単精度) で取得します。
除外されるドメインの詳細は、コンパイラーのドキュメントを参照してください。-fimf-domain-exclusion オプションは、ほかの数学関数のインラインバージョンを取得する場合にも利用します。除算、平方根、超越関数の高精度で (通常は 0.6 ulp) ベクトル化可能な SVML バージョンは、-fimf-precision=high で取得します。
-fp-model precise では、libm (超越) および libsvml (平方根) への高精度 (< 0.55 ulp) のスカラー呼び出しが使用されます。除算には x87 除算命令が使用されます。-no-fast-transcendentals、-prec-sqrt、-prec-div オプションの効果もそれぞれ同じです。次回のアップデートで、これらのオプションおよび -fp-model precise の除算と平方根の x87 命令は、インテル® IMCI を用いるベクトル化可能なインラインのコードシーケンスに変更される予定です。-fp-model strict では x87 命令が引き続き生成されます。
中精度のベクトル化可能な数学関数は、-fp-model precise と組み合わせて (-fp-model precise -fast-transcendentals -no-prec-sqrt -no-prec-div と指定して) 取得できます。高精度のベクトル化可能バージョンは、-fimf-precision=high を追加することで取得できます。
インテル® Xeon Phi™ コプロセッサーとインテル® Xeon® プロセッサーの浮動小数点演算結果の比較
ハードウェア命令が同じ規格に準拠していても、インテル® Xeon Phi™ コプロセッサーの浮動小数点演算は、インテル® Xeon® プロセッサーの等価な演算とビット単位で同じ結果にならないことがあります。これは、コンパイラーの最適化や数学関数の実装が異なっていることが原因でしょう。インテル® Xeon Phi™ コプロセッサーで利用可能な積和演算 (FMA) 命令もその 1 つです。次のガイドラインに従うことで、異なるプラットフォームで得られる結果の違いを最小限に抑えることができます (パフォーマンスはやや低くなります)。
-fp-model precise -fp-model source を指定して両方のプラットフォームのアプリケーションをビルドします。
FMA 命令を無効にするため、-no-fma を指定してインテル® Xeon Phi™ コプロセッサーのアプリケーションをビルドします。[Fortran アプリケーションの場合は、-assume protect_parens コマンドライン・オプションと括弧を組み合わせて個々の表記で FMA 命令を禁止することもできます (例えば、X = (A + (B*C))]。C/C++ アプリケーションの場合は、#pragma fp_contract (off | on) を挿入して個々の関数で FMA の生成を無効にできます。
両方のプラットフォームで (例えば、-fimf-precision=high を指定して) 高精度の数学関数を選択します。
並列にリダクションを実行する OpenMP* アプリケーションの場合は、環境変数 KMP_DETERMINISTIC_REDUCTIONS=yes を設定し、静的スケジューリングと OMP_NUM_THREADS を使用して各プラットフォームで同じ数のスレッドを設定します。
インテル® スレッディング・ビルディング・ブロック (インテル® TBB) を利用する C++ アプリケーションの場合は、parallel_deterministic_reduction() 関数を利用することで、スレッド数が異なる場合でも、両方のプラットフォームでより一貫した結果を取得できます。
これらのガイドラインは、異なるプラットフォーム間の浮動小数点演算における結果の再現性を高め、違いを最小限に抑えることを意図しています。違いは、結果における実際の数値の不確実性を表すものではありません。より大きく表れることもあります。
Intel、インテル、Intel ロゴ、Intel Core、Intel Xeon Phi、Xeon は、アメリカ合衆国および / またはその他の国における Intel Corporation の商標です。
* その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。
© 2013 Intel Corporation. 無断での引用、転載を禁じます。
パフォーマンスに関する注意事項
* パフォーマンスおよびベンチマークの結果に関する詳細は、www.intel.com/benchmarks (英語) を参照してください。
コンパイラーの最適化に関する詳細は、最適化に関する注意事項を参照してください。