除算と言えば遅い命令のひとつですが、逆数(1/x) を求めるのはそんなに遅くないです。(y/x) の精度いらない時とかは、y * (1/x)にすると、除算よりも大分高速に近似値が求められます。
何故逆数は遅くないのか…は、よく知らないですが、変数一個になるのでテーブル引きできる + ニュートン法で求められるとかが効くのではないですかね…
SSE, AVXにも逆数命令はあって、スループットで1〜2サイクルあたり、4個、8個の 12bit 逆数が求められます。
逆数をニュートン法で求めるときは、1回反復するごとに、bit数が倍になるらしいので、12bitの逆数は、1回反復すると、24bitで、単精度分になります。
倍精度だと、ちょっと判断が難しくて、2回反復で48bit、 3回反復で96bitなので、精度捨てるか、時間捨てるかを迫られてる気がしますね。
AVX-512 では、逆数を28bit求める、vrcp28pd という命令が増えました。これなら倍精度でも1回反復するだけで52bit+オマケで4bit得られます。もう迷わなくてよいです。でもなんで26でなくて28bit…?丸め分も考慮してるの?よく知らないので詳しい人に聞いてください。
#include <immintrin.h>
#include <stdio.h>
double in[8] = {2,3,4,5, 6,7,8,9};
double out[8];
int
main()
{
__m512d v = _mm512_loadu_pd(in);
__m512d r = _mm512_rcp28_pd(v);
_mm512_storeu_pd(out, r);
for (int i=0; i<8; i++) {
printf("%f\n", out[i]);
}
}
$ gcc -O2 a.c -mavx512er
$ sde -knl -- ./a.out
0.500000
0.333333
0.250000
0.200000
0.166667
0.142857
0.125000
0.111111
AVX-512ER 拡張が必要です。Skylake, Cannonlake では動かず、KNLでは動きます。
また、SSE,AVX の12bit逆数は、倍精度版が無くて、倍精度で使う場合は単精度値から変換する必要があったのですが、AVX-512 では、14bit逆数を倍精度並びにしてくれる vrcp14pd が増えたので親切さが増してる感じがあります。さらに、14bitなら2回反復で52bit越えますね。vrcp14pd, vrcp14ps は、Skylakeでも使えます。
明日は @tanakmura が vexp2pd について書きます。