SlideShare une entreprise Scribd logo
1  sur  51
Télécharger pour lire hors ligne
Boost.SIMDによる実用的な
         SIMDアクセラレーション

Mathias Gaunard       Joël Falcou     Jean-Thierry Lapresté

                       MetaScale

                     Boostcon 2011


           翻訳 : 高橋 晶(faithandbrave@gmail.com)
コンテキスト

コンテキスト



NT2からBoost.SIMDへ
 •   昨年、我々はハイパフォーマンスな数値計算のための、Matlabライクな
     ProtoベースのライブラリであるNT2のプレゼンテーションを行った
 •   Boost.SIMDは、SIMDサブコンポーネント抽出のライブラリ
 •   GSoCプロジェクトが、レビュー準備のために今年の夏に行われる予定
 •   ここでは、どんな提案をするのかについて話す
SIMD

SIMDとは何か?



            原則
            • ひとつの命令、複数
              のレジスタ
            • ひとつのレジスタの
              NxT要素に適用された
              操作
            • 通常のALU/FPUよりN
              倍速い
SIMDの抽象化

SIMDの抽象化はなぜ必要なのか?


x86ファミリー
• MMX 64-bit float, double    PowerPCファミリー
• SSE 128-bit float           • AltiVec 128-bit int8, int16,
• SSE2 128-bit int8, int16,     int32, int64, float
• int32, int64, double        • Cell SPU 128-bit int8, int16,
• SSE3                          int32, int64, float, double
• SSSE3
• SSE4a (AMD only)
• SSE4.1
                              ARMファミリー
• SSE4.2
• AVX 256-bit float, double   • VFP 64-bit float, double
• FMA4 (AMD only)             • NEON 64-bit and 128-bit
• XOP (AMD only)                float, int8, int16, int32, int64
• FMA3
明示的なSIMD並列化

コンパイラはなぜそれをしないのか?


コンパイラはとても賢いだけ
 •   自動ベクトル化(auto vectorization)は以下のような場合にだけ起こるこ
     とができる:
     – (何者かの代わりに)メモリを扱う者が決まっている
     – コードは本来ベクトル化が可能である
 • コンパイルされた関数はベクトル化されない(libmなど)
 • コンパイラには、それが何をベクトル化することができるか判
   断できるくらいの静的な情報がいつでもあるわけではない
 • ベクトル化のための設計は、ヒューマンプロセスである


結論
 •   明確にSIMD並列性を宣言するのは、あなたのコードをベクトル化させる最
     も良い方法である
 •   このプレゼンテーションでデモンストレーションを行う
Talk Layout



1.   はじめに
2.   インタフェース
3.   SIMDとSTL
4.   SIMD仕様イディオム
5.   結論
SIMD手書き

手書きしてみる


 32ビット整数のベクトルでa * b + cする : SSE
 __m128i a, b, c, result ;
 result = _mm_mul_epi32 (a, _mm_add_epi32 (b, c));



 32ビット整数のベクトルでa * b + cする : Altivec
 __vector int a, b, c, result ;
 result = vec_cts ( vec_madd ( vec_ctf (a ,0)
                             , vec_ctf (b ,0)
                             , vec_ctf (c ,0)
                  )
                  ,0);
パック

パック抽象化


simd::pack<T>
 pack<T, N> 型TのN要素をパックするSIMDレジスタ
 pack<T>    利用可能な最適なNを自動的に使用する
 • TとT以外のパックという例外操作を除いて、それはTのように振舞う。



制約
 •   Tは基本的な算術型でなければならない。たとえば:(un)signed char,
     (unsigned) short, (unsigned) int, (unsigned) long, (unsigned) long long, float
     or double - not bool.
 •   Nは2のべき乗でなければならない
プリミティブ

パック抽象化


 演算子
 •   オーバーロード可能な全ての演算子が利用できる
 •   pack<T> × pack<T>操作だけでなくpack<T> × Tも可能
 •   型の強制と昇格の無効
     uint8_t(255) + uint8_t(1)はint(256)ではなくuint_t(0)となる

 比較
 •   ==, !=, <, <=, >=は、語彙比較(lexical comparison)を行う
 •   eq, neq, lt, gt, le, ge関数は、boolのpackを返す


 その他のプロパティ
 •   ReadOnlyRandomAccessFusionSequenceとReadOnlyRandomAccessRange
     の両方をモデル化する
 •   at_c<i>(p)もしくはp[i]をアクセスに使用できる。i番目の要素へのアクセス
     は便利だが遅い(at_cは速い)
プリミティブ

pack API




 メモリアクセス
  pack<T, N>からT*、もしくはその逆にload/storeを行うには、メモリはsizeof(T)*N
  にアライメントされていなければならない。エラー時の振る舞いは未定義


 Examples
プリミティブ

pack API



 メモリアクセス
  pack<T, N>からT*、もしくはその逆にload/storeを行うには、メモリはsizeof(T)*N
  にアライメントされていなければならない。エラー時の振る舞いは未定義

 例
  load< pack<T, N> >(p, i)はp + i*Nアライメントされたアドレスからloadされる
プリミティブ

pack API



 メモリアクセス
  pack<T, N>からT*、もしくはその逆にload/storeを行うには、メモリはsizeof(T)*N
  にアライメントされていなければならない。エラー時の振る舞いは未定義

 例
  load< pack<T, N>, Offset>(p, i)はp + i*N + Offsetアライメントされたアドレスから
  loadされる 。p + iはアライメントされていなければならない。
プリミティブ

pack API




 メモリアクセス
  pack<T, N>からT*、もしくはその逆にload/storeを行うには、メモリはsizeof(T)*N
  にアライメントされていなければならない。エラー時の振る舞いは未定義

 例
  store(p, i, pk)はp + i*Nアライメントされたアドレスでpkにstoreする
プリミティブ

proto entityとしてのpack


 論拠
 •   ほとんどのSIMD ISAはfused操作を持っている(FMA, etc...)
 •   簡単なコードを書いて最も良いパフォーマンスを得たい
 •   遅延評価が必要 : protoに助けてもらおう!



 利点
 •   全ての式や関数が、変換演算子で評価されるテンプレート式を生成する
 •   a * b + cはfma(a, b, c)にマッピングされる
     a + b * cはfma(b, c, a)にマッピングされる
     !(a < b)はis_nle(a, b)にマッピングされる
 •   拡張のための最適化システムは開かれている
プリミティブ

他の算術、ビット、ieee演算と述語



 算術演算                       ビット演算                述語
 •   saturated              •   select           •   ゼロとの比較
     arithmetic             •   andnoot, ornot   •   比較の否定
 •   float/int変換            •   popcnt           •   is_unord, is_nan,
 •   round, floor, ceil,    •   ffs                  is_invalid
     trunk                  •   ror, rol         •   is_odd, is_even,
 •   sqrt, hypot            •   rshr, rshl       •   majority
 •   average                •   twopower
 •   random
 •   min/max                IEEE
 •   rounded division and   •   ilogb, frexp
     remainder              •   ldexp
                            •   next/prev
                            •   ulpldist
プリミティブ

ReductionとSWAR演算




         Reduction                SWAR
       •   any, all               •   group / split
       •   nbtree                 •   slatetd reduction
       •   minimum/maximum,       •   cumsum
           posmin/posmax          •   sort
       •   sum
       •   product, dot product
拡張ポイント

native<T, X> : archのTに関するSIMDレジスタ。X


 セマンティクス
 •   packと似ているが、全ての演算と関数の戻り値がExpression Templateを
     返すわけではない。
 •   Xは命令ではなく使用可能な型の登録。SSEの全てのバリエーションのタグ
     だけを指定する。
 •   ライブラリを拡張するために使用されなければならないのはインタフェース
     である。

 例
 native<float, tag::sse_>      は __m128 をラップする
 native<uint8_t, tag::sse_> は __m128i をラップする
 native<double, tag::avx_>     は __m256d をラップする
 native<double, tag::altivec_> は __vector float をラップする
