SlideShare a Scribd company logo
LLVMで遊ぶ	
  
整数圧縮とか、x86向け自動ベクトル化とか	
                            2013/3/30	
  
             maropu@x86/64最適化勉強会5	
  	
  




                                            1
clang	
       LLVMで遊ぶ	
  
整数圧縮とか、x86向け自動ベクトル化とか	
                            2013/3/30	
  
             maropu@x86/64最適化勉強会5	
  	
  




                                            2
本日の概要	
•  なんでお前clang(LLVM)の話してんの?	
  
  –  RDBMS関連の話題で最近良く扱われるため勉強中	
  
  –  今書いている整数圧縮のコードをより高速化したい	
  

•  整数圧縮ライブラリ:	
  vpacker	
  
  –  hCps://github.com/maropu/vpacker	
  


•  clangのx86向け自動ベクトル化	
  
  –  SIMDを使用した命令列への自動変換	
  




                                            3
LLVMとの出会い・・・	




                 4
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
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
整数圧縮ライブラリ: vpacker	



                       7
vpacker	
•  32/64-­‐bit整数列を圧縮するライブラリ(C/C++/Java)	
  
  –  hCps://github.com/maropu/vpacker	
  
  	
  
•  前提条件:	
  正の歪度をもつ整数列を効率的に圧縮	
  
  –  大半が小さい値で、稀に大きな値が発生	
  


•  ライブラリの特徴	
  
  –  少ないメモリ量で圧縮&展開	
  
  –  ILPを考慮した展開処理	
  -­‐	
  γ/δ符号と比べて速い	
  
  –  動的計画法による圧縮率の最適化	
  
  –  ヘッダファイルの読み込みのみで使用可能	
  

                                              8
vpacker	
  –	
  使い方 	




                         9
近年の整数圧縮手法	
     ~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
近年の整数圧縮手法	
     ~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
vpacker	
  –	
  内部構造	
  
•  圧縮データのバイナリフォーマット	
  
   –  前半のディスクリプタ部と圧縮したデータ部で構成	
  

       ディスクリプタ部(desc)	
     圧縮データ部(in)	



      1-byteのディスクリプタの列     圧縮された整数データ	
       後半の圧縮したデータが
    どのように格納されているかを記録	




                                           12
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
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
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
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
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
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
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
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
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
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
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
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
clangのx86向け自動ベクトル化	
  



                         25
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
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
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
その他の補助パラメータ	
•  -­‐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
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
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
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
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
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
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
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
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
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
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
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
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
本日のまとめ	
•  clang-­‐v3.2の自動ベクトル化の性能調査	
  
  –  基本的なものは自動的にベクトル化される	
  
  –  処理が複雑になるとgccに対して2~3倍程度の性能差も	
  


•  ‘Vectorizer-­‐Friendly’はまだまだ重要	
  
  –  完全にコンパイラ任せ,というわけには現在いかない	
  
  –  256-­‐bit,	
  512-­‐bit,	
  ...とベクトル長が増えると性能差は拡大	
  
   	
  




                                                            44
