私の書いた実装ってどうなってたっけ、と見てみると、Pade近似でした。 exp.cppでいうところのfloat d = x - n;に対して、0<d<1/8となるまでdを1/2し、その値に対してPade近似、1/2した回数に応じて結果をべき乗、というコードでした。またexp(x)=(2^a)*(e^b)の形に変換してaの項から指数部を直接計算してるのでnに関してのテーブル引きはやってません。
が、メモリ使っていいならテーブルが有利そうですねえ。Pade近似は割り算いるし。
|
[175]Re:exp へるみ . 2009 11/12(Thr) 21:34
|
テーブル引きも結構重たし,SIMDしにくいのであまり好きじゃないのですが,今回は安易にPade近似に走らないようにしてみました(笑).実際のところ8次までのローラン展開を計算する部分だけで今回のやつより遅くなっちゃう感じです.
#ところでおめでとうございます.
|
|
|
[176]Re:exp seizh . 2009 12/9(Wed) 17:56
|
fmathの対応ありがとうございます。
Cygwinでのビルドですが、Xbyakにおける例の箇所だけ修正すれば特に 動作上問題ありませんでした。以下、私の環境での計測結果です。
・Core 2 Quad Q9550 ・Windows XP SP3 ・gcc version 4.3.2 20080827 (beta) 2 (GCC) i686-pc-cygwin
32bit gcc 4.3 useSSE41=1, verifyAll=0 fmath::exp max=4.768372e-07, abs ave=9.176717e-08 ave=9.900496e-09 max=0.000000 fmath::pExp max=4.768372e-07, abs ave=9.176717e-08 ave=9.900496e-09 max=0.000000 range=[0.00, 2.00], d=1.000000e-06, N=30 std::exp sum=4473924.500000 ave=143.022clk(x1.00) fmath::exp sum=4473924.500000 ave= 17.807clk(x8.03) fmath::pExp sum=4473924.500000 ave= 13.747clk(x10.40) range=[0.00, 4.00], d=1.000000e-05, N=30 std::exp sum=5207314.500000 ave=160.378clk(x1.00) fmath::exp sum=5207314.500000 ave= 17.743clk(x9.04) fmath::pExp sum=5207314.500000 ave= 13.765clk(x11.65) range=[0.00, 20.00], d=1.000000e-05, N=30 std::exp sum=48480538066944.000000 ave=175.139clk(x1.00) fmath::exp sum=48480538066944.000000 ave= 17.731clk(x9.88) fmath::pExp sum=48480538066944.000000 ave= 13.739clk(x12.75) range=[-1.00, 0.00], d=1.000000e-06, N=30 std::exp sum=559240.562500 ave=107.843clk(x1.00) fmath::exp sum=559240.562500 ave= 17.845clk(x6.04) fmath::pExp sum=559240.562500 ave= 13.795clk(x7.82) range=[-10.00, 0.00], d=1.000000e-05, N=30 std::exp sum=95631.367188 ave=171.428clk(x1.00) fmath::exp sum=95631.367188 ave= 17.614clk(x9.73) fmath::pExp sum=95631.367188 ave= 13.739clk(x12.48)
単一データに対する並列化は確かにやりにくそうですが4並列とか8並列なら それなりに需要はあるかと思います。 たとえば Intel Compilerの ___m128 __cdecl _mm_exp_ps(__m128 x); みたいな
|
|
|
|