拡張ポイント

native<T, X> : archのTに関するSIMDレジスタ。X




 ソフトウェアフォールバック
 •   tag::none_<N>は、Nバイトサイズのレジスタによる、ソフトウェアエミュレー
     トされたSIMDアーキテクチャ
 •   満足のいくSIMDアーキテクチャが見つからない場合にフォールバックとし
     て使用する
 •   これのおかげで、コードのデグレードが汎用的なまま
 •   SIMDが見つからない場合のデフォルトのネイティブ型 :
     native<T, tag::none_<8> >
RGBをグレースケールにする

RGBをグレースケールにする



スカラバージョン
 float const *red, *green, *blue;
 float* result;
 for (std::size_t i = 0; i != height * width ; ++i)
     result[i] = 0.3f * red[i] + 0.59f * green[i] + 0.11f * blue[i];


SIMDバージョン
 std::size_t N = meta::cardinal_of<pack<float> >::value;
 for (std::size_t i = 0; i != height*width/N; ++i)
 {
     pack<float> r = load< pack<float> >(red, i);
     pack<float> g = load< pack<float> >(green, i);
     pack<float> b = load< pack<float> >(blue, i);
     pack<float> res = 0.3f * r + 0.59f * g + 0.11f * b;
     store(res, result, i);
 }
プリミティブ

簡単だが、どうすれば…




     •   …RGB or RGBAが混在していたらどうするか?
     •   …floatではなく8ビット整数だったら?

     複雑に聞こえるものは、あとで紹介する。
Talk Layout



1.   はじめに
2.   インタフェース
3.   SIMDとSTL
4.   SIMD仕様イディオム
5.   結論
論拠

演算 vs データ



 どこで/どのようにデータを格納するか
 •   SIMD演算はデータ上で動作する必要がある
 •   通常のアプローチでは、ユーザーに規定されたコンテナを強制する
 •   これは十分にジェネリックではない


 より良いアプローチ
 •   SIMD準拠アロケータ
 •   SIMDのRangeとイテレータ : CountiguousRange
 •   標準アルゴリズムのサブセットを操作するためにSIMDクラスをアダプトする
論拠

演算 vs データ



 どこで/どのようにデータを格納するか
 •   SIMD演算はデータ上で動作する必要がある
 •   通常のアプローチでは、ユーザーに規定されたコンテナを強制する
 •   これは十分にジェネリックではない


 より良いアプローチ
 •   SIMD準拠アロケータ
 •   SIMDのRangeとイテレータ : CountiguousRange
 •   標準アルゴリズムのサブセットを操作するためにSIMDクラスをアダプトする
SIMDアロケータ

SIMDアロケータ



 論拠
 •   SIMDに準拠した方法でメモリを処理するコンテナを許可する
 •   メモリのアライメントをハンドル
 •   メモリのパディングをハンドル


例
 std::vector<float, simd::allocator<float> > v(173);
 assert( simd::is_aligned(&v[0]) );
SIMDイテレータとRange

RangeからSIMD Rangeへ



 イテレータインタフェース
 •   Boost.SIMDは、simd::begin()/simd::end()を提供する
 •   SIMDイテレータはpackを返して回るイテレータ
 •   regular rangeをとり、SIMD上でイテレートする


 Examples
SIMDイテレータとRange

RangeからSIMD Rangeへ



 イテレータインタフェース
 •   Boost.SIMDは、simd::begin()/simd::end()を提供する
 •   SIMDイテレータはpackを返して回るイテレータ
 •   regular rangeをとり、SIMD上でイテレートする


 例
SIMDイテレータとRange

RangeからSIMD Rangeへ



 イテレータインタフェース
 •   Boost.SIMDは、simd::begin()/simd::end()を提供する
 •   SIMDイテレータはpackを返して回るイテレータ
 •   regular rangeをとり、SIMD上でイテレートする


 例
 std::vector<float, simd::allocator<float> > v(1024);
 pack<float> x,z;

 x = std::accumulate( simd::begin(v.begin())
                    , simd::end(v.end())
                    , z
                    );
SIMDイテレータとRange

RangeからSIMD Rangeへ



 イテレータインタフェース
 •   Boost.SIMDは、simd::begin()/simd::end()を提供する
 •   SIMDイテレータはpackを返して回るイテレータ
 •   regular rangeをとり、SIMD上でイテレートする


 例
 std::vector<float, simd::allocator<float> > v(1024);
 pack<float> x,z;

 x = boost::accumulate( simd::range(v), z );
SIMDイテレータとRange

RangeからSIMD Rangeへ



 イテレータインタフェース
 •   nativeとpackは、begin()/end()を提供する
 •   標準アルゴリズムを直接使用可能
 •   Boost.Rangeアルゴリズムを直接使用可能


 例
 pack<float> x(1, 2, 3, 4);

 float k = std::accumulate(x.begin() x.end(), 0.f );
SIMDイテレータとRange

RangeとしてのSIMD値




 全てをまとめる
 std::vector<float, simd::allocator<float> > v(1024);
 pack<float> x, z;
 float r;

 x = boost::accumulate(simd::range(v), z);
 r = std::accumulate(x.begin(), x.end(), 0.f);
SIMDイテレータとRange

RangeとしてのSIMD値




 全てをまとめる – より良いバージョン
 std::vector<float, simd::allocator<float> > v(1024);
 float r;

 r = sum(accumulate(simd::range(v), pack<float>()));
SIMDイテレータとRange

RangeとしてのSIMD値



 doubleでのstd::accumulateの高速化
SIMDイテレータとRange

RangeとしてのSIMD値



 floatでのstd::accumulateの高速化
SIMDイテレータとRange

SIMD RangeとジェネリックなSIMD/スカラーコード


 RGB2Greyに戻る
 template <class RangeIn, class RangeOut> inline void
 rgb2grey( RangeOut result, RangeIn red, RangeIn green, RangeIn blue )
 {
     typedef typename RangeIn::iterator in_iterator;
     typedef typename RangeOut::iterator iterator;
     typedef typename iterator_value< iterator >::type type;

     iterator br   =   result.begin(), er = result.end();
     in_iterator   r   = red.begin();
     in_iterator   g   = green.begin();
     in_iterator   b   = blue.begin();

     while ( br != er )
     {
         type rv = load< type     >(r, 0);
         type gv = load< type     >(g, 0);
         type bv = load< type     >(b, 0);
         type res = 0.3f * rv     + 0.59f * gv + 0.11f * bv;
         store(res, br, 0);
         br++; r++; g++; b++;
     }
 }
SIMDイテレータとRange

何が足りないか



 統合されたSIMDサポート
 •   ほとんどの標準アルゴリズムが、一息で実行できるように特殊化されるべ
     きだ
 •   simd(r)のようなRangeアダプタができるだろうか?
 •   load<T, N>を使用したshifted Rangeのサポート


 いくつかのSIMDによる頭の体操
 •   SIMD find?
 •   SIMD sort?
 •   copyのような高速化?
Talk Layout



1.   はじめに
2.   インタフェース
3.   SIMDとSTL
4.   SIMD仕様イディオム
5.   結論
条件ハンドリング

SIMDでの真理値




問題
 pack<float> x(1 ,2 ,3 ,4);
 pack<float> c(2.5);

 cout << lt(x,c) << endl;
条件ハンドリング

SIMDでの真理値




問題
 pack<float> x(1 ,2 ,3 ,4);
 pack<float> c(2.5);

 cout << lt(x,c) << endl;
 (( Nan Nan 0 0 ))