本日のまとめ	
•  自動ベクトル化のためのコード規約	
  
 	
  	
  	
  1.	
  ポインタのエイリアスは避ける	
  
 	
  	
  	
  	
  	
   ・必要な個所では__restrict__を付ける	
  
 	
  
 	
  	
  	
  2.	
  ベクトル長の境界に合わせる	
  
 	
  	
  	
  	
  	
  	
  	
  	
  ・__builQn_assume_aligned(X),	
  __aCribute__((aligned(X))の活用	
  
 	
  
 	
  	
  	
  3.	
  Loop内の手作業のinline化は避ける	
  
 	
  	
  	
  	
  	
  	
  	
  ・Loop	
  Vectorizerに任せたほうが賢い	
  
  	
  




                                                                                                    45

More Related Content

PDF
2015年度GPGPU実践プログラミング 第5回 GPUのメモリ階層
PDF
ARM CPUにおけるSIMDを用いた高速計算入門
PDF
ゲーム開発者のための C++11/C++14
PDF
いまさら聞けない!CUDA高速化入門
PDF
規格書で読むC++11のスレッド
PDF
高速な倍精度指数関数expの実装
PDF
C++ マルチスレッド 入門
PDF
Intro to SVE 富岳のA64FXを触ってみた
2015年度GPGPU実践プログラミング 第5回 GPUのメモリ階層
ARM CPUにおけるSIMDを用いた高速計算入門
ゲーム開発者のための C++11/C++14
いまさら聞けない!CUDA高速化入門
規格書で読むC++11のスレッド
高速な倍精度指数関数expの実装
C++ マルチスレッド 入門
Intro to SVE 富岳のA64FXを触ってみた

What's hot (20)

PDF
条件分岐とcmovとmaxps
PDF
C++ マルチスレッドプログラミング
PPTX
並列化による高速化
PDF
LLVM最適化のこつ
PDF
明日使えないすごいビット演算
PDF
2015年度先端GPGPUシミュレーション工学特論 第2回 GPUによる並列計算の概念と メモリアクセス
PDF
中3女子でもわかる constexpr
PPTX
画像処理の高性能計算
PDF
カスタムメモリマネージャと高速なメモリアロケータについて
PPTX
AVX-512(フォーマット)詳解
PDF
最適化超入門
PDF
プログラムを高速化する話
PPTX
DockerコンテナでGitを使う
PPTX
Effective Modern C++ 勉強会 Item 22
PDF
Marp Tutorial
PDF
プログラムを高速化する話Ⅱ 〜GPGPU編〜
PPTX
CPU / GPU高速化セミナー!性能モデルの理論と実践:理論編
PDF
いまさら聞けないarmを使ったNEONの基礎と活用事例
PDF
すごい constexpr たのしくレイトレ!
PDF
1076: CUDAデバッグ・プロファイリング入門
条件分岐とcmovとmaxps
C++ マルチスレッドプログラミング
並列化による高速化
LLVM最適化のこつ
明日使えないすごいビット演算
2015年度先端GPGPUシミュレーション工学特論 第2回 GPUによる並列計算の概念と メモリアクセス
中3女子でもわかる constexpr
画像処理の高性能計算
カスタムメモリマネージャと高速なメモリアロケータについて
AVX-512(フォーマット)詳解
最適化超入門
プログラムを高速化する話
DockerコンテナでGitを使う
Effective Modern C++ 勉強会 Item 22
Marp Tutorial
プログラムを高速化する話Ⅱ 〜GPGPU編〜
CPU / GPU高速化セミナー!性能モデルの理論と実践:理論編
いまさら聞けないarmを使ったNEONの基礎と活用事例
すごい constexpr たのしくレイトレ!
1076: CUDAデバッグ・プロファイリング入門
Ad

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

PDF
フラグを愛でる
PPTX
Prosym2012
PDF
“Symbolic bounds analysis of pointers, array indices, and accessed memory reg...
PDF
x64 のスカラー,SIMD 演算性能を測ってみた @ C++ MIX #10
PDF
Haswellサーベイと有限体クラスの紹介
PDF
Boost.SIMD
PDF
V6 unix in okinawa
PDF
組み込みでこそC++を使う10の理由
PDF
optimal Ate pairing
PDF
llvm入門
PDF
Precise garbage collection for c
PDF
Xbyakの紹介とその周辺
PDF
あまぁいRcpp生活
PDF
boost tour 1.48.0 all
PDF
x64 のスカラー,SIMD 演算性能を測ってみた v0.1 @ C++ MIX #10
PDF
Boost Tour 1.50.0 All
PDF
KLab勉強会#6 発表資料
PDF
Boost tour 1_40_0
PDF
動的計画法の並列化
PDF
SSE4.2の文字列処理命令の紹介
フラグを愛でる
Prosym2012
“Symbolic bounds analysis of pointers, array indices, and accessed memory reg...
x64 のスカラー,SIMD 演算性能を測ってみた @ C++ MIX #10
Haswellサーベイと有限体クラスの紹介
Boost.SIMD
V6 unix in okinawa
組み込みでこそC++を使う10の理由
optimal Ate pairing
llvm入門
Precise garbage collection for c
Xbyakの紹介とその周辺
あまぁいRcpp生活
boost tour 1.48.0 all
x64 のスカラー,SIMD 演算性能を測ってみた v0.1 @ C++ MIX #10
Boost Tour 1.50.0 All
KLab勉強会#6 発表資料
Boost tour 1_40_0
動的計画法の並列化
SSE4.2の文字列処理命令の紹介
Ad

More from Takeshi Yamamuro (20)

PDF
LT: Spark 3.1 Feature Expectation
PDF
Apache Spark + Arrow
PPT
Quick Overview of Upcoming Spark 3.0 + α
PDF
MLflowによる機械学習モデルのライフサイクルの管理
PDF
Taming Distributed/Parallel Query Execution Engine of Apache Spark
PPTX
LLJVM: LLVM bitcode to JVM bytecode
PDF
20180417 hivemall meetup#4
PDF
An Experimental Study of Bitmap Compression vs. Inverted List Compression
PDF
Sparkのクエリ処理系と周辺の話題
PDF
20160908 hivemall meetup
PDF
20150513 legobease
PDF
20150516 icde2015 r19-4
PDF
VLDB2013 R1 Emerging Hardware
PDF
浮動小数点(IEEE754)を圧縮したい@dsirnlp#4
PDF
Introduction to Modern Analytical DB
PDF
SIGMOD’12勉強会 -Session 7-
PDF
A x86-optimized rank&select dictionary for bit sequences
PDF
VAST-Tree, EDBT'12
PDF
VLDB’11勉強会 -Session 9-
PDF
研究動向から考えるx86/x64最適化手法
LT: Spark 3.1 Feature Expectation
Apache Spark + Arrow
Quick Overview of Upcoming Spark 3.0 + α
MLflowによる機械学習モデルのライフサイクルの管理
Taming Distributed/Parallel Query Execution Engine of Apache Spark
LLJVM: LLVM bitcode to JVM bytecode
20180417 hivemall meetup#4
An Experimental Study of Bitmap Compression vs. Inverted List Compression
Sparkのクエリ処理系と周辺の話題
20160908 hivemall meetup
20150513 legobease
20150516 icde2015 r19-4
VLDB2013 R1 Emerging Hardware
浮動小数点(IEEE754)を圧縮したい@dsirnlp#4
Introduction to Modern Analytical DB
SIGMOD’12勉強会 -Session 7-
A x86-optimized rank&select dictionary for bit sequences
VAST-Tree, EDBT'12
VLDB’11勉強会 -Session 9-
研究動向から考えるx86/x64最適化手法

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

  • 1. LLVMで遊ぶ   整数圧縮とか、x86向け自動ベクトル化とか 2013/3/30   maropu@x86/64最適化勉強会5     1
  • 2. clang LLVMで遊ぶ   整数圧縮とか、x86向け自動ベクトル化とか 2013/3/30   maropu@x86/64最適化勉強会5     2
  • 3. 本日の概要 •  なんでお前clang(LLVM)の話してんの?   –  RDBMS関連の話題で最近良く扱われるため勉強中   –  今書いている整数圧縮のコードをより高速化したい   •  整数圧縮ライブラリ:  vpacker   –  hCps://github.com/maropu/vpacker   •  clangのx86向け自動ベクトル化   –  SIMDを使用した命令列への自動変換   3
  • 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. 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
  • 8. vpacker •  32/64-­‐bit整数列を圧縮するライブラリ(C/C++/Java)   –  hCps://github.com/maropu/vpacker     •  前提条件:  正の歪度をもつ整数列を効率的に圧縮   –  大半が小さい値で、稀に大きな値が発生   •  ライブラリの特徴   –  少ないメモリ量で圧縮&展開   –  ILPを考慮した展開処理  -­‐  γ/δ符号と比べて速い   –  動的計画法による圧縮率の最適化   –  ヘッダファイルの読み込みのみで使用可能   8
  • 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. 近年の整数圧縮手法 ~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. vpacker  –  内部構造   •  圧縮データのバイナリフォーマット   –  前半のディスクリプタ部と圧縮したデータ部で構成   ディスクリプタ部(desc) 圧縮データ部(in) 1-byteのディスクリプタの列 圧縮された整数データ 後半の圧縮したデータが どのように格納されているかを記録 12
  • 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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
  • 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. 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. 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. その他の補助パラメータ •  -­‐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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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
  • 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. 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
  • 44. 本日のまとめ •  clang-­‐v3.2の自動ベクトル化の性能調査   –  基本的なものは自動的にベクトル化される   –  処理が複雑になるとgccに対して2~3倍程度の性能差も   •  ‘Vectorizer-­‐Friendly’はまだまだ重要   –  完全にコンパイラ任せ,というわけには現在いかない   –  256-­‐bit,  512-­‐bit,  ...とベクトル長が増えると性能差は拡大       44
  • 45. 本日のまとめ •  自動ベクトル化のためのコード規約        1.  ポインタのエイリアスは避ける             ・必要な個所では__restrict__を付ける          2.  ベクトル長の境界に合わせる                  ・__builQn_assume_aligned(X),  __aCribute__((aligned(X))の活用          3.  Loop内の手作業のinline化は避ける                ・Loop  Vectorizerに任せたほうが賢い       45