3

フロートをゼロと比較するとひどい失速があるプラットフォームで作業しています。最適化として、次のコードが使用されているのを見てきました。

inline bool GreaterThanZero( float value )
{
   const int value_as_int = *(int*)&value;
   return ( value_as_int > 0 );
}

生成されたアセンブリを見ると、ストールがなくなり、関数のパフォーマンスが向上しています。

これは機能しますか?IEEE トリックの最適化はすべて SIGNMASKS と多くの AND/OR 操作を使用するため、私は混乱しています (たとえば、https: //www.lomont.org/papers/2005/CompareFloat.pdf)。signed int へのキャストは役に立ちますか? 単純なハーネスでのテストでは、問題は検出されませんでした。

どんな洞察でも良いでしょう。

4

1 に答える 1

8

この式は、最小の正の非正規化数 ( と同じ表現を持つ) から最大の有限浮動小数点数 (表現を持つ) と( と同じ表現を持つ) までの正の浮動小数点数であるか*(int*)&value > 0どうかをテストします。このトリックは、すべてではありませんが多数の NaN 表現 (上記の NaN 表現) を正として検出します。テストを真にする NaN のいくつかの値を気にしなくても問題ありません。value0x000000010x7f7fffff+inf0x7f8000000x7f800001

これはすべて、IEEE 754 形式の表現のために機能します。

NaNIEEE 754 操作をエミュレートする目的で文献で見たビット操作関数は、および符号付きゼロの特定の動作を考慮して、おそらく完全なエミュレーションを目指していました。たとえば、バリエーション*(int*)&value >= 0は と同等ではありません。これはvalue >= 0.0f、unsigned int として-0.0f表され、したがってsigned として表される は、後者の条件を true にし、前者の条件を false にするためです。これにより、そのような機能が非常に複雑になる可能性があります。0x80000000-0x80000000

署名されたキャストへのキャストはint役立ちますか?

ええ、そうです。なぜなら、 と の符号ビットはfloat同じint場所にあり、設定を解除すると両方とも正の数を示すからです。しかし、この条件は、符号なし整数としてvalue > 0.0f再解釈することでも実装できます。value


注: のint*アドレスのへの変換valueは厳密なエイリアシング規則に違反しますが、コンパイラがこれらのプログラムに意味を与えることを保証する場合 (おそらくコマンドライン オプションを使用)、これは許容される場合があります。

于 2014-11-26T06:41:45.377 に答える