条件ハンドリング

SIMDでの真理値




問題
 pack<float> x(1 ,2 ,3 ,4);
 pack<float> c(2.5);

 cout << lt(x,c) << endl;
 (( Nan Nan 0 0 ))



解決策
 Tに適切なtrue値w/rを返すTrue<T>()
 Tに適切なfalse値w/rを返すFalse<T>()
条件ハンドリング

SIMDでの条件式




例
 // スカラーコード
 if( x > 4 )
     y = 2*x;
 else
     z = 1.f/x;

 // SIMD code
 // ???
条件ハンドリング

SIMDでの条件式




例
 // スカラーコード
 if( x > 4 )
     y = 2*x;
 else
     z = 1.f/x;

 // SIMD code
 y = where( gt(x, 4), 2*x, y);
 z = where( gt(x, 4), z, 1.f/x);
シフトした読み込み

動機
シフトした読み込み

着々と進んでいる…
シフトした読み込み

ベクトルの解決策
シフトした読み込み

ベクトルの解決策


SIMD/スカラーバージョン
 template < class RangeIn, class RangeOut >
 inline void average( RangeOut result, RangeIn input )
 {
     typedef typename RangeIn::iterator in_iterator;
     typedef typename RangeOut::iterator iterator;
     typedef typename iterator_value< iterator >::type type;

     iterator br = result.begin(), er = result.end();
     in_iterator data = input.begin();

     br++; er--;
     while ( br != er )
     {
         type xm1 = load<type, -1>(data, i);
         type x   = load<type>(data, i);
         type xp1 = load<type, +1>(data, i);
         store(res, i, 0) = 1.f/3 * (xm1 + x + xp1);
     }
 }
昇格と飽和(Promotion and Saturation)

RGB2Greyへ戻る




 8ビットRGB
 static const std::size_t N = meta::cardinal_of< pack<uint8_t> >::value;
 for (std::size_t i = 0; i != height*width/N; ++i)
 {
     pack<uint8_t> r = load< pack<uint8_t> >(red, i);
     pack<uint8_t> g = load< pack<uint8_t> >(green, i);
     pack<uint8_t> b = load< pack<uint8_t> >(blue, i);
     pack<uint8_t> res = uint8_t(77) * r / uint8_t(255) + uint8_t(150)
                       * g / uint8_t(255) + uint8_t(28) * b / uint8_t(255);
     store(res, result, i);
 }
昇格と飽和(Promotion and Saturation)

RGB2Greyへ戻る




 packの昇格
 uint16_t   r_coeff =   77;
 uint16_t   g_coeff =   150;
 uint16_t   b_coeff =   28;
 uint16_t   div_coeff   = 255;

 pack<uint16_t> r1, r2, g1, g2, b1, b2;
 tie(r1, r2) = split(r);
 tie(g1, g2) = split(g);
 tie(b1, b2) = split(b);

 pack<uint16_t> res1 = (r_coeff * r1 + g_coeff * g1 + b_coeff * b1) / div_coeff;
 pack<uint16_t> res2 = (r_coeff * r2 + g_coeff * g2 + b_coeff * b2) / div_coeff;
 pack<uint8_t> res = group(res1, res2);
Talk Layout



1.   はじめに
2.   インタフェース
3.   SIMDとSTL
4.   SIMD仕様イディオム
5.   結論
Boost.SIMDの概要

proto entityとしてのpack




 我々の目標
 •   SIMDプログラミングに、使いやすい状態をもたらす
 •   もしboost.atomicがあったら、boost.simdをどうするか?
 •   C++の残りのすばらしいものを使って、さらに魅力的にする



 我々が達成したいこと
 •   NT2で学んだことの活用する
 •   パフォーマンス用語のいくつかの影響を実証する
 •   スカラーを使用する場合と同じくらい単純なSIMD命令にする
今後の活動




Google Summer of Code 2011
•   混乱をクリーンナップし、boostifyにする
•   STL/Boostとの互換性を向上させる
•    募集:このライブラリを実際に活用したアプリケーション
Thanks for your attension

Contenu connexe

Tendances

ARM CPUにおけるSIMDを用いた高速計算入門
ARM CPUにおけるSIMDを用いた高速計算入門ARM CPUにおけるSIMDを用いた高速計算入門
ARM CPUにおけるSIMDを用いた高速計算入門Fixstars Corporation
 
Halide による画像処理プログラミング入門
Halide による画像処理プログラミング入門Halide による画像処理プログラミング入門
Halide による画像処理プログラミング入門Fixstars Corporation
 
Xbyakの紹介とその周辺
Xbyakの紹介とその周辺Xbyakの紹介とその周辺
Xbyakの紹介とその周辺MITSUNARI Shigeo
 
いまさら聞けない!CUDA高速化入門
いまさら聞けない!CUDA高速化入門いまさら聞けない!CUDA高速化入門
いまさら聞けない!CUDA高速化入門Fixstars Corporation
 
Master Canary Forging: 新しいスタックカナリア回避手法の提案 by 小池 悠生 - CODE BLUE 2015
Master Canary Forging: 新しいスタックカナリア回避手法の提案 by 小池 悠生 - CODE BLUE 2015Master Canary Forging: 新しいスタックカナリア回避手法の提案 by 小池 悠生 - CODE BLUE 2015
Master Canary Forging: 新しいスタックカナリア回避手法の提案 by 小池 悠生 - CODE BLUE 2015CODE BLUE
 
LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)
LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)
LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)Takeshi Yamamuro
 
競技プログラミングにおけるコードの書き方とその利便性
競技プログラミングにおけるコードの書き方とその利便性競技プログラミングにおけるコードの書き方とその利便性
競技プログラミングにおけるコードの書き方とその利便性Hibiki Yamashiro
 
RSA暗号運用でやってはいけない n のこと #ssmjp
RSA暗号運用でやってはいけない n のこと #ssmjpRSA暗号運用でやってはいけない n のこと #ssmjp
RSA暗号運用でやってはいけない n のこと #ssmjpsonickun
 
多倍長整数の乗算と高速フーリエ変換
多倍長整数の乗算と高速フーリエ変換多倍長整数の乗算と高速フーリエ変換
多倍長整数の乗算と高速フーリエ変換京大 マイコンクラブ
 
WebAssembly向け多倍長演算の実装
WebAssembly向け多倍長演算の実装WebAssembly向け多倍長演算の実装
WebAssembly向け多倍長演算の実装MITSUNARI Shigeo
 
constexpr関数はコンパイル時処理。これはいい。実行時が霞んで見える。cpuの嬌声が聞こえてきそうだ
constexpr関数はコンパイル時処理。これはいい。実行時が霞んで見える。cpuの嬌声が聞こえてきそうだconstexpr関数はコンパイル時処理。これはいい。実行時が霞んで見える。cpuの嬌声が聞こえてきそうだ
constexpr関数はコンパイル時処理。これはいい。実行時が霞んで見える。cpuの嬌声が聞こえてきそうだGenya Murakami
 
組み込みでこそC++を使う10の理由
組み込みでこそC++を使う10の理由組み込みでこそC++を使う10の理由
組み込みでこそC++を使う10の理由kikairoya
 
中3女子でもわかる constexpr
中3女子でもわかる constexpr中3女子でもわかる constexpr
中3女子でもわかる constexprGenya Murakami
 
すごい constexpr たのしくレイトレ!
すごい constexpr たのしくレイトレ!すごい constexpr たのしくレイトレ!
すごい constexpr たのしくレイトレ!Genya Murakami
 
条件分岐とcmovとmaxps
条件分岐とcmovとmaxps条件分岐とcmovとmaxps
条件分岐とcmovとmaxpsMITSUNARI Shigeo
 
