4

コンパイラの最適化を妨げている IEEE 浮動小数点規則に問題がありますが、これは明らかなようです。例えば、

char foo(float x) {
    if (x == x) 
       return 1;
    else 
       return 0; 
}

NaN == NaN が false であるため、1 を返すように最適化することはできません。わかりました、大丈夫だと思います。

ただし、オプティマイザが実際に修正できるように記述したいと思います。すべてのフロートに当てはまる数学的同一性はありますか? たとえば、!(x - x) が常に保持されているとコンパイラが想定できるのであれば、喜んで !(x - x) を記述します (ただし、そうではありません)。

このような ID については、たとえばここなどで Web 上にいくつかの参照がありますが、IEEE 754 標準の軽いスキャンを含め、整理された情報は見つかりませんでした。

オプティマイザに isnormal(x) を想定させることができれば、(gcc または clang で) 追加のコードを生成する必要はありません。

明らかに、ソース コードに (x == x) を実際に記述するつもりはありませんが、インライン化用に設計された関数があります。関数は foo(float x, float y) として宣言できますが、多くの場合、x は 0、y は 0、または x と y は両方とも z などです。float は画面上の幾何学的座標を表します。これらはすべて、関数を使用せずに手動でコーディングした場合、0 と (x - x) を決して区別せず、ばかげたものを手動で最適化するだけです。そのため、関数をインライン展開した後にコンパイラが行う IEEE 規則についてはまったく気にしません。基本的に画面上で描画を行っているため、丸めの違いもそれほど重要ではありません。

関数がヘッダー ファイルに表示され、関数を使用する .c ファイルが -ffast-math でコンパイルされるのは適切ではないため、-ffast-math はオプションではないと思います。

4

5 に答える 5

2

このモジュールで使用される浮動小数点数が Inf/NaN でないと想定できる場合は、-ffinite-math-only(GCC で) コンパイルできます。これにより、投稿したような例のコード生成が「改善」される場合があります。

于 2009-12-29T22:24:01.050 に答える
2

Yossarian King による、Game Programming Gems volume 2 の浮動小数点の最適化に関する非常に優れた記事も参考になるかもしれません。ここで記事を読むことができます。実装とアーキテクチャを考慮して、IEEE 形式について非常に詳細に説明し、多くの最適化のトリックを提供します。

于 2009-12-29T06:22:30.600 に答える
2

コンピュータの浮動小数点演算を数学的実数演算のように動作させるのに常に苦労していると思いますが、何らかの理由でそうしないことをお勧めします。2 つの fp 数値の等価性を比較しようとして型エラーを起こしていることをお勧めします。fp 値は圧倒的多数で近似値であるため、これを受け入れて近似値をテストとして使用する必要があります。

数値の等価性テスト用にコンピューター整数が存在します。

まあ、それは私が思うことです、あなたが望むなら、あなたは先に進んでマシン(実際にはすべてのマシン)と戦ってください.

さて、あなたの質問のいくつかの部分に答えるために:

-- 実数演算でよく知られているすべての数学的恒等式について、IEEE であるかどうかに関係なく、浮動小数点数の領域に反例があります。

-- 「巧妙な」プログラミングは、ほとんどの場合、コンパイラが単純なプログラミングよりもコードを最適化することを難しくします。

-- グラフィック プログラミングを行っているようです。最終的には、概念空間内の点の座標が画面上のピクセルにマッピングされます。ピクセルは常に整数の座標を持ちます。概念空間から画面空間への変換により、近似等価関数が定義されます

よろしく

マーク

于 2009-12-29T09:47:46.560 に答える
1

ビットごとの等価性を比較できます。同等であるがビットごとに異なるいくつかの値に噛まれる可能性がありますが、言及したように真の同等性があるすべてのケースをキャッチします。そして、コンパイラがあなたの行動を認識し、インライン化するときにそれを削除するかどうかはわかりませんが(これがあなたが求めているものだと私は信じています)が、それは簡単に確認できます。

于 2010-01-06T23:25:07.497 に答える
0

当たり前の方法で試してプロファイリングしたらどうなりましたか? または生成されたasmを調べましたか?

関数が呼び出しサイトで既知の値でインライン化されている場合、オプティマイザーはこの情報を利用できます。例: foo(0, y).

実行する必要のない作業に驚くかもしれませんが、少なくともプロファイルを作成したり、コンパイラがコードに対して実際に行っていることを調べたりすると、より多くの情報が得られ、次にどこに進むべきかを判断するのに役立ちます。

そうは言っても、オプティマイザーが自分で把握できない特定のことがわかっている場合は、関数の複数のバージョンを記述し、呼び出すバージョンを指定できます。これはちょっと面倒ですが、少なくともインライン関数では、それらはすべて 1 つのヘッダーにまとめて指定されます。また、インライン asm を使用して必要なことを正確に実行する次のステップよりもかなり簡単です。

于 2009-12-29T06:36:28.240 に答える