背景
embree-aarch64 において, ARM NEON だと交差判定で欠けがでる.
どうも除算 and/or 平方根の精度の問題っぽい.
ARM NEON と x64(SSE2) での 1/x と 1/sqrt(x) の近似命令を使った 1/x と 1/sqrt(x) の計算の精度を合わせたい.
基本情報
a/x の計算(除算): 1/x を求め, a * (1/x)
で実現
sqrt(x) の計算: 1/sqrt(x) を求め, x * (1/sqrt(x))
で求めることができる.
精度について
e < 2^{-n}
の誤差のとき, n bit の精度と言うことにします.
また, 単精度を扱います.
命令の実装的には, テーブルを引いていると思われます(参照文献 "ディジタル数値演算回路の実用設計" 参照).
倍精度の場合はテーブルを増やすのははたぶん意味がなくて(これも参照文献 "ディジタル数値演算回路の実用設計" 参照), Newton-Raphson iteration で精度を上げての対応になるためと思われますので, 倍精度の場合は少なくとも SSE2 では近似命令は存在しませんので, 単精度の近似命令を使いまします.
(これにより, assembler 上では float <-> double の変換が発生しますが, uOP fusion して実行時には実際には消える... かも?)
Newton-Raphson を何回か適用することで, 実際の除算/逆平方根とおなじ精度がほぼだせます(たぶん).
近似ではない実際の除算, 逆平方根と同じ精度を出すには, 22~23 bit の精度(float32)が必要でしょうか.
近似命令は, SSE では ~12bit, ARM NEON では ~6 or 7bit 程度のようです.
NEONの逆数推定命令の精度 : Accuracy of NEON reciprocal estimation instruction
https://qiita.com/sanmanyannyan/items/62bb5ce6ada975a7106a
ありがとうございます. ARM の場合 CPU にもよるのですね.
したがって NEON ではより Newton-Raphson でのイテレーションを増やす必要があります. 幸いなことに, NEON では Newton-Raphson 用の命令が用意されています.
ARM NEONでの初期逆数推定値の補正 / Correction of reciprocal value w/ ARM NEON
https://qiita.com/sanmanyannyan/items/4d06b00078dd4abc4225
ありがとうございます.
SSE2
_mm_rcp_**
, _mm_rsqrt_**
命令があります.
AVX
AVX512VL(AVX512F?)から, 14bit 精度での rsqrt vrsqrt14ss
, vrsqrt14ps
があります.
ARM NEON
vrecipeq_f32
, vrsqrteq_f32
で近似を求める命令があります.
NEON の場合は整数用の命令もあるのがいいですね.
ここから, Newton-Raphon 用の計算を行ってくれる命令(SSE/AVX には無い)
vrecipsq_f32
, vrsqrtsq_f32
を使って精度をあげることができます.
(命令名称が似ているので注意!)
ARM NEONの使い方 除算編
http://atkg.hatenablog.com/entry/2016/11/26/205019
考察
ARM NEON では NewtonRaphson iteration を増やさないと精度がでないので, 精度求めるなら命令数は多くなる.
Intel のように, div 命令が別ポートで実行されているなら, 以外と近似で求めなくても性能でる...かも?
もしくは, 自前逆数テーブル引きを実装してみるとか...(NEON だと, テーブルルックアップに使える命令があったような?)
参考情報
- https://en.wikipedia.org/wiki/Fast_inverse_square_root
- ディジタル数値演算回路の実用設計―四則演算、初等超越関数、浮動小数点演算の作りかた (Design Wave Advanceシリーズ) https://www.cqpub.co.jp/hanbai/books/36/36171.htm