C/C++プログラマのための開発ツール
C/C++プログラマのための開発ツールC/C++プログラマのための開発ツール
C/C++プログラマのための開発ツールMITSUNARI Shigeo
 

Tendances (20)

ARM CPUにおけるSIMDを用いた高速計算入門
ARM CPUにおけるSIMDを用いた高速計算入門ARM CPUにおけるSIMDを用いた高速計算入門
ARM CPUにおけるSIMDを用いた高速計算入門
 
Halide による画像処理プログラミング入門
Halide による画像処理プログラミング入門Halide による画像処理プログラミング入門
Halide による画像処理プログラミング入門
 
Xbyakの紹介とその周辺
Xbyakの紹介とその周辺Xbyakの紹介とその周辺
Xbyakの紹介とその周辺
 
いまさら聞けない!CUDA高速化入門
いまさら聞けない!CUDA高速化入門いまさら聞けない!CUDA高速化入門
いまさら聞けない!CUDA高速化入門
 
Master Canary Forging: 新しいスタックカナリア回避手法の提案 by 小池 悠生 - CODE BLUE 2015
Master Canary Forging: 新しいスタックカナリア回避手法の提案 by 小池 悠生 - CODE BLUE 2015Master Canary Forging: 新しいスタックカナリア回避手法の提案 by 小池 悠生 - CODE BLUE 2015
Master Canary Forging: 新しいスタックカナリア回避手法の提案 by 小池 悠生 - CODE BLUE 2015
 
フラグを愛でる
フラグを愛でるフラグを愛でる
フラグを愛でる
 
LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)
LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)
LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)
 
競技プログラミングにおけるコードの書き方とその利便性
競技プログラミングにおけるコードの書き方とその利便性競技プログラミングにおけるコードの書き方とその利便性
競技プログラミングにおけるコードの書き方とその利便性
 
RSA暗号運用でやってはいけない n のこと #ssmjp
RSA暗号運用でやってはいけない n のこと #ssmjpRSA暗号運用でやってはいけない n のこと #ssmjp
RSA暗号運用でやってはいけない n のこと #ssmjp
 
多倍長整数の乗算と高速フーリエ変換
多倍長整数の乗算と高速フーリエ変換多倍長整数の乗算と高速フーリエ変換
多倍長整数の乗算と高速フーリエ変換
 
WebAssembly向け多倍長演算の実装
WebAssembly向け多倍長演算の実装WebAssembly向け多倍長演算の実装
WebAssembly向け多倍長演算の実装
 
constexpr関数はコンパイル時処理。これはいい。実行時が霞んで見える。cpuの嬌声が聞こえてきそうだ
constexpr関数はコンパイル時処理。これはいい。実行時が霞んで見える。cpuの嬌声が聞こえてきそうだconstexpr関数はコンパイル時処理。これはいい。実行時が霞んで見える。cpuの嬌声が聞こえてきそうだ
constexpr関数はコンパイル時処理。これはいい。実行時が霞んで見える。cpuの嬌声が聞こえてきそうだ
 
組み込みでこそC++を使う10の理由
組み込みでこそC++を使う10の理由組み込みでこそC++を使う10の理由
組み込みでこそC++を使う10の理由
 
明日使えないすごいビット演算
明日使えないすごいビット演算明日使えないすごいビット演算
明日使えないすごいビット演算
 
Glibc malloc internal
Glibc malloc internalGlibc malloc internal
Glibc malloc internal
 
中3女子でもわかる constexpr
中3女子でもわかる constexpr中3女子でもわかる constexpr
中3女子でもわかる constexpr
 
すごい constexpr たのしくレイトレ!
すごい constexpr たのしくレイトレ!すごい constexpr たのしくレイトレ!
すごい constexpr たのしくレイトレ!
 
llvm入門
llvm入門llvm入門
llvm入門
 
条件分岐とcmovとmaxps
条件分岐とcmovとmaxps条件分岐とcmovとmaxps
条件分岐とcmovとmaxps
 
C/C++プログラマのための開発ツール
C/C++プログラマのための開発ツールC/C++プログラマのための開発ツール
C/C++プログラマのための開発ツール
 

En vedette

プログラムの処方箋~健康なコードと病んだコード
プログラムの処方箋~健康なコードと病んだコードプログラムの処方箋~健康なコードと病んだコード
プログラムの処方箋~健康なコードと病んだコードShigenori Sagawa
 
Gura プログラミング言語の紹介
Gura プログラミング言語の紹介Gura プログラミング言語の紹介
Gura プログラミング言語の紹介Yutaka Saito
 
マルチコアのプログラミング技法 -- OpenCLとWebCL
マルチコアのプログラミング技法 -- OpenCLとWebCLマルチコアのプログラミング技法 -- OpenCLとWebCL
マルチコアのプログラミング技法 -- OpenCLとWebCLmaruyama097
 
正規表現に潜む対称性 〜等式公理による等価性判定〜
正規表現に潜む対称性 〜等式公理による等価性判定〜正規表現に潜む対称性 〜等式公理による等価性判定〜
正規表現に潜む対称性 〜等式公理による等価性判定〜Ryoma Sin'ya
 
エンジニアにMacを薦める理由
エンジニアにMacを薦める理由エンジニアにMacを薦める理由
エンジニアにMacを薦める理由Hiroyuki Kusu
 
Editor縮小のススメ
Editor縮小のススメEditor縮小のススメ
Editor縮小のススメNobukazu Hanada
 
GPUによる多倍長整数乗算の高速化手法の提案
GPUによる多倍長整数乗算の高速化手法の提案GPUによる多倍長整数乗算の高速化手法の提案
GPUによる多倍長整数乗算の高速化手法の提案Koji Kitano
 
私がお世話になった技術書たち
私がお世話になった技術書たち私がお世話になった技術書たち
私がお世話になった技術書たち法林浩之
 
UNIXことはじめ
UNIXことはじめUNIXことはじめ
UNIXことはじめTomoya Miwa
 
SIMDで整数除算
SIMDで整数除算SIMDで整数除算
SIMDで整数除算shobomaru
 
コードレビューの文化を手探りで作っていった話
コードレビューの文化を手探りで作っていった話コードレビューの文化を手探りで作っていった話
コードレビューの文化を手探りで作っていった話yasuhiro kiyota
 
Unixコマンド入門
Unixコマンド入門Unixコマンド入門
Unixコマンド入門Satosi Sakai
 
Lisp Meet Up #25, 8-bit PIC マイコン用ネイティブコンパイラの作成
Lisp Meet Up #25, 8-bit PIC マイコン用ネイティブコンパイラの作成Lisp Meet Up #25, 8-bit PIC マイコン用ネイティブコンパイラの作成
Lisp Meet Up #25, 8-bit PIC マイコン用ネイティブコンパイラの作成masayukitakagi
 
Xeonphiハッカソンでexpを作ってみた
Xeonphiハッカソンでexpを作ってみたXeonphiハッカソンでexpを作ってみた
Xeonphiハッカソンでexpを作ってみたMITSUNARI Shigeo
 
Unix 基礎
Unix 基礎Unix 基礎
Unix 基礎Sho A
 
C++ Template Metaprogramming
C++ Template MetaprogrammingC++ Template Metaprogramming
C++ Template MetaprogrammingAkira Takahashi
 
Template Meta Programming入門から応用まで
Template Meta Programming入門から応用までTemplate Meta Programming入門から応用まで
Template Meta Programming入門から応用までyoshihikoozaki5
 
Unixカーネルの設計 7 プロセスの制御
Unixカーネルの設計 7 プロセスの制御Unixカーネルの設計 7 プロセスの制御
Unixカーネルの設計 7 プロセスの制御Norito Agetsuma
 

