11

バックグラウンド:

何年も前に、Visual Studio (VC++) フラグ '/fp:fast' を使用して特定の計算量の多いライブラリでより高速なコードを生成するコードベースを継承しました。残念ながら、'/fp:fast' は、別のコンパイラ (Borland C++) の下で同じライブラリとわずかに異なる結果を生成しました。まったく同じ結果を出す必要があったので、'/fp:precise' に切り替えました。ただし、現在、uBuntu Linux 10.04 で g++ を使用して同じライブラリをコンパイルしていて、同様の動作が見られます。同様の根本原因があるのではないかと考えています。g++ ビルドの数値結果は、VC++ ビルドの数値結果とは少し異なります。これは私の質問に私をもたらします:

質問:

g++ には、VC++ の 'fp:fast' および 'fp:precise' オプションと同等または類似のパラメーターがありますか? (そしてそれらは何ですか? 'fp:precise' に相当するものを有効にしたいのです。)

詳細情報:

g++ を呼び出す「make」を使用してコンパイルします。私が知る限り (make ファイルは少し不可解で、私が書いたものではありません) g++ 呼び出しに追加される唯一のパラメーターは、「通常の」パラメーター (フォルダーとコンパイルするファイルを含める) と -fPIC (このスイッチが何をするのかよくわかりません。'man' ページには表示されません)。

「man g++」の唯一の関連パラメーターは、最適化オプションをオンにするためのもののようです。(例: -funsafe-math-optimizations)。ただし、何かをオンにしているわけではなく、関連する最適化をオフにしたいだけです。

リリース ビルドとデバッグ ビルドを試しましたが、VC++ ではリリースとデバッグで同じ結果が得られ、g++ ではリリースとデバッグで同じ結果が得られますが、g++ バージョンで VC++ バージョンと同じ結果を得ることができません。

4

5 に答える 5

18

GCCマニュアルから:

-float-store 浮動小数点変数をレジスタに格納せず、浮動小数点値がレジスタまたはメモリから取得されるかどうかを変更する可能性のある他のオプションを禁止します。

このオプションは、(68881 の) 浮動レジスターが double の想定よりも高い精度を維持する 68000 などのマシンで、望ましくない過剰な精度を防ぎます。x86 アーキテクチャの場合も同様です。ほとんどのプログラムでは、過剰な精度は有効ですが、少数のプログラムは IEEE 浮動小数点の正確な定義に依存しています。そのようなプログラムには、関連するすべての中間計算を変数に格納するように変更した後、-float-store を使用します。

少し拡大すると、これらの不一致のほとんどは、計算に x86 80 ビット浮動小数点レジスタを使用することに起因します (double値を格納するために使用される 64 ビットに対して)。中間結果がメモリに書き戻さずにレジスタに保持されている場合、計算で 16 ビットの余分な精度が効果的に得られ、より正確になりますが、中間値のメモリへの書き込み/読み取りで生成された結果 (または64 ビット FP レジスタしかないアーキテクチャ)。

これらのフラグ (GCC と MSVC の両方) は、通常、各中間結果を強制的に 64 ビットに切り捨てます。これにより、計算はコード生成と最適化の気まぐれやプラットフォームの違いの影響を受けなくなります。この一貫性には、通常、精度/精度のコストに加えて、わずかなランタイム コストが伴います。

于 2010-07-13T03:53:02.070 に答える
10

過剰なレジスタ精度は FPU レジスタのみの問題であり、コンパイラ (適切な有効化スイッチを使用) はとにかく回避する傾向があります。浮動小数点計算が SSE レジスタで実行される場合、レジスタの精度はメモリの精度と等しくなります。

私の経験では、 /fp:fast への影響 (および潜在的な不一致) のほとんどは、代数変換を自由に実行するコンパイラーに起因します。これは、加数の順序を変更するのと同じくらい簡単です。

( a + b ) + c --> a + ( b + c)

- a*(b+c) のような乗算を自由に分配し、かなり複雑な変換を行うことができます - すべて以前の計算を再利用することを目的としています。もちろん、無限精度では、このような変換は良性ですが、有限精度では実際に結果が変わります。おもちゃの例として、a=b=2^(-23), c = 1 で加数オーダーの例を試してみてください。MS の Eric Fleegalはそれをより詳しく説明しています

この点で、/fp:precise に最も近い gcc スイッチは -fno-unsafe-math-optimizations です。デフォルトでオンになっていると思います-おそらく明示的に設定してみて、違いがあるかどうかを確認してください。同様に、すべての -ffast-math 最適化を明示的にオフにすることもできます: -fno-finite-math-only、-fmath-errno、-ftrapping-math、-frounding-math、および -fsignaling-nans (最後の 2 つのオプションはデフォルト!)

于 2010-07-13T05:00:51.590 に答える
5

正確に同等のものはないと思います。-mfpmath=sseデフォルトの代わりに試し-mfpmath=387てみて、それが役立つかどうかを確認してください。

于 2010-07-13T03:51:21.780 に答える
1

これは間違いなく最適化フラグとは関係ありません。「デバッグ」とは「最適化をオフにする」ことを意味すると仮定します。g++ がリリースとデバッグで同じ結果を出す場合、それは最適化関連の問題ではないことを意味します。デバッグ ビルドは常に各中間結果をメモリに格納する必要があるため、MSVC に対して /fp:precise が行うのと同じ結果が保証されます。

これは、(a) コンパイラの 1 つにコンパイラのバグがあるか、(b) 数学ライブラリのバグである可能性が高いことを意味します。計算の個々の関数を掘り下げて、不一致がどこにあるかを絞り込みます。その時点で回避策が見つかる可能性が高く、バグが見つかった場合は、関連するチームがそれについて知りたいと思っています.

于 2010-07-13T05:55:22.930 に答える
0

-mpc32 または -mpc64?

ただし、違いを確認するには、スイッチを使用してCおよび数学ライブラリを再コンパイルする必要がある場合があります...これは、他の人が提案したオプションにも当てはまる場合があります。

于 2010-07-13T06:50:14.737 に答える