2013-04-03 20 views
5

/fp:precise/fp:fastフラグを使用するコードを調べていました。 /fp:preciseためMSDN documentationによればStrange/fp浮動小数点モデルのフラグの動作

FP /付:正確なx86プロセッサ上で、コンパイラが割り当てとキャストのために適切な精度にfloat型の変数に丸めとにパラメータを渡すときに実行するには関数。この丸めによって、データがそのタイプの容量よりも大きな重要性を保持しないことが保証されます。/fp:preciseでコンパイルされたプログラムは、/ fp:preciseを除いてコンパイルされたプログラムよりも遅くて大きくなる可能性があります。/fp:exactは組み込み関数を無効にします。代わりに標準ランタイムライブラリルーチンが使用されます。詳細については、/ Oi(組み込み関数の生成)を参照してください。

0033185D cvtss2sd xmm0,xmm1 
00331861 call  __libm_sse2_sqrt_precise (0333370h) 
00331866 cvtsd2ss xmm0,xmm0 

this questionから、私は現代のx86/x64プロセッサは、80ビット・レジスタを(使用していないと考えている:(x86/Win32プラットフォームをターゲットに、/arch:SSE2と呼ばれる)sqrtfへの呼び出しの解体を見てみると

または少なくとも彼らの使用を妨げる)ので、コンパイラは、私が次善のものであると想定するものを行い、64ビットの倍精度で計算を行います。また、組み込み関数が無効になっているので、ライブラリsqrtf関数が呼び出されます。

これで十分ですが、これはドキュメントに記載されている内容に準拠しているようです。

私はx64のアーチ用にコンパイルする場合しかし、奇妙な何かが起こる:

000000013F2B199E movups  xmm0,xmm1 
000000013F2B19A1 sqrtps  xmm1,xmm1 
000000013F2B19A4 movups  xmmword ptr [rcx+rax],xmm1 

計算は64ビット倍精度で実行されていない、と組み込み関数が使用されています。私が知る限り、結果は/fp:fastフラグが使用された場合とまったく同じです。

なぜ2つの間に相違がありますか? /fp:preciseはx64プラットフォームでは動作しませんか?

ここで、健全性チェックとして、/fp:precise/arch:SSE2というVS2010 x86で同じコードをテストしました。驚くべきことに、sqrtpdの組み込み関数が使用されていました!

00AF14C7 cvtps2pd xmm0,xmm0 
00AF14CA sqrtsd  xmm0,xmm0 
00AF14CE cvtpd2ps xmm0,xmm0 

ここでは何が起こっていますか? VS2010がシステムライブラリを呼び出す間、VS2010は組み込み関数を使用するのはなぜですか?

x64プラットフォームをターゲットとしたVS2010のテストでは、VS2012(/fp:preciseは無視されているようです)と同様の結果が得られます。

古いバージョンのVSにはアクセスできないため、これらのプラットフォームでのテストはできません。

参考までに、私はインテルi5-m430プロセッサー搭載のWindows 7 64ビットでテストを行っています。

+2

これは本当に奇妙です。私は '/ fp:precise'がコンパイラに中間体をより高い精度で裁量的に宣伝させることがあるという事実を知っています。しかし、それはここでのまったく矛盾を説明していません。 – Mysticial

+0

"この質問から、私はx86アーチに80ビットレジスタがないと信じています。 –

+0

奇妙な言葉遣い。その使用に対する一般的な推奨を明確にするために更新されました。 – helloworld922

答えて

3

最初に、this中間浮動小数点精度についての本当の良いブログ記事を読んでください。この記事では、ビジュアルスタジオで生成されたコードのみを処理しています(しかし、あなたの質問がすべてです)。そして今の例に:

0033185D cvtss2sd xmm0,xmm1 
00331861 call  __libm_sse2_sqrt_precise (0333370h) 
00331866 cvtsd2ss xmm0,xmm0 

このアセンブラコードは、x86プラットフォーム用/fp:precise /arch:SSE2で生成されています。 documentationによれば、正確な浮動小数点モデルは、すべての計算をx86プラットフォームの内部でと倍増するように促進します。また、組み込み関数の使用を防ぎます(私はすでにthis informationと読んでいると思います)。したがって、コードはfloatからdoubleへの変換から始まり、倍精度sqrt呼び出しから始まり、最後に結果はfloatに変換されます。

000000013F2B199E movups  xmm0,xmm1 
000000013F2B19A1 sqrtps  xmm1,xmm1 
000000013F2B19A4 movups  xmmword ptr [rcx+rax],xmm1 

第二の例は、x64(AMD64)プラットフォーム用にコンパイルされており、このプラットフォームは完全に異なる動作します!ドキュメントに従って:

パフォーマンス上の理由から、中間演算は、使用可能な最も広い精度ではなく、どちらかのオペランドの最も広い精度で計算されます。

したがって、計算は単精度で内部的に行われます。可能であれば、イントリンシックを使用することにしましたので、/fp:precise/fp:fastの違いは、x64プラットフォームののほうが少し小さいです。新しい動作により、より速いコードが得られます。これは、正確に何が起こったのかをプログラマーにより多くの制御を与えます(互換性の問題は新しいx64プラットフォームには関係しないため、ゲームのルールを変更することができました)。残念なことに、これらの変更点/相違点は、ドキュメントに明示的に記載されていません。

00AF14C7 cvtps2pd xmm0,xmm0 
00AF14CA sqrtsd  xmm0,xmm0 
00AF14CE cvtpd2ps xmm0,xmm0 

最後に、最後の例は、Visual Studio 2010のコンパイラでコンパイルし、私は彼らが誤って、彼らがより良い(少なくとも/fp:preciseモードのために)必要はありませんsqrtのために固有の使用だと思うが、彼らは変更することが決定しました/ Visual Studio 2012でこの現象を修正してください(here参照)。

関連する問題