En vedette (20)

プログラムの処方箋~健康なコードと病んだコード
プログラムの処方箋~健康なコードと病んだコードプログラムの処方箋~健康なコードと病んだコード
プログラムの処方箋~健康なコードと病んだコード
 
Boost Fusion Library
Boost Fusion LibraryBoost Fusion Library
Boost Fusion Library
 
Gura プログラミング言語の紹介
Gura プログラミング言語の紹介Gura プログラミング言語の紹介
Gura プログラミング言語の紹介
 
マルチコアのプログラミング技法 -- OpenCLとWebCL
マルチコアのプログラミング技法 -- OpenCLとWebCLマルチコアのプログラミング技法 -- OpenCLとWebCL
マルチコアのプログラミング技法 -- OpenCLとWebCL
 
正規表現に潜む対称性 〜等式公理による等価性判定〜
正規表現に潜む対称性 〜等式公理による等価性判定〜正規表現に潜む対称性 〜等式公理による等価性判定〜
正規表現に潜む対称性 〜等式公理による等価性判定〜
 
エンジニアにMacを薦める理由
エンジニアにMacを薦める理由エンジニアにMacを薦める理由
エンジニアにMacを薦める理由
 
Editor縮小のススメ
Editor縮小のススメEditor縮小のススメ
Editor縮小のススメ
 
GPUによる多倍長整数乗算の高速化手法の提案
GPUによる多倍長整数乗算の高速化手法の提案GPUによる多倍長整数乗算の高速化手法の提案
GPUによる多倍長整数乗算の高速化手法の提案
 
私がお世話になった技術書たち
私がお世話になった技術書たち私がお世話になった技術書たち
私がお世話になった技術書たち
 
UNIXことはじめ
UNIXことはじめUNIXことはじめ
UNIXことはじめ
 
SIMDで整数除算
SIMDで整数除算SIMDで整数除算
SIMDで整数除算
 
コードレビューの文化を手探りで作っていった話
コードレビューの文化を手探りで作っていった話コードレビューの文化を手探りで作っていった話
コードレビューの文化を手探りで作っていった話
 
Unixコマンド入門
Unixコマンド入門Unixコマンド入門
Unixコマンド入門
 
Lisp Meet Up #25, 8-bit PIC マイコン用ネイティブコンパイラの作成
Lisp Meet Up #25, 8-bit PIC マイコン用ネイティブコンパイラの作成Lisp Meet Up #25, 8-bit PIC マイコン用ネイティブコンパイラの作成
Lisp Meet Up #25, 8-bit PIC マイコン用ネイティブコンパイラの作成
 
Xeonphiハッカソンでexpを作ってみた
Xeonphiハッカソンでexpを作ってみたXeonphiハッカソンでexpを作ってみた
Xeonphiハッカソンでexpを作ってみた
 
PFI Seminar 2010/02/18
PFI Seminar 2010/02/18PFI Seminar 2010/02/18
PFI Seminar 2010/02/18
 
Unix 基礎
Unix 基礎Unix 基礎
Unix 基礎
 
C++ Template Metaprogramming
C++ Template MetaprogrammingC++ Template Metaprogramming
C++ Template Metaprogramming
 
Template Meta Programming入門から応用まで
Template Meta Programming入門から応用までTemplate Meta Programming入門から応用まで
Template Meta Programming入門から応用まで
 
Unixカーネルの設計 7 プロセスの制御
Unixカーネルの設計 7 プロセスの制御Unixカーネルの設計 7 プロセスの制御
Unixカーネルの設計 7 プロセスの制御
 

Similaire à Boost.SIMD

GPUが100倍速いという神話をぶち殺せたらいいな ver.2013
GPUが100倍速いという神話をぶち殺せたらいいな ver.2013GPUが100倍速いという神話をぶち殺せたらいいな ver.2013
GPUが100倍速いという神話をぶち殺せたらいいな ver.2013Ryo Sakamoto
 
Dalvik仮想マシンのアーキテクチャ 改訂版
Dalvik仮想マシンのアーキテクチャ 改訂版Dalvik仮想マシンのアーキテクチャ 改訂版
Dalvik仮想マシンのアーキテクチャ 改訂版Takuya Matsunaga
 
Cvim saisentan 半精度浮動小数点数 half
Cvim saisentan 半精度浮動小数点数 halfCvim saisentan 半精度浮動小数点数 half
Cvim saisentan 半精度浮動小数点数 halftomoaki0705
 
Python physicalcomputing
Python physicalcomputingPython physicalcomputing
Python physicalcomputingNoboru Irieda
 
Shadow gunのサンプルから学べるモバイル最適化
Shadow gunのサンプルから学べるモバイル最適化Shadow gunのサンプルから学べるモバイル最適化
Shadow gunのサンプルから学べるモバイル最適化Katsutoshi Makino
 
HaskellではじめるCortex-M3組込みプログラミング
HaskellではじめるCortex-M3組込みプログラミングHaskellではじめるCortex-M3組込みプログラミング
HaskellではじめるCortex-M3組込みプログラミングKiwamu Okabe
 
Node.jsでつくるNode.js ミニインタープリター&コンパイラー
Node.jsでつくるNode.js ミニインタープリター&コンパイラーNode.jsでつくるNode.js ミニインタープリター&コンパイラー
Node.jsでつくるNode.js ミニインタープリター&コンパイラーmganeko
 
C# 7.2 with .NET Core 2.1
C# 7.2 with .NET Core 2.1C# 7.2 with .NET Core 2.1
C# 7.2 with .NET Core 2.1信之 岩永
 
PHP AST 徹底解説
PHP AST 徹底解説PHP AST 徹底解説
PHP AST 徹底解説do_aki
 
C++11概要 ライブラリ編
C++11概要 ライブラリ編C++11概要 ライブラリ編
C++11概要 ライブラリ編egtra
 
Javaセキュアコーディングセミナー東京第2回講義
Javaセキュアコーディングセミナー東京第2回講義Javaセキュアコーディングセミナー東京第2回講義
Javaセキュアコーディングセミナー東京第2回講義JPCERT Coordination Center
 
x86とコンテキストスイッチ
x86とコンテキストスイッチx86とコンテキストスイッチ
x86とコンテキストスイッチMasami Ichikawa
 
C++コミュニティーの中心でC++をDISる
C++コミュニティーの中心でC++をDISるC++コミュニティーの中心でC++をDISる
C++コミュニティーの中心でC++をDISるHideyuki Tanaka
 
Write good parser in perl
Write good parser in perlWrite good parser in perl
Write good parser in perlJiro Nishiguchi
 
ROP Illmatic: Exploring Universal ROP on glibc x86-64 (ja)
ROP Illmatic: Exploring Universal ROP on glibc x86-64 (ja)ROP Illmatic: Exploring Universal ROP on glibc x86-64 (ja)
ROP Illmatic: Exploring Universal ROP on glibc x86-64 (ja)inaz2
 
Polyphony の行く末(2018/3/3)
Polyphony の行く末(2018/3/3)Polyphony の行く末(2018/3/3)
Polyphony の行く末(2018/3/3)ryos36
 

Similaire à Boost.SIMD (20)

GPUが100倍速いという神話をぶち殺せたらいいな ver.2013
GPUが100倍速いという神話をぶち殺せたらいいな ver.2013GPUが100倍速いという神話をぶち殺せたらいいな ver.2013
GPUが100倍速いという神話をぶち殺せたらいいな ver.2013
 
Dalvik仮想マシンのアーキテクチャ 改訂版
Dalvik仮想マシンのアーキテクチャ 改訂版Dalvik仮想マシンのアーキテクチャ 改訂版
Dalvik仮想マシンのアーキテクチャ 改訂版
 
