12

Linux x86 32 ビット用に開発されたアプリケーションがあります。多くの浮動小数点演算と、結果に応じた多くのテストがあります。現在、x86_64 に移植していますが、このアーキテクチャではテスト結果が異なります。アーキテクチャごとに個別の結果セットを保持したくありません。

記事An Introduction to GCC - for the GNU compilers gcc and g++によると、問題は X86_64 の GCC がfpmath=sseを想定しているのに対し、x86 はfpmath=387を想定していることです。387 FPU はすべての演算に80 ビットの内部精度を使用し、結果を特定の浮動小数点型 (float、double、または long double) にのみ変換しますが、SSE はオペランドの型を使用して内部精度を決定します。

独自のコードをコンパイルするときに-mfpmath=387 を強制でき、すべての操作が正しく機能しますが、ライブラリ関数 (sin、cos、atan2 など) を呼び出すたびに、結果が再び間違っています。libmが fpmath オーバーライドなしでコンパイルされたためだと思います。

387 エミュレーションを使用して自分で libm (glibc) をビルドしようとしましたが、あちこちで多くのクラッシュが発生しました (何か間違ったことをしたかどうかはわかりません)。

プロセス内のすべてのコードが x86_64 で 387 エミュレーションを使用するように強制する方法はありますか? それとも、両方のアーキテクチャで libm と同じ値を返すライブラリがあるのでしょうか? 助言がありますか?

「80ビット精度は必要ですか?」という質問については、個人の運用としては問題ないと言わざるを得ません。この単純なケースでは、違いは非常に小さく、違いはありません。ただし、多くの操作を組み合わせると、エラーが伝播し、最終結果の違いはそれほど小さくなくなり、違いが生じます。だから私は80ビットの精度が必要だと思います。

4

4 に答える 4

18

テストを修正する必要があると思います。浮動小数点演算が正確であると仮定すると、通常はがっかりすることになります。完全に等しいかどうかをテストする代わりに、期待される結果に十分近いかどうかをテストします。結局のところ、あなたが見つけたものはバグではないので、テストでエラーが報告された場合、そのテストは間違っています。;)

お気づきのように、依存するすべてのライブラリは SSE 浮動小数点を前提としているため、FP モードを x87 に設定できるようにするためだけに、すべてを手動でコンパイルする予定がない限り、対処したほうがよいでしょう。 FP 計算は 100% 正確ではなく、一般に 2 つの異なるプラットフォームで同じ結果が得られるわけではないことを受け入れるだけです。(AMD CPU は、x87 演算でもわずかに異なる結果をもたらすと思います)。

絶対に80 ビットの精度が必要ですか? (そうであれば、 80 ビット FP を使用するようにすべてを自分でコンパイルする以外に、明らかに多くの選択肢はありません。)

それ以外の場合は、テストを調整して、いくつかの小さなイプシロン内で比較と等値テストを実行します。差がそのイプシロンより小さい場合、値は等しいと見なされます。

于 2008-11-27T02:42:38.397 に答える
5

80 ビット精度は実際には危険です。問題は、変数が CPU レジスタに格納されている限り、実際には保持されることです。RAM に強制的に出力されるたびに、型の精度に合わせて切り捨てられます。したがって、コード内で何も起こらなかったとしても、変数の値を実際に変更することができます。

于 2009-01-27T22:39:58.643 に答える
3

精度が必要な場合は、余分な魔法の精度を期待したり、持ったりするのではなく、すべての浮動小数点変数にlong double使用してください。これは本当に簡単です。long doublefloatdouble

于 2011-06-28T20:14:38.783 に答える
2

SSE 浮動小数点と 387 浮動小数点はまったく異なる命令を使用するため、SSE fp 命令で 387 を使用するように説得する方法はありません。おそらく、これに対処する最善の方法は、テスト スイートをあきらめて、わずかに異なる結果を得ることです。結果は最後のビットまで同じです。

于 2008-11-27T21:37:57.500 に答える