Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
LLVMで遊ぶ	  整数圧縮とか、x86向け自動ベクトル化とか	                            2013/3/30	               maropu@x86/64最適化勉強会5	  	             ...
clang	       LLVMで遊ぶ	  整数圧縮とか、x86向け自動ベクトル化とか	                            2013/3/30	               maropu@x86/64最適化勉強会5	  	...
本日の概要	•  なんでお前clang(LLVM)の話してんの?	    –  RDBMS関連の話題で最近良く扱われるため勉強中	    –  今書いている整数圧縮のコードをより高速化したい	  •  整数圧縮ライブラリ:	  vpacker	...
LLVMとの出会い・・・	                 4
DB業界におけるLLVMの利活用	•  SQLによる関係代数の処理をLLVM-­‐JITで改善	    –  既存DBのSQL処理系*1は冗長的で非効率	                                *1SQLコンパイラとSQ...
DB業界におけるLLVMの利活用	•  Cloudera	  ImpalaにおけるLLVMの利用	    •  SQL対応の分散クエリエンジン	    •  aggregaQon/join/scanの一部をJITで効率化	    •  hCps...
整数圧縮ライブラリ: vpacker	                       7
vpacker	•  32/64-­‐bit整数列を圧縮するライブラリ(C/C++/Java)	    –  hCps://github.com/maropu/vpacker	    	  •  前提条件:	  正の歪度をもつ整数列を効率的に圧...
vpacker	  –	  使い方 	                         9
近年の整数圧縮手法	     ~1990’s	     ~2000’s	                                 ~2013	                                               ...
近年の整数圧縮手法	     ~1990’s	     ~2000’s	                                 ~2013	                                               ...
vpacker	  –	  内部構造	  •  圧縮データのバイナリフォーマット	     –  前半のディスクリプタ部と圧縮したデータ部で構成	         ディスクリプタ部(desc)	     圧縮データ部(in)	      1-b...
vpacker	  –	  内部構造	  •  圧縮データのバイナリフォーマット	         ディスクリプタ部(desc)	                    圧縮データ部(in)	      1-byteのデータに固定長1-bitで...
vpacker	  –	  内部構造	•  圧縮データのバイナリフォーマット	          2-byteのデータに固定長2-bitで8個の整数が格納	       ディスクリプタ部(desc)	                    圧縮...
vpacker	  –	  内部構造	•  復元処理の動作概要	         2-byteのデータに固定長2-bitで8個の整数が格納	      ディスクリプタ部(desc)	            圧縮データ部(in)	     1-b...
vpacker	  –	  内部構造	•  LLVM-­‐JITを用いてwhile-­‐switchを軽量化	    –  共通する復元処理をまとめることでjmp命令を除去	        ディスクリプタ部(desc)	            ...
vpacker	  –	  内部構造	•  呼び出しが集中している関数を高速化	    –  基本はSIMDを利用したデータ並列性の向上	        ディスクリプタ部(desc)	               圧縮データ部(in)	    ...
gcc(v4.8)の自動ベクトル化	•  この関数*1ってどんな機械語に変換されるの?	     –  処理に依存関係が無く,ベクトル化しやすそうな印象	     void unpack1(const char *in, uint32_t *o...
gcc(v4.8)の自動ベクトル化	•  この関数ってどんな機械語に変換されるの?	   –  処理に依存関係が無く,ベクトル化しやすそうな印象	    void unpack1(const char *in, uint32_t *out, i...
gcc(v4.8)の自動ベクトル化	•  この関数ってどんな機械語に変換されるの?	   –  処理に依存関係が無く,ベクトル化しやすそうな印象	    void unpack1(const char *in, uint32_t *out, i...
gcc(v4.8)の自動ベクトル化	•  この関数ってどんな機械語に変換されるの?	   –  処理に依存関係が無く,ベクトル化しやすそうな印象	    void unpack1(const char * __restrict__ in,   ...
gcc(v4.8)の自動ベクトル化	      •  一部だけ抜粋	  &	  並び替え(’gcc	  -­‐O3’)	        movdqu      (%r9), %xmm1   // in - %xmm1         pxor ...
gcc(v4.8)の自動ベクトル化	      •  一部だけ抜粋	  	  並び替え(’gcc	  -­‐O3’)	        movdqu      (%r9), %xmm1   // in - %xmm1         pxor  ...
gcc(v4.8)の自動ベクトル化	      •  一部だけ抜粋	  	  並び替え(’gcc	  -­‐O3’)	        movdqu      (%r9), %xmm1    // in - %xmm1         pxor ...
clangのx86向け自動ベクトル化	                           25
clangと自動ベクトル化	•  LLVM上に実装されたC/C++用フロントエンド	      –  hCp://clang.llvm.org/index.html	  •  Auto-­‐VectorizaQon	  in	  LLVM	  ...
clangにおける2種類のVectorizer	•  Basic-­‐Block(BB)	  Vectorizer	  –	  SLP	  in	  gcc	  	       –  v3.1で”	  -­‐mllvm	  –vectorize...
clangの自動ベクトル化パラメータ	•  clang-­‐v3.2を利用(2013/3/30現在最新)	      –  デフォルトで自動ベクトル化は全てOFF	      –  v3.3からLoop	  Vectorizerはデフォルトに	...
その他の補助パラメータ	•  -­‐mllvm	  –unroll-­‐allow-­‐parQal	         –  Loop内の部分的なUnrollを可能に	  •  -­‐mllvm	  –unroll-­‐runQme	     ...
WriQng	  Vectorizer-­‐Friendly	  Code	  in	  clang	  	  •  example.1#	         –  clang	  -­‐O3	  -­‐mllvm	  -­‐vectorize-...
WriQng	  Vectorizer-­‐Friendly	  Code	  in	  clang	  	  •  example.1#	         –  clang	  -­‐O3	  -­‐mllvm	  -­‐vectorize-...
WriQng	  Vectorizer-­‐Friendly	  Code	  in	  clang	  	  •  example.2#	         –  clang	  -­‐O3	  -­‐mllvm	  -­‐vectorize-...
WriQng	  Vectorizer-­‐Friendly	  Code	  in	  clang	  	  •  example.2#	         –  clang	  -­‐O3	  -­‐mllvm	  -­‐vectorize-...
WriQng	  Vectorizer-­‐Friendly	  Code	  in	  clang	  	  •  example.3#	         –  clang	  -­‐O3	  -­‐mllvm	  -­‐vectorize-...
WriQng	  Vectorizer-­‐Friendly	  Code	  in	  clang	  	  •  example.3#	         –  clang	  -­‐O3	  -­‐mllvm	  -­‐vectorize-...
WriQng	  Vectorizer-­‐Friendly	  Code	  in	  clang	  	  •  example.4#	         –  clang	  -­‐O3	  -­‐mllvm	  -­‐vectorize-...
WriQng	  Vectorizer-­‐Friendly	  Code	  in	  clang	  	  •  example.4#	         –  clang	  -­‐O3	  -­‐mllvm	  -­‐vectorize-...
WriQng	  Vectorizer-­‐Friendly	  Code	  in	  clang	  	  •  example.4#	         –  gcc	  -­‐O3	  -­‐ffast-­‐math	  	        ...
WriQng	  Vectorizer-­‐Friendly	  Code	  in	  clang	  	  •  example.4#	         –  gcc	  -­‐O3	  -­‐ffast-­‐math	     ベクトル加算...
最後に・・・	               40
clangが出力する「unpack1」	•  一部だけ抜粋(’	  clang	  -­‐S	  -­‐O3	  -­‐mllvm	  -­‐vectorize’)	      movsbl     (%rdi), %eax        # ...
gcc-­‐4.8	  vs	  clang-­‐3.2	  	•  「unapack1」の性能比較	  •  Intel	  Core	  i5-­‐3427@1.8GHzを使用	                         n=15	 ...
本日のまとめ	               43
本日のまとめ	•  clang-­‐v3.2の自動ベクトル化の性能調査	    –  基本的なものは自動的にベクトル化される	    –  処理が複雑になるとgccに対して2~3倍程度の性能差も	  •  ‘Vectorizer-­‐Frien...
本日のまとめ	•  自動ベクトル化のためのコード規約	   	  	  	  1.	  ポインタのエイリアスは避ける	   	  	  	  	  	   ・必要な個所では__restrict__を付ける	   	   	  	  	  2.	...
Upcoming SlideShare
Loading in …5
×

LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)

11,101 views

Published on

LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)

  1. 1. LLVMで遊ぶ  整数圧縮とか、x86向け自動ベクトル化とか 2013/3/30   maropu@x86/64最適化勉強会5     1
  2. 2. clang LLVMで遊ぶ  整数圧縮とか、x86向け自動ベクトル化とか 2013/3/30   maropu@x86/64最適化勉強会5     2
  3. 3. 本日の概要 •  なんでお前clang(LLVM)の話してんの?   –  RDBMS関連の話題で最近良く扱われるため勉強中   –  今書いている整数圧縮のコードをより高速化したい  •  整数圧縮ライブラリ:  vpacker   –  hCps://github.com/maropu/vpacker  •  clangのx86向け自動ベクトル化   –  SIMDを使用した命令列への自動変換   3
  4. 4. LLVMとの出会い・・・ 4
  5. 5. DB業界におけるLLVMの利活用 •  SQLによる関係代数の処理をLLVM-­‐JITで改善   –  既存DBのSQL処理系*1は冗長的で非効率   *1SQLコンパイラとSQL実行エンジンのこと Thomas Neumann, Efficiently Compiling Efficient Query Plans for Modern Hardware, Proc. of VLDB’11 5
  6. 6. DB業界におけるLLVMの利活用 •  Cloudera  ImpalaにおけるLLVMの利用   •  SQL対応の分散クエリエンジン   •  aggregaQon/join/scanの一部をJITで効率化   •  hCps://github.com/cloudera/impala   引用: http://www.theregister.co.uk/2012/10/24/cloudera_hadoop_impala_real_time_query/ 6
  7. 7. 整数圧縮ライブラリ: vpacker 7
  8. 8. vpacker •  32/64-­‐bit整数列を圧縮するライブラリ(C/C++/Java)   –  hCps://github.com/maropu/vpacker    •  前提条件:  正の歪度をもつ整数列を効率的に圧縮   –  大半が小さい値で、稀に大きな値が発生  •  ライブラリの特徴   –  少ないメモリ量で圧縮&展開   –  ILPを考慮した展開処理  -­‐  γ/δ符号と比べて速い   –  動的計画法による圧縮率の最適化   –  ヘッダファイルの読み込みのみで使用可能   8
  9. 9. vpacker  –  使い方 9
  10. 10. 近年の整数圧縮手法 ~1990’s ~2000’s ~2013 BP/SIMD-BP(2012) γ/δ/Variable-Byte符号 Varint-G8IU(2011) Simple9(2005) Simple16(2009) Simple8b(2010) VSEncoding(2010) PForDelta(2006) OPTPForDelta(2009) SIMD-FastPFor/SimplePFor(2012) 10
  11. 11. 近年の整数圧縮手法 ~1990’s ~2000’s ~2013 BP/SIMD-BP(2012) γ/δ/Variable-Byte符号 Varint-G8IU(2011) Simple9(2005) Simple16(2009) Simple8b(2010) -  現在、最速の手法で秒間2000M個整数を展開 -  vpackerは20130330現在の実装で秒間600〜700M程度 VSEncoding(2010) PForDelta(2006) OPTPForDelta(2009) SIMD-FastPFor/SimplePFor(2012) 11
  12. 12. vpacker  –  内部構造  •  圧縮データのバイナリフォーマット   –  前半のディスクリプタ部と圧縮したデータ部で構成   ディスクリプタ部(desc) 圧縮データ部(in) 1-byteのディスクリプタの列 圧縮された整数データ 後半の圧縮したデータが どのように格納されているかを記録 12
  13. 13. vpacker  –  内部構造  •  圧縮データのバイナリフォーマット   ディスクリプタ部(desc) 圧縮データ部(in) 1-byteのデータに固定長1-bitで8個の整数が格納 void unpack1_8(const char *in, uint32_t *out) { *out++ = in[0] & 0x01; *out++ = (in[0] >> 1) & 0x01; *out++ = (in[0] >> 2) & 0x01; ... *out++ = (in[0] >> 7) & 0x01; } 13
  14. 14. vpacker  –  内部構造 •  圧縮データのバイナリフォーマット   2-byteのデータに固定長2-bitで8個の整数が格納 ディスクリプタ部(desc) 圧縮データ部(in) 1-byteのデータに固定長1-bitで8個の整数が格納 void unpack2_8(const char *in, uint32_t *out) { *out++ = in[0] & 0x03; *out++ = (in[0] >> 2) & 0x03; *out++ = (in[0] >> 4) & 0x03; ... *out++ = (in[1] >> 6) & 0x03; } 14
  15. 15. vpacker  –  内部構造 •  復元処理の動作概要   2-byteのデータに固定長2-bitで8個の整数が格納 ディスクリプタ部(desc) 圧縮データ部(in) 1-byteのデータに固定長1-bitで8個の整数が格納 while (1) { switch (*desc++) { case 1-bitで8個の整数を展開: unpack1_8(in, out); break; case 2-bitで8個の整数を展開: unpack2_8(in, out); break; ... } -  VMのインタプリタ的な処理の流れ } -  descは1-byteのため最大256分岐(分岐数は設計による) 15
  16. 16. vpacker  –  内部構造 •  LLVM-­‐JITを用いてwhile-­‐switchを軽量化   –  共通する復元処理をまとめることでjmp命令を除去   ディスクリプタ部(desc) 圧縮データ部(in) 「前提条件」より大半の復元処理は 一部の関数に集中 while (1) { switch (*desc++) { case 1-bitで8個の整数を展開: unpack1_8(in, out); break; case 2-bitで8個の整数を展開: unpack2_8(in, out); break; ... } } 16
  17. 17. vpacker  –  内部構造 •  呼び出しが集中している関数を高速化   –  基本はSIMDを利用したデータ並列性の向上   ディスクリプタ部(desc) 圧縮データ部(in) 呼び出しが集中している関数を高速化 while (1) { switch (*desc++) { case 1-bitで8個の整数を展開: unpack1_8(in, out); break; case 2-bitで8個の整数を展開: unpack2_8(in, out); break; ... } } 17
  18. 18. gcc(v4.8)の自動ベクトル化 •  この関数*1ってどんな機械語に変換されるの?   –  処理に依存関係が無く,ベクトル化しやすそうな印象   void unpack1(const char *in, uint32_t *out, int n) { for (int i = 0; i < n; i++) { *out++ = in[0] & 0x01; *out++ = (in[0] >> 1) & 0x01; *out++ = (in[0] >> 2) & 0x01; ... *out++ = (in[0] >> 7) & 0x01; } } *1 現実に即して,ループ回数(n)を指定できるように変更しました 18
  19. 19. gcc(v4.8)の自動ベクトル化 •  この関数ってどんな機械語に変換されるの?   –  処理に依存関係が無く,ベクトル化しやすそうな印象   void unpack1(const char *in, uint32_t *out, int n) { for (int i = 0; i < n; i++) { *out++ = in[0] & 0x01; *out++ = (in[0] >> 1) & 0x01; *out++ = (in[0] >> 2) & 0x01; ... *out++ = (in[0] >> 7) & 0x01; } } 重要) コンパイルする前に自動ベクトル化されやすいように前処理 19
  20. 20. gcc(v4.8)の自動ベクトル化 •  この関数ってどんな機械語に変換されるの?   –  処理に依存関係が無く,ベクトル化しやすそうな印象   void unpack1(const char *in, uint32_t *out, int n) { for (int i = 0; i < n; i++) { for (int j = 0; j < 8; j++) *out++ = (*in >> j) & 0x01; in++; } } gccの場合、SLP(Superword-Level Parallelism)による最適化より Loop Vectorizerに任せたほうが良いらしいです 20
  21. 21. gcc(v4.8)の自動ベクトル化 •  この関数ってどんな機械語に変換されるの?   –  処理に依存関係が無く,ベクトル化しやすそうな印象   void unpack1(const char * __restrict__ in, uint32_t * __restrict__ out, int n) { for (int i = 0; i < n; i++) { for (int j = 0; j < 8; j++) *out++ = (*in >> j) & 0x01; in++; } } __restrict__を付与してin/outを呼び出し側で16Bにアライメント 21
  22. 22. gcc(v4.8)の自動ベクトル化 •  一部だけ抜粋  &  並び替え(’gcc  -­‐O3’)   movdqu (%r9), %xmm1 // in - %xmm1 pxor %xmm2, %xmm2 pcmpgtb %xmm1, %xmm2 movdqa %xmm1, %xmm3 punpckhbw %xmm2, %xmm1 punpcklbw %xmm2, %xmm3      pxor %xmm2, %xmm2 movdqa %xmm3, %xmm4 pcmpgtw %xmm3, %xmm2 punpcklwd %xmm2, %xmm4 movdqa %xmm4, %xmm5 pand %xmm0, %xmm5 // %xmm1=[0x01, 0x01, 0x01, 0x01] .... 22
  23. 23. gcc(v4.8)の自動ベクトル化 •  一部だけ抜粋    並び替え(’gcc  -­‐O3’)   movdqu (%r9), %xmm1 // in - %xmm1 pxor %xmm2, %xmm2 pcmpgtb %xmm1, %xmm2 movdqa %xmm1, %xmm3 punpckhbw %xmm2, %xmm1 punpcklbw %xmm2, %xmm3 バイトからワードに符号拡張       pxor %xmm2, %xmm2 movdqa %xmm3, %xmm4 pcmpgtw %xmm3, %xmm2 punpcklwd %xmm2, %xmm4 ワードからダブルワードに符号拡張 movdqa %xmm4, %xmm5 pand %xmm0, %xmm5 // %xmm1=[0x01, 0x01, 0x01, 0x01] .... 0x01でマスクして展開処理完了 23
  24. 24. gcc(v4.8)の自動ベクトル化 •  一部だけ抜粋    並び替え(’gcc  -­‐O3’)   movdqu (%r9), %xmm1 // in - %xmm1 pxor %xmm2, %xmm2 pcmpgtb %xmm1, %xmm2 movdqa %xmm1, %xmm3 punpckhbw %xmm2, %xmm1 punpcklbw %xmm2, %xmm3 バイトからワードに符号拡張       pxor %xmm2, %xmm2 movdqa %xmm3, %xmm4 pcmpgtw %xmm3, %xmm2 punpcklwd %xmm2, %xmm4 ワードからダブルワードに符号拡張 ‘n 15’で分岐させてLoopを全てinline化するアグレッシブな最適化 movdqa %xmm4, %xmm5 →’n = 15’はベクトル化されていないパスに分岐 pand %xmm0, %xmm5 // %xmm1=[0x01, 0x01, 0x01, 0x01] .... 0x01でマスクして展開処理完了 24
  25. 25. clangのx86向け自動ベクトル化   25
  26. 26. clangと自動ベクトル化 •  LLVM上に実装されたC/C++用フロントエンド   –  hCp://clang.llvm.org/index.html  •  Auto-­‐VectorizaQon  in  LLVM   –  hCp://llvm.org/docs/Vectorizers.html  •  Linpackを用いた性能評価   –  with  loop  vectorizaQon  at  -­‐O3  running  on  a  Sandybridge   自動ベクトル化の有無で 性能差が3倍程度! 26
  27. 27. clangにおける2種類のVectorizer •  Basic-­‐Block(BB)  Vectorizer  –  SLP  in  gcc     –  v3.1で”  -­‐mllvm  –vectorize”として導入   –  最適化の対象が「Basic  Block」   –  歴史的に実装されたのはコチラが先  •  Loop  Vectorizer   –  v3.2でようやく”  -­‐mllvm  –vectorize-­‐loops”として導入   –  「Unroll+BB  Vectorizer」にLoop間依存解析を加えたもの   –  自動ベクトル化の制約(v3.2のReleaseNotesより)   •  Loop枚のカウントは”1”のみ   •  InducQon変数は一番内側のLoopのみ使用可能   27
  28. 28. clangの自動ベクトル化パラメータ •  clang-­‐v3.2を利用(2013/3/30現在最新)   –  デフォルトで自動ベクトル化は全てOFF   –  v3.3からLoop  Vectorizerはデフォルトに    •  -­‐mllvm  –vectorize,  -­‐mllvm  –vectorize-­‐loops   –  -­‐O2/-­‐O3との併用が必要   –  -­‐Osはコード増加が発生しない場合に適用  •  -­‐mllvm  –bb-­‐vectorize-­‐aligned-­‐only   –  アラインされたstore/loadのみを最適化に使用  •  -­‐mllvm  –force-­‐vector-­‐width=X   –  最適化で使用するベクトル要素数をXで指定   28
  29. 29. その他の補助パラメータ •  -­‐mllvm  –unroll-­‐allow-­‐parQal   –  Loop内の部分的なUnrollを可能に  •  -­‐mllvm  –unroll-­‐runQme   –  実行時にLoopを数えてUnroll可能に  •  -­‐funsafe-­‐math-­‐opQmizaQons,  -­‐ffast-­‐math   –  浮動小数点演算にIEEE/ISO仕様外の最適化を適用  •  他の関連するパラメータは以下の資料が詳しい   –  Auto-­‐vectorizaQon  with  LLVM   –  hCp://llvm.org/devmtg/2012-­‐04-­‐12/Slides/Hal_Finkel.pdf     29
  30. 30. WriQng  Vectorizer-­‐Friendly  Code  in  clang    •  example.1#   –  clang  -­‐O3  -­‐mllvm  -­‐vectorize-­‐loops     void test1(float * __restrict__ a, float * __restrict__ b, int n) { for (int i = 0; i n; i++) a[i] += b[i]; } 30
  31. 31. WriQng  Vectorizer-­‐Friendly  Code  in  clang    •  example.1#   –  clang  -­‐O3  -­‐mllvm  -­‐vectorize-­‐loops     %rdiと%rsiは16Bに揃えてあるのに .LBB0_2: なぜかmovapsに変換されない? movups 16(%rdi,%rax,4), %xmm1 movups 16(%rsi,%rax,4), %xmm0 addps %xmm1, %xmm0 movups (%rdi,%rax,4), %xmm1 movups (%rsi,%rax,4), %xmm2 movups %xmm0, 16(%rdi,%rax,4) addps %xmm1, %xmm2 movups %xmm2, (%rdi,%rax,4) addq $8, %rax cmpq %rax, %rcx jne .LBB0_2 31
  32. 32. WriQng  Vectorizer-­‐Friendly  Code  in  clang    •  example.2#   –  clang  -­‐O3  -­‐mllvm  -­‐vectorize-­‐loops     void test2(float * __restrict__ a, float * __restrict__ b, int n) { for (int i = 0; i n; i += 2) a[i] += b[i]; } 32
  33. 33. WriQng  Vectorizer-­‐Friendly  Code  in  clang    •  example.2#   –  clang  -­‐O3  -­‐mllvm  -­‐vectorize-­‐loops     .LBB0_2: movss (%rsi,%rax,4), %xmm0 addss (%rdi,%rax,4), %xmm0 movss %xmm0, (%rdi,%rax,4) addq $2, %rax cmpl %edx, %eax jl .LBB0_2 33
  34. 34. WriQng  Vectorizer-­‐Friendly  Code  in  clang    •  example.3#   –  clang  -­‐O3  -­‐mllvm  -­‐vectorize-­‐loops     void test3(float * __restrict__ a, float * __restrict__ b, int n) { for (int i = 0; i n; i += 1) { for (int j = 0; j SIZE; j++) a[i * SIZE + j] += b[i * SIZE + j]; } } 34
  35. 35. WriQng  Vectorizer-­‐Friendly  Code  in  clang    •  example.3#   –  clang  -­‐O3  -­‐mllvm  -­‐vectorize-­‐loops     .LBB1_22: # = The Inner Loop movups (%rbx), %xmm2 movups 16(%rbx), %xmm1 movups (%rax), %xmm0 movups 16(%rax), %xmm3 addps %xmm2, %xmm0 addps %xmm1, %xmm3 movups %xmm3, 16(%rbx) movups %xmm0, (%rbx) addq $32, %rbx addq $32, %rax addq $-8, %rdi jne .LBB1_22 35
  36. 36. WriQng  Vectorizer-­‐Friendly  Code  in  clang    •  example.4#   –  clang  -­‐O3  -­‐mllvm  -­‐vectorize-­‐loops     float test4(float * __restrict__ a, int n) { float S = 0.0; for (int i = 0; i n; i += 1) S += a[i]; return S; } 36
  37. 37. WriQng  Vectorizer-­‐Friendly  Code  in  clang    •  example.4#   –  clang  -­‐O3  -­‐mllvm  -­‐vectorize-­‐loops     .LBB0_1: addss (%rdi), %xmm0 addq $4, %rdi decl %esi jne .LBB0_1 浮動小数点演算は結合則が成り立たないため、こういう命令列に →clangにも’-ffast-math’があるが、出力する命令は同じだった 37
  38. 38. WriQng  Vectorizer-­‐Friendly  Code  in  clang    •  example.4#   –  gcc  -­‐O3  -­‐ffast-­‐math     .L33: addps (%rax), %xmm0 addq $16, %rax cmpq %rdx, %rax jne .L33 movaps %xmm0, %xmm1 movhlps %xmm0, %xmm1 addps %xmm0, %xmm1 movaps %xmm1, %xmm0 shufps $85, %xmm1, %xmm0 addps %xmm1, %xmm0 unpcklps %xmm0, %xmm0 38
  39. 39. WriQng  Vectorizer-­‐Friendly  Code  in  clang    •  example.4#   –  gcc  -­‐O3  -­‐ffast-­‐math   ベクトル加算して   .L33: addps (%rax), %xmm0 addq $16, %rax cmpq %rdx, %rax jne .L33 水平加算 movaps %xmm0, %xmm1 movhlps %xmm0, %xmm1 addps %xmm0, %xmm1 movaps %xmm1, %xmm0 shufps $85, %xmm1, %xmm0 addps %xmm1, %xmm0 unpcklps %xmm0, %xmm0 39
  40. 40. 最後に・・・   40
  41. 41. clangが出力する「unpack1」 •  一部だけ抜粋(’  clang  -­‐S  -­‐O3  -­‐mllvm  -­‐vectorize’)   movsbl (%rdi), %eax # *in - %eax movd %eax, %xmm0 pshufd $0, %xmm0, %xmm4 pshufd $68, %xmm4, %xmm3 pand %xmm8, %xmm4 movl %eax, %ecx ... shrq $2, %r10 movd %r10, %xmm0 punpcklqdq %xmm7, %xmm0 pand 人類には早すぎる難解なアセンブリが出力された・・・ %xmm1, %xmm0 pshufd →nの値でunrollはしないgccに比べてコンサバな最適化 $-128, %xmm0, %xmm7 movss %xmm6, %xmm7 movlhps %xmm7, %xmm5 shufps $-30, %xmm7, %xmm5 movups %xmm5, (%rsi) # %xmm5 - dst 41
  42. 42. gcc-­‐4.8  vs  clang-­‐3.2   •  「unapack1」の性能比較  •  Intel  Core  i5-­‐3427@1.8GHzを使用   n=15 n=16 n=32 n=64 gcc 0.051us 0.040us 0.073us 0.152us clang 0.105us 0.110us 0.224us 0.446us raQo x2.1 x2.7 x3.1 x3.0 ベクトル化された状態で約3倍の性能差 42
  43. 43. 本日のまとめ   43
  44. 44. 本日のまとめ •  clang-­‐v3.2の自動ベクトル化の性能調査   –  基本的なものは自動的にベクトル化される   –  処理が複雑になるとgccに対して2~3倍程度の性能差も  •  ‘Vectorizer-­‐Friendly’はまだまだ重要   –  完全にコンパイラ任せ,というわけには現在いかない   –  256-­‐bit,  512-­‐bit,  ...とベクトル長が増えると性能差は拡大       44
  45. 45. 本日のまとめ •  自動ベクトル化のためのコード規約        1.  ポインタのエイリアスは避ける             ・必要な個所では__restrict__を付ける          2.  ベクトル長の境界に合わせる                  ・__builQn_assume_aligned(X),  __aCribute__((aligned(X))の活用          3.  Loop内の手作業のinline化は避ける                ・Loop  Vectorizerに任せたほうが賢い       45

×