Prosym2012
Prosym2012Prosym2012
Prosym2012
 
Cvim saisentan 半精度浮動小数点数 half
Cvim saisentan 半精度浮動小数点数 halfCvim saisentan 半精度浮動小数点数 half
Cvim saisentan 半精度浮動小数点数 half
 
HPC Phys-20201203
HPC Phys-20201203HPC Phys-20201203
HPC Phys-20201203
 
Python physicalcomputing
Python physicalcomputingPython physicalcomputing
Python physicalcomputing
 
Shadow gunのサンプルから学べるモバイル最適化
Shadow gunのサンプルから学べるモバイル最適化Shadow gunのサンプルから学べるモバイル最適化
Shadow gunのサンプルから学べるモバイル最適化
 
boost tour 1.48.0 all
boost tour 1.48.0 allboost tour 1.48.0 all
boost tour 1.48.0 all
 
HaskellではじめるCortex-M3組込みプログラミング
HaskellではじめるCortex-M3組込みプログラミングHaskellではじめるCortex-M3組込みプログラミング
HaskellではじめるCortex-M3組込みプログラミング
 
Node.jsでつくるNode.js ミニインタープリター&コンパイラー
Node.jsでつくるNode.js ミニインタープリター&コンパイラーNode.jsでつくるNode.js ミニインタープリター&コンパイラー
Node.jsでつくるNode.js ミニインタープリター&コンパイラー
 
C# 7.2 with .NET Core 2.1
C# 7.2 with .NET Core 2.1C# 7.2 with .NET Core 2.1
C# 7.2 with .NET Core 2.1
 
PHP AST 徹底解説
PHP AST 徹底解説PHP AST 徹底解説
PHP AST 徹底解説
 
C++11概要 ライブラリ編
C++11概要 ライブラリ編C++11概要 ライブラリ編
C++11概要 ライブラリ編
 
Javaセキュアコーディングセミナー東京第2回講義
Javaセキュアコーディングセミナー東京第2回講義Javaセキュアコーディングセミナー東京第2回講義
Javaセキュアコーディングセミナー東京第2回講義
 
Boost Tour 1.50.0 All
Boost Tour 1.50.0 AllBoost Tour 1.50.0 All
Boost Tour 1.50.0 All
 
x86とコンテキストスイッチ
x86とコンテキストスイッチx86とコンテキストスイッチ
x86とコンテキストスイッチ
 
C++コミュニティーの中心でC++をDISる
C++コミュニティーの中心でC++をDISるC++コミュニティーの中心でC++をDISる
C++コミュニティーの中心でC++をDISる
 
Write good parser in perl
Write good parser in perlWrite good parser in perl
Write good parser in perl
 
ROP Illmatic: Exploring Universal ROP on glibc x86-64 (ja)
ROP Illmatic: Exploring Universal ROP on glibc x86-64 (ja)ROP Illmatic: Exploring Universal ROP on glibc x86-64 (ja)
ROP Illmatic: Exploring Universal ROP on glibc x86-64 (ja)
 
Polyphony の行く末(2018/3/3)
Polyphony の行く末(2018/3/3)Polyphony の行く末(2018/3/3)
Polyphony の行く末(2018/3/3)
 

Plus de Akira Takahashi (20)

Cpp20 overview language features
Cpp20 overview language featuresCpp20 overview language features
Cpp20 overview language features
 
Cppmix 02
Cppmix 02Cppmix 02
Cppmix 02
 
Cppmix 01
Cppmix 01Cppmix 01
Cppmix 01
 
Modern C++ Learning
Modern C++ LearningModern C++ Learning
Modern C++ Learning
 
cpprefjp documentation
cpprefjp documentationcpprefjp documentation
cpprefjp documentation
 
C++1z draft
C++1z draftC++1z draft
C++1z draft
 
Boost tour 1_61_0 merge
Boost tour 1_61_0 mergeBoost tour 1_61_0 merge
Boost tour 1_61_0 merge
 
Boost tour 1_61_0
Boost tour 1_61_0Boost tour 1_61_0
Boost tour 1_61_0
 
error handling using expected
error handling using expectederror handling using expected
error handling using expected
 
Boost tour 1.60.0 merge
Boost tour 1.60.0 mergeBoost tour 1.60.0 merge
Boost tour 1.60.0 merge
 
Boost tour 1.60.0
Boost tour 1.60.0Boost tour 1.60.0
Boost tour 1.60.0
 
Boost container feature
Boost container featureBoost container feature
Boost container feature
 
Boost Tour 1_58_0 merge
Boost Tour 1_58_0 mergeBoost Tour 1_58_0 merge
Boost Tour 1_58_0 merge
 
Boost Tour 1_58_0
Boost Tour 1_58_0Boost Tour 1_58_0
Boost Tour 1_58_0
 
C++14 solve explicit_default_constructor
C++14 solve explicit_default_constructorC++14 solve explicit_default_constructor
C++14 solve explicit_default_constructor
 
C++14 enum hash
C++14 enum hashC++14 enum hash
C++14 enum hash
 
Multi paradigm design
Multi paradigm designMulti paradigm design
Multi paradigm design
 
Start Concurrent
Start ConcurrentStart Concurrent
Start Concurrent
 
Programmer mind
Programmer mindProgrammer mind
Programmer mind
 
Boost.Study 14 Opening
Boost.Study 14 OpeningBoost.Study 14 Opening
Boost.Study 14 Opening
 

