xeonphiハッカソンでexpを作ってみた

12
1XeonPhiハッカソン 2013/8/3 光成滋生

Upload: mitsunari-shigeo

Post on 03-Jul-2015

1.105 views

Category:

Technology


9 download

TRANSCRIPT

Page 1: Xeonphiハッカソンでexpを作ってみた

第1回XeonPhiハッカソン

2013/8/3 光成滋生

Page 2: Xeonphiハッカソンでexpを作ってみた

やったこと

• 自作の近似指数関数double exp(double)をXeonPhiに移植する

Page 3: Xeonphiハッカソンでexpを作ってみた

結果

• icpcに負けた

–実装コード

• https://github.com/herumi/misc/blob/master/exp-xeonphi.cpp

Page 4: Xeonphiハッカソンでexpを作ってみた

作業内容を振り返る

• 既存のベンチマーク

– Phiが載ってるマシン Xeon E5-2620@2GHz

• gcc 4.4.7での比較(clk:小さいほど速い)

• icpc 13.1.3での比較

– Xeon上ではicpcには勝ってる

scalar loop(vector)

std 285 286

fmath 14 8.5

scalar loop(vector)

std 26 9.8

fmath 13.35 7.7

Page 5: Xeonphiハッカソンでexpを作ってみた

Phi上のC(not intrinsic)の評価

• scalar版が勝ってるので速くなるかもと期待

scalar loop(vector)

std 85 14

fmath 78 後ほど

Page 6: Xeonphiハッカソンでexpを作ってみた

intrinsic-SSE版をPhiに移植開始

• __m128d → __m512d

• alignは16byteから64byte単位へ

–忘れると多分落ちる

• _mm_mul_pd → _mm512_mul_pdなど

– このあたりは形式的に可能

Page 7: Xeonphiハッカソンでexpを作ってみた

シャッフルではまる

• x[]の偶数番目だけをy[]に入れる

• x = [...:7:6:5:4:3:2:1:0] → y = [...x4:x2:x0]

• vpermd(_mm512_permutevar_epi32)を使った

– int ptn[16] = { 0, 2, 4, 6, 8, 10, 12, 14 };

– __m512i selEven = (* __m512i*)ptn;

– y = _mm512_permutevar_epi32(selEven, x);

• 引数の順序に注意

• もっとよい方法があるかもしれない(教えてください)

Page 8: Xeonphiハッカソンでexpを作ってみた

gatherを使ってみる

• SSE版は一つずつ読んでpackでくっつける

– Haswellのgatherは次回作に期待?(by 中村さん)

– int32のインデックスからdoubleを読む

• 対応する命令は_mm512_i32logather_epi64

• 遅いのかどうかは時間不足で計測できず

– zmmintrin.hには_mm512_prefetch_i32extgather_ps()とかあった

– これを使えばprefetchできる?

• 今回はindex確定してから利用まで短いので効果は出るか?

Page 9: Xeonphiハッカソンでexpを作ってみた

シフト

• 64bit単位でのシフト命令を探す

–ない

–ない

– 32bit単位のシフトしかない

• ええ??

– 32bit単位でシフトしてorしてエミュレート?

– x=[H:L], x >>= s

• H >>= s, L >>= s, H = (H << (32-s)) >> 32

– byte単位のシフトもない

Page 10: Xeonphiハッカソンでexpを作ってみた

32bit左シフト

• 時間がないので先程のvpermdを使った

– もっとよい方法があれば(略

__m512i shl32bit(__m512i x) { static const MIE_ALIGN(64) int m[16] = { 0, 0, 0, 2, 0, 4, 0, 6, 0, 8, 0, 10, 0, 12, 0, 14 }; static const __m512i y = *(__m512i*)m; __m512i zero = _mm512_setzero_epi32(); return _mm512_mask_permutevar_epi32(zero,0xaaaa,y,x); }

Page 11: Xeonphiハッカソンでexpを作ってみた

実装結果

• 一応scalarの4倍速くなった

–がicpcの自動ベクトル化に負けた

• ヘッダには_mm512_exp_pd()という関数がある

• 言い訳

–まだ動くようにしただけ

• asm出力もみてない 最適化もしてない

• こちらは近似計算だし4clkぐらいはなんとかしたい

scalar loop(vector)

std 85 14

fmath 78 18

Page 12: Xeonphiハッカソンでexpを作ってみた

ToDo

• プリフェッチが効くらしい

– _mm_prefetchを入れてみたが遅くなった(25clk

–他の方法?

• vexp223psを使ってみたかった

– exp()の近似値を返す関数っぽい

• これはAVXにも欲しいAVX-512に期待

– これがあると多分最初のテーブル引きやgatherが不要になる

• が、多分アルゴリズムの修正が必要