4

次のようなコードがあります。

inline int calc_something(double x) {
  if (x > 0.0) {
    // do something
    return 1;
  } else {
    // do something else
    return 0;
  }
}

残念ながら、 flag を使用すると、/fp:fast明らかcalc_something(0)==1に間違ったコード パスを使用していることになります。これは、コード内の複数のポイントで異なるパラメーターを使用してメソッドを使用する場合にのみ発生するため、コンパイラ (Microsoft Visual Studio 2008、SP1) からの怪しい最適化が行われていると思います。

また、インターフェースを次のように変更すると、上記の問題はなくなります。

inline int calc_something(const double& x) {

しかし、なぜこれが奇妙な動作を修正するのかわかりません。誰でもこの動作を説明できますか? 何が起こっているのか理解できない場合は、/fp:fastスイッチを削除する必要がありますが、これによりアプリケーションがかなり遅くなります。

4

5 に答える 5

6

私は確実にコメントできるほどFPUに精通していませんが、コンパイラーが等しいと考える既存の値をxその比較に参加させているのではないかと思います。おそらく、既に FP スタック上にあるので、コンパイラをy = x + 20.; y = y - 20; yロードするのではなく、と比較するだけです。しかし、丸め誤差のため、本来あるべきものとはまったく異なり、奇妙な結果が得られます。xyy0.0

より良い説明:なぜ cos(x) != cos(y) なのに x == y? C++FAQ lite から。これは私が理解しようとしているものの一部ですが、今までどこで読んだのか正確に思い出せませんでした。

const 参照に変更すると、コンパイラがエイリアシングを心配するため、これが修正されます。xを作成した後のある時点でその値が変更されていないと仮定できないため、からのロードを強制します。実際にはy、[私が精通しているすべての浮動小数点形式で表現可能です] 丸め誤差は消えます。x0.0

MS は、関数ごとに FP フラグを設定できるプラグマを提供していると確信しています。または、このルーチンを別のファイルに移動して、そのファイルにカスタム フラグを設定することもできます。いずれにせよ、その 1 つのルーチンを満足させるためだけに、プログラム全体が苦しむのを防ぐことができます。

于 2010-06-15T08:00:39.567 に答える
3

他の質問で言ったように、コンパイラは浮動小数点コードを生成するのが苦手です。Dennis がリンクしている記事では、問題がよく説明されています。もう 1 つ: MSDN の記事

コードのパフォーマンスが重要な場合は、独自のアセンブラー コードを作成することで、コンパイラーより簡単にパフォーマンスを向上させることができます。アルゴリズムがベクトル化可能な場合は、SIMD も利用できます (ただし、精度はわずかに低下します)。

  1. FPUの仕組みを理解していると仮定します。
于 2010-06-15T08:30:18.360 に答える
2

inline int calc_something(double x)(おそらく) 80 ビットのレジスタを使用します。inline int calc_something(const double& x)double をメモリに格納します。メモリには 64 ビットが必要です。それは少なくとも2つの違いを説明しています。

ただし、そもそもあなたのテストはかなり怪しいと思います。の結果はcalc_something、入力の丸めに非常に敏感です。FP アルゴリズムは、丸めに対して堅牢である必要があります。calc_something(1.0-(1.0/3.0)*3)と同じである必要がありますcalc_something(0.0)

于 2010-06-15T08:53:11.433 に答える
2

calc_something(0L)、またはの結果は何calc_something(0.0f)ですか? キャストする前に、型のサイズにリンクできます。整数は 4 バイト、倍精度は 8 バイトです。

前述の変換がどのように行われるかを確認するために、アセンブルされたコードを調べてみましたか?

「fp fast」をグーグル検索すると、この投稿[social.msdn.microsoft.com]が見つかりました。

于 2010-06-15T07:35:44.563 に答える
1

その行為は正しいと思います。

保持型の精度よりも小さい浮動小数点数を比較することはありません。

ゼロから生じる何かは、別のゼロと等しいか、大きいか、または小さい場合があります。

http://floating-point-gui.de/を参照

于 2010-06-15T06:21:41.240 に答える