Boost.SIMD

  • 1. Boost.SIMDによる実用的な SIMDアクセラレーション Mathias Gaunard Joël Falcou Jean-Thierry Lapresté MetaScale Boostcon 2011 翻訳 : 高橋 晶(faithandbrave@gmail.com)
  • 2. コンテキスト コンテキスト NT2からBoost.SIMDへ • 昨年、我々はハイパフォーマンスな数値計算のための、Matlabライクな ProtoベースのライブラリであるNT2のプレゼンテーションを行った • Boost.SIMDは、SIMDサブコンポーネント抽出のライブラリ • GSoCプロジェクトが、レビュー準備のために今年の夏に行われる予定 • ここでは、どんな提案をするのかについて話す
  • 3. SIMD SIMDとは何か? 原則 • ひとつの命令、複数 のレジスタ • ひとつのレジスタの NxT要素に適用された 操作 • 通常のALU/FPUよりN 倍速い
  • 4. SIMDの抽象化 SIMDの抽象化はなぜ必要なのか? x86ファミリー • MMX 64-bit float, double PowerPCファミリー • SSE 128-bit float • AltiVec 128-bit int8, int16, • SSE2 128-bit int8, int16, int32, int64, float • int32, int64, double • Cell SPU 128-bit int8, int16, • SSE3 int32, int64, float, double • SSSE3 • SSE4a (AMD only) • SSE4.1 ARMファミリー • SSE4.2 • AVX 256-bit float, double • VFP 64-bit float, double • FMA4 (AMD only) • NEON 64-bit and 128-bit • XOP (AMD only) float, int8, int16, int32, int64 • FMA3
  • 5. 明示的なSIMD並列化 コンパイラはなぜそれをしないのか? コンパイラはとても賢いだけ • 自動ベクトル化(auto vectorization)は以下のような場合にだけ起こるこ とができる: – (何者かの代わりに)メモリを扱う者が決まっている – コードは本来ベクトル化が可能である • コンパイルされた関数はベクトル化されない(libmなど) • コンパイラには、それが何をベクトル化することができるか判 断できるくらいの静的な情報がいつでもあるわけではない • ベクトル化のための設計は、ヒューマンプロセスである 結論 • 明確にSIMD並列性を宣言するのは、あなたのコードをベクトル化させる最 も良い方法である • このプレゼンテーションでデモンストレーションを行う
  • 6. Talk Layout 1. はじめに 2. インタフェース 3. SIMDとSTL 4. SIMD仕様イディオム 5. 結論
  • 7. SIMD手書き 手書きしてみる 32ビット整数のベクトルでa * b + cする : SSE __m128i a, b, c, result ; result = _mm_mul_epi32 (a, _mm_add_epi32 (b, c)); 32ビット整数のベクトルでa * b + cする : Altivec __vector int a, b, c, result ; result = vec_cts ( vec_madd ( vec_ctf (a ,0) , vec_ctf (b ,0) , vec_ctf (c ,0) ) ,0);
  • 8. パック パック抽象化 simd::pack<T> pack<T, N> 型TのN要素をパックするSIMDレジスタ pack<T> 利用可能な最適なNを自動的に使用する • TとT以外のパックという例外操作を除いて、それはTのように振舞う。 制約 • Tは基本的な算術型でなければならない。たとえば:(un)signed char, (unsigned) short, (unsigned) int, (unsigned) long, (unsigned) long long, float or double - not bool. • Nは2のべき乗でなければならない
  • 9. プリミティブ パック抽象化 演算子 • オーバーロード可能な全ての演算子が利用できる • pack<T> × pack<T>操作だけでなくpack<T> × Tも可能 • 型の強制と昇格の無効 uint8_t(255) + uint8_t(1)はint(256)ではなくuint_t(0)となる 比較 • ==, !=, <, <=, >=は、語彙比較(lexical comparison)を行う • eq, neq, lt, gt, le, ge関数は、boolのpackを返す その他のプロパティ • ReadOnlyRandomAccessFusionSequenceとReadOnlyRandomAccessRange の両方をモデル化する • at_c<i>(p)もしくはp[i]をアクセスに使用できる。i番目の要素へのアクセス は便利だが遅い(at_cは速い)
  • 10. プリミティブ pack API メモリアクセス pack<T, N>からT*、もしくはその逆にload/storeを行うには、メモリはsizeof(T)*N にアライメントされていなければならない。エラー時の振る舞いは未定義 Examples
  • 11. プリミティブ pack API メモリアクセス pack<T, N>からT*、もしくはその逆にload/storeを行うには、メモリはsizeof(T)*N にアライメントされていなければならない。エラー時の振る舞いは未定義 例 load< pack<T, N> >(p, i)はp + i*Nアライメントされたアドレスからloadされる
  • 12. プリミティブ pack API メモリアクセス pack<T, N>からT*、もしくはその逆にload/storeを行うには、メモリはsizeof(T)*N にアライメントされていなければならない。エラー時の振る舞いは未定義 例 load< pack<T, N>, Offset>(p, i)はp + i*N + Offsetアライメントされたアドレスから loadされる 。p + iはアライメントされていなければならない。
  • 13. プリミティブ pack API メモリアクセス pack<T, N>からT*、もしくはその逆にload/storeを行うには、メモリはsizeof(T)*N にアライメントされていなければならない。エラー時の振る舞いは未定義 例 store(p, i, pk)はp + i*Nアライメントされたアドレスでpkにstoreする
  • 14. プリミティブ proto entityとしてのpack 論拠 • ほとんどのSIMD ISAはfused操作を持っている(FMA, etc...) • 簡単なコードを書いて最も良いパフォーマンスを得たい • 遅延評価が必要 : protoに助けてもらおう! 利点 • 全ての式や関数が、変換演算子で評価されるテンプレート式を生成する • a * b + cはfma(a, b, c)にマッピングされる a + b * cはfma(b, c, a)にマッピングされる !(a < b)はis_nle(a, b)にマッピングされる • 拡張のための最適化システムは開かれている
  • 15. プリミティブ 他の算術、ビット、ieee演算と述語 算術演算 ビット演算 述語 • saturated • select • ゼロとの比較 arithmetic • andnoot, ornot • 比較の否定 • float/int変換 • popcnt • is_unord, is_nan, • round, floor, ceil, • ffs is_invalid trunk • ror, rol • is_odd, is_even, • sqrt, hypot • rshr, rshl • majority • average • twopower • random • min/max IEEE • rounded division and • ilogb, frexp remainder • ldexp • next/prev • ulpldist
  • 16. プリミティブ ReductionとSWAR演算 Reduction SWAR • any, all • group / split • nbtree • slatetd reduction • minimum/maximum, • cumsum posmin/posmax • sort • sum • product, dot product
  • 17. 拡張ポイント native<T, X> : archのTに関するSIMDレジスタ。X セマンティクス • packと似ているが、全ての演算と関数の戻り値がExpression Templateを 返すわけではない。 • Xは命令ではなく使用可能な型の登録。SSEの全てのバリエーションのタグ だけを指定する。 • ライブラリを拡張するために使用されなければならないのはインタフェース である。 例 native<float, tag::sse_> は __m128 をラップする native<uint8_t, tag::sse_> は __m128i をラップする native<double, tag::avx_> は __m256d をラップする native<double, tag::altivec_> は __vector float をラップする
  • 18. 拡張ポイント native<T, X> : archのTに関するSIMDレジスタ。X ソフトウェアフォールバック • tag::none_<N>は、Nバイトサイズのレジスタによる、ソフトウェアエミュレー トされたSIMDアーキテクチャ • 満足のいくSIMDアーキテクチャが見つからない場合にフォールバックとし て使用する • これのおかげで、コードのデグレードが汎用的なまま • SIMDが見つからない場合のデフォルトのネイティブ型 : native<T, tag::none_<8> >
  • 19. RGBをグレースケールにする RGBをグレースケールにする スカラバージョン float const *red, *green, *blue; float* result; for (std::size_t i = 0; i != height * width ; ++i) result[i] = 0.3f * red[i] + 0.59f * green[i] + 0.11f * blue[i]; SIMDバージョン std::size_t N = meta::cardinal_of<pack<float> >::value; for (std::size_t i = 0; i != height*width/N; ++i) { pack<float> r = load< pack<float> >(red, i); pack<float> g = load< pack<float> >(green, i); pack<float> b = load< pack<float> >(blue, i); pack<float> res = 0.3f * r + 0.59f * g + 0.11f * b; store(res, result, i); }
  • 20. プリミティブ 簡単だが、どうすれば… • …RGB or RGBAが混在していたらどうするか? • …floatではなく8ビット整数だったら? 複雑に聞こえるものは、あとで紹介する。
  • 21. Talk Layout 1. はじめに 2. インタフェース 3. SIMDとSTL 4. SIMD仕様イディオム 5. 結論
  • 22. 論拠 演算 vs データ どこで/どのようにデータを格納するか • SIMD演算はデータ上で動作する必要がある • 通常のアプローチでは、ユーザーに規定されたコンテナを強制する • これは十分にジェネリックではない より良いアプローチ • SIMD準拠アロケータ • SIMDのRangeとイテレータ : CountiguousRange • 標準アルゴリズムのサブセットを操作するためにSIMDクラスをアダプトする
  • 23. 論拠 演算 vs データ どこで/どのようにデータを格納するか • SIMD演算はデータ上で動作する必要がある • 通常のアプローチでは、ユーザーに規定されたコンテナを強制する • これは十分にジェネリックではない より良いアプローチ • SIMD準拠アロケータ • SIMDのRangeとイテレータ : CountiguousRange • 標準アルゴリズムのサブセットを操作するためにSIMDクラスをアダプトする
  • 24. SIMDアロケータ SIMDアロケータ 論拠 • SIMDに準拠した方法でメモリを処理するコンテナを許可する • メモリのアライメントをハンドル • メモリのパディングをハンドル 例 std::vector<float, simd::allocator<float> > v(173); assert( simd::is_aligned(&v[0]) );
  • 25. SIMDイテレータとRange RangeからSIMD Rangeへ イテレータインタフェース • Boost.SIMDは、simd::begin()/simd::end()を提供する • SIMDイテレータはpackを返して回るイテレータ • regular rangeをとり、SIMD上でイテレートする Examples
  • 26. SIMDイテレータとRange RangeからSIMD Rangeへ イテレータインタフェース • Boost.SIMDは、simd::begin()/simd::end()を提供する • SIMDイテレータはpackを返して回るイテレータ • regular rangeをとり、SIMD上でイテレートする 例
  • 27. SIMDイテレータとRange RangeからSIMD Rangeへ イテレータインタフェース • Boost.SIMDは、simd::begin()/simd::end()を提供する • SIMDイテレータはpackを返して回るイテレータ • regular rangeをとり、SIMD上でイテレートする 例 std::vector<float, simd::allocator<float> > v(1024); pack<float> x,z; x = std::accumulate( simd::begin(v.begin()) , simd::end(v.end()) , z );
  • 28. SIMDイテレータとRange RangeからSIMD Rangeへ イテレータインタフェース • Boost.SIMDは、simd::begin()/simd::end()を提供する • SIMDイテレータはpackを返して回るイテレータ • regular rangeをとり、SIMD上でイテレートする 例 std::vector<float, simd::allocator<float> > v(1024); pack<float> x,z; x = boost::accumulate( simd::range(v), z );
  • 29. SIMDイテレータとRange RangeからSIMD Rangeへ イテレータインタフェース • nativeとpackは、begin()/end()を提供する • 標準アルゴリズムを直接使用可能 • Boost.Rangeアルゴリズムを直接使用可能 例 pack<float> x(1, 2, 3, 4); float k = std::accumulate(x.begin() x.end(), 0.f );
  • 30. SIMDイテレータとRange RangeとしてのSIMD値 全てをまとめる std::vector<float, simd::allocator<float> > v(1024); pack<float> x, z; float r; x = boost::accumulate(simd::range(v), z); r = std::accumulate(x.begin(), x.end(), 0.f);
  • 31. SIMDイテレータとRange RangeとしてのSIMD値 全てをまとめる – より良いバージョン std::vector<float, simd::allocator<float> > v(1024); float r; r = sum(accumulate(simd::range(v), pack<float>()));
  • 34. SIMDイテレータとRange SIMD RangeとジェネリックなSIMD/スカラーコード RGB2Greyに戻る template <class RangeIn, class RangeOut> inline void rgb2grey( RangeOut result, RangeIn red, RangeIn green, RangeIn blue ) { typedef typename RangeIn::iterator in_iterator; typedef typename RangeOut::iterator iterator; typedef typename iterator_value< iterator >::type type; iterator br = result.begin(), er = result.end(); in_iterator r = red.begin(); in_iterator g = green.begin(); in_iterator b = blue.begin(); while ( br != er ) { type rv = load< type >(r, 0); type gv = load< type >(g, 0); type bv = load< type >(b, 0); type res = 0.3f * rv + 0.59f * gv + 0.11f * bv; store(res, br, 0); br++; r++; g++; b++; } }
  • 35. SIMDイテレータとRange 何が足りないか 統合されたSIMDサポート • ほとんどの標準アルゴリズムが、一息で実行できるように特殊化されるべ きだ • simd(r)のようなRangeアダプタができるだろうか? • load<T, N>を使用したshifted Rangeのサポート いくつかのSIMDによる頭の体操 • SIMD find? • SIMD sort? • copyのような高速化?
  • 36. Talk Layout 1. はじめに 2. インタフェース 3. SIMDとSTL 4. SIMD仕様イディオム 5. 結論
  • 37. 条件ハンドリング SIMDでの真理値 問題 pack<float> x(1 ,2 ,3 ,4); pack<float> c(2.5); cout << lt(x,c) << endl;
  • 38. 条件ハンドリング SIMDでの真理値 問題 pack<float> x(1 ,2 ,3 ,4); pack<float> c(2.5); cout << lt(x,c) << endl; (( Nan Nan 0 0 ))
  • 39. 条件ハンドリング SIMDでの真理値 問題 pack<float> x(1 ,2 ,3 ,4); pack<float> c(2.5); cout << lt(x,c) << endl; (( Nan Nan 0 0 )) 解決策 Tに適切なtrue値w/rを返すTrue<T>() Tに適切なfalse値w/rを返すFalse<T>()
  • 40. 条件ハンドリング SIMDでの条件式 例 // スカラーコード if( x > 4 ) y = 2*x; else z = 1.f/x; // SIMD code // ???
  • 41. 条件ハンドリング SIMDでの条件式 例 // スカラーコード if( x > 4 ) y = 2*x; else z = 1.f/x; // SIMD code y = where( gt(x, 4), 2*x, y); z = where( gt(x, 4), z, 1.f/x);
  • 45. シフトした読み込み ベクトルの解決策 SIMD/スカラーバージョン template < class RangeIn, class RangeOut > inline void average( RangeOut result, RangeIn input ) { typedef typename RangeIn::iterator in_iterator; typedef typename RangeOut::iterator iterator; typedef typename iterator_value< iterator >::type type; iterator br = result.begin(), er = result.end(); in_iterator data = input.begin(); br++; er--; while ( br != er ) { type xm1 = load<type, -1>(data, i); type x = load<type>(data, i); type xp1 = load<type, +1>(data, i); store(res, i, 0) = 1.f/3 * (xm1 + x + xp1); } }
  • 46. 昇格と飽和(Promotion and Saturation) RGB2Greyへ戻る 8ビットRGB static const std::size_t N = meta::cardinal_of< pack<uint8_t> >::value; for (std::size_t i = 0; i != height*width/N; ++i) { pack<uint8_t> r = load< pack<uint8_t> >(red, i); pack<uint8_t> g = load< pack<uint8_t> >(green, i); pack<uint8_t> b = load< pack<uint8_t> >(blue, i); pack<uint8_t> res = uint8_t(77) * r / uint8_t(255) + uint8_t(150) * g / uint8_t(255) + uint8_t(28) * b / uint8_t(255); store(res, result, i); }
  • 47. 昇格と飽和(Promotion and Saturation) RGB2Greyへ戻る packの昇格 uint16_t r_coeff = 77; uint16_t g_coeff = 150; uint16_t b_coeff = 28; uint16_t div_coeff = 255; pack<uint16_t> r1, r2, g1, g2, b1, b2; tie(r1, r2) = split(r); tie(g1, g2) = split(g); tie(b1, b2) = split(b); pack<uint16_t> res1 = (r_coeff * r1 + g_coeff * g1 + b_coeff * b1) / div_coeff; pack<uint16_t> res2 = (r_coeff * r2 + g_coeff * g2 + b_coeff * b2) / div_coeff; pack<uint8_t> res = group(res1, res2);
  • 48. Talk Layout 1. はじめに 2. インタフェース 3. SIMDとSTL 4. SIMD仕様イディオム 5. 結論
  • 49. Boost.SIMDの概要 proto entityとしてのpack 我々の目標 • SIMDプログラミングに、使いやすい状態をもたらす • もしboost.atomicがあったら、boost.simdをどうするか? • C++の残りのすばらしいものを使って、さらに魅力的にする 我々が達成したいこと • NT2で学んだことの活用する • パフォーマンス用語のいくつかの影響を実証する • スカラーを使用する場合と同じくらい単純なSIMD命令にする
  • 50. 今後の活動 Google Summer of Code 2011 • 混乱をクリーンナップし、boostifyにする • STL/Boostとの互換性を向上させる • 募集:このライブラリを実際に活用したアプリケーション
  • 51. Thanks for your attension