ソフトウェアでエミュレートされたIEEEfloat/ doubleは、多くのエッジケースをチェックして適切に処理する必要があるため、低速です。
- 入力の+/-無限大
- 入力の非A番号
- 入力で+/-0
- 入力の正規化数と非正規化数、および仮数の暗黙の「1」
- 開梱と梱包
- 正規化/非正規化
- アンダーチェックとオーバーフローチェック
- 正しい丸め。余分な(非)正規化および/またはアンダーフロー/オーバーフローにつながる可能性があります
上記を基本的なマイクロ操作の数(リストの各項目に1つ)として大まかに数えると、10に近くなります。最悪の場合はさらに多くなります。
したがって、IEEEコンパイラの浮動小数点演算に関心がある場合は、エミュレートされたすべての演算が、対応する整数の演算よりも30倍遅いことを期待してください(CodesInChaosのコメントは、加算/乗算ごとに38クロックでタイムリーです)。
次の浮動小数点形式を選択することで、いくつかのコーナーをカットできます。
- たった1つのゼロ
- Not-A-Numberはありません
- 正規化された数値のみ
- 仮数に暗黙の「1」はありません
- 指数と仮数はそれぞれ整数バイトを占めます
- 丸めなしまたは原始的な丸め
- おそらく、無限大はありません
- おそらく、2の補数仮数
- おそらく、指数バイアスはありません
固定小数点演算は、はるかにパフォーマンスが高くなる可能性があります。ただし、通常の問題は、オーバーフローを回避するために適切な形式を選択できるように、入力のすべての範囲と中間結果を事前に知っておく必要があることです。また、16.16、32.32、8.24、0.32など、サポートされているさまざまな固定小数点形式も必要になる可能性があります。C ++テンプレートは、ここでのコードの重複を減らすのに役立つ場合があります。
いずれにせよ、あなたができる最善のことは、問題を定義し、浮動小数点演算と固定小数点演算の両方で問題を解決し、2つのうちどちらがどのCPUに最適かを観察し、勝者を選択することです。
編集:より単純な浮動小数点形式の例については、MIL-STD-1750Aの32ビット浮動小数点形式を見てください:
MSB LSB MSB LSB
------------------------------------------------------------------
| S| Mantissa | Exponent |
------------------------------------------------------------------
0 1 23 24 31
浮動小数点数は、指数の累乗で累乗された仮数の2倍で表されます。すべての浮動小数点数は、浮動小数点演算の開始時に正規化または浮動小数点ゼロと見なされ、すべての浮動小数点演算の結果は正規化されます(正規化された浮動小数点数には、仮数の符号と反対の値の次のビットがあります)。浮動小数点ゼロ。浮動小数点ゼロは、0000 0000 16、つまり、仮数がゼロで指数がゼロ(00 16)として定義されます。拡張浮動小数点ゼロは、0000 0000 0000 16として定義されます。つまり、仮数がゼロで指数がゼロです。32ビット浮動小数点数のマシン表現の例:
10進数の16進表記
(仮数x Exp)
0.9999998 x 2127 7FFFFF 7F
0.5 x 2 127 400000 7F
0.625 x 2 4 500000 04
0.5 x 2 1 400000 01
0.5 x 2 0 400000 00
0.5 x 2 -1 400000 FF
0.5 x 2 -128 400000 80
0.0 x 2 0 000000 00
-1.0 x 2 0 800000 00
-0.5000001 x 2 -128 BFFFFF 80
-0.7500001 x 2 4 9FFFFF 04