SlideShare a Scribd company logo
1 of 29
Download to read offline
University of Tokyo
1/29	
AVX命令を用いたLJの力計算のSIMD化
2016年10月31日	
渡辺宙志	
 東京大学物性研究所
University of Tokyo
2/29	
SIMDとは何か? (1/4)
一つのサイクルで複数の命令を実行するしかない	
計算機の仕組み	
命令
デコーダ	
実行
ユニット	
キャッシュ	
メモリ	
メモリからデータと命令を取ってきて、デコーダが実行ユニットに渡す	
動作周波数を上げずに演算性能を上げたい	
CPUの動作周波数向上は2000年頃から頭打ちに	
http://cacm.acm.org/magazines/2012/4/147359-cpu-db-recording-microprocessor-history/fulltext
University of Tokyo
3/29	
解決案1: スーパースカラ	
命令
デコーダ	
実行
ユニット	
キャッ
シュ	
メモリ	
実行
ユニット	
欠点:
 ・ 実行ユニットが増えると、振り分けの手間が指数関数的に増大
 ・ 整数演算4つ、浮動小数点演算2つくらいまでが限界	
SIMDとは何か? (2/4)
実行ユニットの数を増やす	
命令をたくさんロードしてキューに詰める
スケジューラが依存関係をチェックし、実行可能なものを振り分ける	
長所:
・ 命令セットの変更を伴わない (後方互換性)
・ コンパイラはこれまで通りの命令を吐けば良い 	
ハードウェアにがんばらせる	
命令
キュー	
振り分け
University of Tokyo
4/29	
解決案2: VLIW	
命令
デコーダ	
実行
ユニット	
キャッ
シュ	
メモリ	
実行
ユニット	
コンパイラにがんばらせる	
命令A	
命令B	
実行ユニットの数は複数用意しておく
コンパイラが予め並列実行可能な命令を並べておき、そのまま実行ユニットに流す	
長所:
・ 依存関係チェックが不要になるため、ハードウェアは簡単になる
・ コード全体を調べるため、より積極的な最適化が可能 	
短所:
・ コンパイラ作るのが死ぬほど大変
・ 後方互換性を失う (命令セットが変わるため)	
SIMDとは何か? (3/4)
University of Tokyo
5/29	
SIMDとは何か? (4/4)
命令
デコー
ダ	
実行
ユニット	
キャッ
シュ	
メモリ	
解決案3: SIMD	
プログラマにがんばらせる	
実行ユニットの数は増やさない
複数のデータに、同じ演算を一度に行う
長所:
・ ハードウェアが簡単になる
・ SIMDは命令セットの拡張という形で入るため、後方互換性もそれなり	
短所:
・ コンパイラがSIMD命令を効率的に吐くのは難しい
・ プログラマが明示的にSIMD命令を使う必要がある	
現在はスーパースカラ+SIMDが主流
実行ユニットの数は増えず、SIMD幅が増えていく傾向
University of Tokyo
6/29	
http://news.mynavi.jp/photo/articles/2016/09/08/hc28_arm2/images/009l.jpg	
ポスト京
ソフトウェア:
 ・ SVE (Scalable Vector Extension)
 ・ 512〜2048bitの可変長ベクトル命令
ハードウェア:
 ・512bit (倍精度64bit × 8個)で実装	
なんでSIMD化するの?
A: SIMD化しないと性能が出なくなっていくから	
システムB
Haswell、AVX命令
・256bit (倍精度64bit × 4個)	
(2016年8月公表@Hot Chips 28)	
京
SPARC-VIIIxfx, HPC-ACE
・128bit (倍精度64bit × 2個)	
128bitくらいまでならスルーできたが、512bitだと真面目にやらないと苦しい?
University of Tokyo
7/29	
よし、LJの力計算を真面目にSIMD化してみよう
University of Tokyo
8/29	
基本アルゴリズム
University of Tokyo
9/29	
ペアリストとBookkeeping法 (1/2)
相互作用ペアリスト	
カットオフ距離以内にある相互作用原子ペアを探す
全探索するとO(N^2)となるので、空間をセルに区切ってO(N)に落とす	
空間をセルに切る
原子をセルに登録する
セル内、隣接セルで相互作用ペアを探索する	
セルの大きさは、相互作用が次近接のセルに届かないようにとる
University of Tokyo
10/29	
Bookkeepingによるペアリスト再利用	
ペアリストとBookkeeping法 (2/2)
相互作用ペア探索は重い処理
→ 探索距離を長めにとって何ステップか再利用する
原子がマージンを横切るまでこのペアリストは再利用できる	
相互作用距離	
探索距離	
マージン	
・ マージンを「ペアリストの寿命」とする
・ 系の最速の原子を探し、その速度をvとする
・ マージンから v*2*dtだけ引く (dtは時間刻み)
・ まだマージンが残っていればペアリストを再利用
・ マージンが無くなったらペアリスト再構築	
相互作用距離	
 マージン	
最悪のケース	
最速と次最速の原子が、お互いに近づく時
→ 系の最速の原子がマージンの半分を
  横切るまではペアリストが有効 	
有効期限判定
University of Tokyo
11/29	
相互作用ペアソート (1/2)
力の計算とペアリスト
力の計算はペアごとに行う
相互作用範囲内にあるペアは配列に格納
ペアの番号の若い方をi粒子、相手をj粒子と呼ぶ	
得られた相互作用ペア	
相互作用ペアの配列表現	
1	
 0	
 0	
 2	
 3	
 3	
 1	
 1	
 2	
 3	
 0	
 2	
9	
 2	
 1	
 7	
 9	
 5	
 2	
 4	
 8	
 4	
 5	
 6	
このまま計算すると	
2個の粒子の座標を取得 (48Byte) 運動量の読み書き (96Byte)
力の計算が50演算程度とすると、B/F〜3.0を要求	
1	
9	
0	
2	
0	
1	
2	
7	
3	
9	
3	
5	
1	
2	
1	
4	
2	
8	
3	
4	
0	
5	
2	
6	
i粒子	
j粒子	
i粒子	
j粒子
University of Tokyo
12/29	
相互作用相手でソート
相互作用ペア	
相互作用ペアソート (2/2)
1	
9	
0	
2	
0	
1	
2	
7	
3	
9	
3	
5	
1	
2	
1	
4	
2	
8	
3	
4	
0	
5	
2	
6	
i粒子でソート	
1	
 2	
 5	
 2	
 4	
 9	
 6	
 7	
 8	
 4	
 5	
 9	
Sorted List	
0	
1	
 2	
 5	
1	
2	
 4	
 9	
2	
6	
 7	
 8	
3	
4	
 5	
 9	
配列表現	
0	
 1	
 2	
 3	
i粒子の情報がレジスタにのる
→ 読み込み、書き込みがj粒子のみ
→ メモリアクセスが半分に
キャッシュに乗る領域でも10%前後の高速化	
i粒子	
j粒子	
i粒子	
j粒子
University of Tokyo
13/29	
AVX命令によるSIMD化	
前提条件:
 ・ 相互作用相手はペアリストにより間接参照、インデックスは不連続
 ・ Bookkeeping法により、相互作用していないペアも含まれる
University of Tokyo
14/29	
レジスタとメモリ	
A[2]	
全ての計算は原則としてレジスタ上で行う
「C = A + B」を計算する例:
(1)  メモリからAとBをレジスタにロード
(2)  レジスタでA+Bを計算
(3)  結果Cをレジスタからメモリにストア
A[1]	
SIMD	
SIMD: 複数のデータに対して、一度に同じタイプの演算を行う仕組み
SIMD用レジスタ:複数の値を同時に保持、演算できるレジスタ
C[1] = A[1]+B[1]
C[2] = A[2]+B[2]
A	
 B	
 C	
1	
 2	
メモリ	
レジスタ	
3	
 1	
 2	
+	
3	
ロード	
ストア	
B[2]	
 B[1]	
+	
C[2]	
 C[1]	
 =	
二つ以上の演算を一度に行うことができる	
x86レジスタ (1/3)
University of Tokyo
15/29	
浮動小数点レジスタ	
下位	
上位	
xmm0	
ymm0	
浮動小数点演算用に256bitのレジスタが16本用意されている
そのうち下位128bitをxmmレジスタ、全体をymmレジスタと呼ぶ
倍精度実数は64bitなので、倍精度実数4つ分の値を保持できる
汎用レジスタ	
64bitの汎用レジスタがある
下位32bit, 16bit, 8bitを別名で共有
アドレッシングや整数演算に使う
下位	
上位	
64bit	
RAX	
EAX	
AX	
AH	
 AL	
x86レジスタ (2/3)
University of Tokyo
16/29	
xmmレジスタは倍精度実数二つ分保持できるが、下位64bitを普段使いに使う
double func(double a, double b){
return a+b;
}	
func(double, double):
addsd %xmm1, %xmm0
ret	
ソース	
 アセンブリ	
関数の引数のdoubleは、順番にxmm0,xmm1に値を入れる
返り値がdoubleの時はxmm0に値を入れる
(xmmレジスタの下位64bitだけ使う)
浮動小数点演算	
整数演算	
int func(int a, int b){
return a+b;
}	
func(int, int):
addl %esi, %eax
ret	
※ 実際にはlealが使われる	
ソース	
 アセンブリ	
関数の引数のint(32bit)は、順番にeax, esi, edx, ecx, ...に値を入れる
返り値がintの時はeaxに値を入れる
x86レジスタ (3/3)
University of Tokyo
17/29	
Lennard-Jonesの力計算 (1/2)
V (r) = 4 r 12
r 6
f(r) =
48
r13
24
r7
r	
dx	
dy	
ポテンシャル	
力	
力積	
 Ix = f ⇥
dx
r
⇥ dt ⌘ df ⇥ dx
df =
✓
48
r14
24
r8
◆
dt
ここをまとめる	
計算したい量	
~r = (dx, dy, dz)相対座標	
r = |~r|相対距離
University of Tokyo
18/29	
Lennard-Jonesの力計算 (2/2)
~qi = (qi
x, qi
y, qi
z) ~qj = (qj
x, qj
y, qj
z)
~dq = ~qj ~qi
r2
= ~dq
2
r6
= r2
⇥ r2
⇥ r2
r14
= r6
⇥ r6
⇥ r2
減算*3	
乗算*3 + 加算*2	
乗算*2	
乗算*2	
df =
(48 24 ⇥ r6
) ⇥ dt
r14
乗算*2 + 減算*1 + 除算1	
乗算*3 + 加算*3	
乗算*3 + 加算*3	
~pi = ~pi df ⇥ ~dq
~pj = ~pj + df ⇥ ~dq
加減乗算 * 27 + 除算*1 	
 LJの力計算は軽い
University of Tokyo
19/29	
力計算の単純SIMD化 (1/2)
ナイーブな実装	
ˆqi
x qi
x
以下、SIMDベクトルレジスタをハットで表現する	
ˆqj
x qj
xqj+1
xqj+2
xqj+3
x
qi+1
xqi+2
xqi+3
x
4つの座標データをymmレジスタにロードする	
4つの座標データをymmレジスタにロードする	
※ y, zも同様	
※ y, zも同様	
ˆdx = ˆqj
x ˆqi
x
ˆr2 = ˆdx
2
+ ˆdy
2
+ ˆdz
2
あとは同様に計算することで、4対の粒子間の力を同時に計算できる
University of Tokyo
20/29	
相互作用粒子のインデックスは連続ではない
→ 4つのデータをバラバラにロード	
D	
 C	
 B	
 A	
D	
 C	
 B	
 A	
メモリ	
レジスタ	
D	
 C	
 B	
 A	
A	
メモリ	
xmm0	
D	
 C	
 B	
 A	
B	
 A	
メモリ	
xmm0	
vmovsd	
 vmovhpd	
D	
 C	
 B	
 A	
C	
メモリ	
 D	
 C	
 B	
 A	
D	
 C	
メモリ	
vmovsd	
 vmovhpd	
B	
 A	
ymm0	
xmm1	
 xmm1	
D	
 C	
D	
 C	
xmm1	
(1) Aをxmm0下位にロード	
 (2) Bをxmm0上位にロード	
(3) Cをxmm1下位にロード	
 (4) Dをxmm1上位にロード	
(5) xmm1全体をymm0上位128bitにコピー	
vinsertf128	
実際に起きること	
問題点	
※ これをx,y,z座標それぞれでやる
※ データの書き戻しも同様	
力計算の単純SIMD化 (2/2)
※ vgatherdpdでなんとかできるかもしれないが・・・
University of Tokyo
21/29	
やったこと	
データを粒子数*4成分の二次元配列で宣言
double q[N][4], p[N][4];	
z	
 y	
 x	
 z	
 y	
 x	
メモリ	
 z	
 y	
 x	
0	
1	
2	
z	
 y	
 x	
3	
粒子番号	
うれしいこと	
(x,y,z)の3成分のデータをymmレジスタに一発ロード
ただし、1成分(64bit) は無駄になる	
z	
 y	
 x	
 z	
 y	
 x	
メモリ	
 z	
 y	
 x	
0	
1	
2	
z	
 y	
 x	
3	
粒子番号	
z	
 y	
 x	
movupd/movapd	
ymm0	
力計算のSIMD化 (1/5)
University of Tokyo
22/29	
力の計算(1ペア)	
qj
xqj
yqj
z
qi
xqi
yqi
z
ˆqj
ˆqi
ˆdq = ˆqj ˆqi
ˆdq
2
dx2dy2
dz2
dxdydz
ここから	
r2
= dx2
+ dy2
+ dz2 を作りたい	
SIMDのシャッフル命令を使う	
力計算のSIMD化 (2/5)
University of Tokyo
23/29	
シャッフル系命令	
レジスターメモリ間の転送は極めてコストが高い
なので、レジスタの中でデータを並び替えたい
→ 豊富なシャッフル系命令が用意されている	
D	
 C	
 B	
 A	
ベクトルの並び替え
(vpermpd)	
A	
 B	
 D	
 B	
同じ要素の重複可	
二つのベクトルの要素を混ぜる
(blendpd)	
D2	
 C2	
 B2	
 A2	
 D1	
 C1	
 B1	
 A1	
D1	
 C2	
 B2	
 A1	
どちらの要素をコピーするか選択化	
力計算のSIMD化 (3/5)
University of Tokyo
24/29	
力の計算(1ペア) cont.	
dx2dy2
dz2
dx2
dx2
dy2
dz2
dy2
dz2
相対ベクトルの自乗を並び替える	
全部足す	
r2
r2
r2
力の計算(4ペア)	
これを4つのペアについて行う	
r2
A
r2
B
r2
C
r2
D
r2
Ar2
A
r2
Br2
B
r2
Cr2
C
r2
Dr2
D
r2
Ar2
A r2
Cr2
C
r2
Br2
B r2
Dr2
D
unpacklpd	
 vshufpd	
r2
Ar2
C r2
Br2
D
あとは4ペア同時に力の計算ができる	
vpermpd	
力計算のSIMD化 (4/5)
University of Tokyo
25/29	
力積の書き戻し	
dfAdfBdfCdfD
dfAdfAdfAdfA
~pi = ~pi df ⇥ ~dq
dxAdyAdzA
(1) Aペアの力だけ取り出す	
vpermpd	
dfAdfAdfAdfApi
xpi
ypi
z pi
x
pi
ypi
z=	
 -	
 ×	
(2) 運動量をロード	
(3) 力積ベクトルの計算	
pi
xpi
ypi
z
pi
xpi
ypi
z
メモリ	
ymmレジスタ	
(4) 運動量の書き戻し	
pi
xpi
ypi
z
pi
xpi
ypi
z
メモリ	
ymmレジスタ	
これを4ペアについて行う	
vfnmadd213pd	
vmovupd	
vmovupd	
力計算のSIMD化 (5/5)
University of Tokyo
26/29	
マスク処理	
Bookkeeping法により、相互作用範囲外のペアもいる→マスク処理	
D2	
 C2	
 B2	
 A2	
D1	
 C1	
 B1	
 A1	
負	
 正	
 正	
 負	
src1	
src2	
mask	
 D2	
 C1	
 B1	
 A2	
vblendvpd: マスクの要素の正負により要素を選ぶ	
※ 実際にはmaskの最上位bitが0か1かで判定している	
相互作用距離とカットオフ距離でマスクを作成し、力をゼロクリア 	
dfAdfBdfCdfD
0	
 0	
 0	
 0	
src1	
src2	
dfBdfC0	
 0	
ペアAとDが相互作用範囲外	
カットオフのマスク処理
University of Tokyo
27/29	
1
9
0
2
0
1
2
7
3
9
3
5
1
2
1
4
2
8
3
4
0
5
2
6
0
1 2 5
1
2 4 9
2
6 7 8
3
4 5 9
pair: ペア毎に力計算	
sorted: 相互作用相手でソート	
next:	
 手で二段ソフトウェア
パイプライニング	
intrin:	
手でSIMD化	
計算条件:
・密度1.0
・カットオフ3.0
・探索範囲3.3
・12万粒子, 100回の力計算にかかった時間	
86%	
83%	
70%	
47%	
実行結果
ソースファイル
https://github.com/kaityo256/lj_simd
University of Tokyo
28/29	
SIMD化前 (33行)	
 SIMD化後 (98行)	
ホットスポットのチューニングとしては許容範囲・・・?	
実際のソースコード
行数は3倍に	
ここを4倍展開
University of Tokyo
29/29	
まとめと感想
・ AVX命令を使ってLennard-Jones系の力計算をSIMD化した
・ レジスタとメモリの間のやり取りは高コスト
 → ロード/ストアを減らすため、データ構造を工夫
 → なるべくレジスタで処理をするため、シャッフル命令を活用
・ SIMD化無しの最速コードに比べて速度向上は33%
まとめ	
感想	
・ やろうと思い立ってから、SIMD化が完成するまで1ヶ月ちょっと
・ 実働2週間程度?
・ 難しくはないが極めて面倒くさい
 → 実際に早くなるかはやってみないとわからない
・ 「京」では128bit SIMD化により10〜15%程度の性能向上
・ Intel Xeonでは256bit SIMD化により 30〜40%程度の性能向上
・ 512bit SIMDでは二倍程度は差がでるのではないか?

More Related Content

What's hot

計算機アーキテクチャを考慮した高能率画像処理プログラミング
計算機アーキテクチャを考慮した高能率画像処理プログラミング計算機アーキテクチャを考慮した高能率画像処理プログラミング
計算機アーキテクチャを考慮した高能率画像処理プログラミングNorishige Fukushima
 
本当にわかる Spectre と Meltdown
本当にわかる Spectre と Meltdown本当にわかる Spectre と Meltdown
本当にわかる Spectre と MeltdownHirotaka Kawata
 
Linuxのプロセススケジューラ(Reading the Linux process scheduler)
Linuxのプロセススケジューラ(Reading the Linux process scheduler)Linuxのプロセススケジューラ(Reading the Linux process scheduler)
Linuxのプロセススケジューラ(Reading the Linux process scheduler)Hiraku Toyooka
 
【学習メモ#7th】12ステップで作る組込みOS自作入門
【学習メモ#7th】12ステップで作る組込みOS自作入門 【学習メモ#7th】12ステップで作る組込みOS自作入門
【学習メモ#7th】12ステップで作る組込みOS自作入門 sandai
 
Intel TSX について x86opti
Intel TSX について x86optiIntel TSX について x86opti
Intel TSX について x86optiTakashi Hoshino
 
Chainer v1.6からv1.7の新機能
Chainer v1.6からv1.7の新機能Chainer v1.6からv1.7の新機能
Chainer v1.6からv1.7の新機能Ryosuke Okuta
 
2015年度先端GPGPUシミュレーション工学特論 第5回 GPUのメモリ階層の詳細 (様々なメモリの利用)
2015年度先端GPGPUシミュレーション工学特論 第5回 GPUのメモリ階層の詳細(様々なメモリの利用)2015年度先端GPGPUシミュレーション工学特論 第5回 GPUのメモリ階層の詳細(様々なメモリの利用)
2015年度先端GPGPUシミュレーション工学特論 第5回 GPUのメモリ階層の詳細 (様々なメモリの利用) 智啓 出川
 
PFIセミナーH271022 ~コマンドを叩いて遊ぶ コンテナ仮想、その裏側~
PFIセミナーH271022 ~コマンドを叩いて遊ぶ コンテナ仮想、その裏側~PFIセミナーH271022 ~コマンドを叩いて遊ぶ コンテナ仮想、その裏側~
PFIセミナーH271022 ~コマンドを叩いて遊ぶ コンテナ仮想、その裏側~Preferred Networks
 
研究動向から考えるx86/x64最適化手法
研究動向から考えるx86/x64最適化手法研究動向から考えるx86/x64最適化手法
研究動向から考えるx86/x64最適化手法Takeshi Yamamuro
 
【学習メモ#3rd】12ステップで作る組込みOS自作入門
【学習メモ#3rd】12ステップで作る組込みOS自作入門【学習メモ#3rd】12ステップで作る組込みOS自作入門
【学習メモ#3rd】12ステップで作る組込みOS自作入門sandai
 
【学習メモ#8th】12ステップで作る組込みOS自作入門
【学習メモ#8th】12ステップで作る組込みOS自作入門 【学習メモ#8th】12ステップで作る組込みOS自作入門
【学習メモ#8th】12ステップで作る組込みOS自作入門 sandai
 
Deep Learning Implementations: pylearn2 and torch7 (JNNS 2015)
Deep Learning Implementations: pylearn2 and torch7 (JNNS 2015)Deep Learning Implementations: pylearn2 and torch7 (JNNS 2015)
Deep Learning Implementations: pylearn2 and torch7 (JNNS 2015)Kotaro Nakayama
 
【学習メモ#4th】12ステップで作る組込みOS自作入門
【学習メモ#4th】12ステップで作る組込みOS自作入門【学習メモ#4th】12ステップで作る組込みOS自作入門
【学習メモ#4th】12ステップで作る組込みOS自作入門sandai
 
Completely Fair Scheduler (CFS)
Completely Fair Scheduler (CFS)Completely Fair Scheduler (CFS)
Completely Fair Scheduler (CFS)gokzy
 
並列化による高速化
並列化による高速化 並列化による高速化
並列化による高速化 sakura-mike
 
プロセスとコンテキストスイッチ
プロセスとコンテキストスイッチプロセスとコンテキストスイッチ
プロセスとコンテキストスイッチKazuki Onishi
 
さわってみようTOPPERS/SSP
さわってみようTOPPERS/SSPさわってみようTOPPERS/SSP
さわってみようTOPPERS/SSPNSaitoNmiri
 

What's hot (20)

計算機アーキテクチャを考慮した高能率画像処理プログラミング
計算機アーキテクチャを考慮した高能率画像処理プログラミング計算機アーキテクチャを考慮した高能率画像処理プログラミング
計算機アーキテクチャを考慮した高能率画像処理プログラミング
 
本当にわかる Spectre と Meltdown
本当にわかる Spectre と Meltdown本当にわかる Spectre と Meltdown
本当にわかる Spectre と Meltdown
 
Linuxのプロセススケジューラ(Reading the Linux process scheduler)
Linuxのプロセススケジューラ(Reading the Linux process scheduler)Linuxのプロセススケジューラ(Reading the Linux process scheduler)
Linuxのプロセススケジューラ(Reading the Linux process scheduler)
 
【学習メモ#7th】12ステップで作る組込みOS自作入門
【学習メモ#7th】12ステップで作る組込みOS自作入門 【学習メモ#7th】12ステップで作る組込みOS自作入門
【学習メモ#7th】12ステップで作る組込みOS自作入門
 
CMSI計算科学技術特論A (2015) 第9回
CMSI計算科学技術特論A (2015) 第9回CMSI計算科学技術特論A (2015) 第9回
CMSI計算科学技術特論A (2015) 第9回
 
Intel TSX について x86opti
Intel TSX について x86optiIntel TSX について x86opti
Intel TSX について x86opti
 
Chainer v1.6からv1.7の新機能
Chainer v1.6からv1.7の新機能Chainer v1.6からv1.7の新機能
Chainer v1.6からv1.7の新機能
 
2015年度先端GPGPUシミュレーション工学特論 第5回 GPUのメモリ階層の詳細 (様々なメモリの利用)
2015年度先端GPGPUシミュレーション工学特論 第5回 GPUのメモリ階層の詳細(様々なメモリの利用)2015年度先端GPGPUシミュレーション工学特論 第5回 GPUのメモリ階層の詳細(様々なメモリの利用)
2015年度先端GPGPUシミュレーション工学特論 第5回 GPUのメモリ階層の詳細 (様々なメモリの利用)
 
PFIセミナーH271022 ~コマンドを叩いて遊ぶ コンテナ仮想、その裏側~
PFIセミナーH271022 ~コマンドを叩いて遊ぶ コンテナ仮想、その裏側~PFIセミナーH271022 ~コマンドを叩いて遊ぶ コンテナ仮想、その裏側~
PFIセミナーH271022 ~コマンドを叩いて遊ぶ コンテナ仮想、その裏側~
 
研究動向から考えるx86/x64最適化手法
研究動向から考えるx86/x64最適化手法研究動向から考えるx86/x64最適化手法
研究動向から考えるx86/x64最適化手法
 
【学習メモ#3rd】12ステップで作る組込みOS自作入門
【学習メモ#3rd】12ステップで作る組込みOS自作入門【学習メモ#3rd】12ステップで作る組込みOS自作入門
【学習メモ#3rd】12ステップで作る組込みOS自作入門
 
【学習メモ#8th】12ステップで作る組込みOS自作入門
【学習メモ#8th】12ステップで作る組込みOS自作入門 【学習メモ#8th】12ステップで作る組込みOS自作入門
【学習メモ#8th】12ステップで作る組込みOS自作入門
 
CMSI計算科学技術特論C (2015) MODYLAS と古典MD①
CMSI計算科学技術特論C (2015) MODYLAS と古典MD①CMSI計算科学技術特論C (2015) MODYLAS と古典MD①
CMSI計算科学技術特論C (2015) MODYLAS と古典MD①
 
画像処理の高性能計算
画像処理の高性能計算画像処理の高性能計算
画像処理の高性能計算
 
Deep Learning Implementations: pylearn2 and torch7 (JNNS 2015)
Deep Learning Implementations: pylearn2 and torch7 (JNNS 2015)Deep Learning Implementations: pylearn2 and torch7 (JNNS 2015)
Deep Learning Implementations: pylearn2 and torch7 (JNNS 2015)
 
【学習メモ#4th】12ステップで作る組込みOS自作入門
【学習メモ#4th】12ステップで作る組込みOS自作入門【学習メモ#4th】12ステップで作る組込みOS自作入門
【学習メモ#4th】12ステップで作る組込みOS自作入門
 
Completely Fair Scheduler (CFS)
Completely Fair Scheduler (CFS)Completely Fair Scheduler (CFS)
Completely Fair Scheduler (CFS)
 
並列化による高速化
並列化による高速化 並列化による高速化
並列化による高速化
 
プロセスとコンテキストスイッチ
プロセスとコンテキストスイッチプロセスとコンテキストスイッチ
プロセスとコンテキストスイッチ
 
さわってみようTOPPERS/SSP
さわってみようTOPPERS/SSPさわってみようTOPPERS/SSP
さわってみようTOPPERS/SSP
 

Viewers also liked

Viewers also liked (7)

130613-debug
130613-debug130613-debug
130613-debug
 
Ad stirの裏側
Ad stirの裏側Ad stirの裏側
Ad stirの裏側
 
広告配信のための高速疎ベクトル検索エンジンの開発@WebDBフォーラム2015 #webdbf2015
広告配信のための高速疎ベクトル検索エンジンの開発@WebDBフォーラム2015 #webdbf2015広告配信のための高速疎ベクトル検索エンジンの開発@WebDBフォーラム2015 #webdbf2015
広告配信のための高速疎ベクトル検索エンジンの開発@WebDBフォーラム2015 #webdbf2015
 
空間分割
空間分割空間分割
空間分割
 
衝突判定
衝突判定衝突判定
衝突判定
 
CMSI計算科学技術特論A(12) 古典分子動力学法の高速化1
CMSI計算科学技術特論A(12) 古典分子動力学法の高速化1CMSI計算科学技術特論A(12) 古典分子動力学法の高速化1
CMSI計算科学技術特論A(12) 古典分子動力学法の高速化1
 
SDL2の紹介
SDL2の紹介SDL2の紹介
SDL2の紹介
 

Similar to AVX命令を用いたLJの力計算のSIMD化

条件分岐とcmovとmaxps
条件分岐とcmovとmaxps条件分岐とcmovとmaxps
条件分岐とcmovとmaxpsMITSUNARI Shigeo
 
LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)
LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)
LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)Takeshi Yamamuro
 
8 並列計算に向けた pcセッティング
8 並列計算に向けた pcセッティング8 並列計算に向けた pcセッティング
8 並列計算に向けた pcセッティングTakeshi Takaishi
 
200625material naruse
200625material naruse200625material naruse
200625material naruseRCCSRENKEI
 
Intel AVX-512/富岳SVE用SIMDコード生成ライブラリsimdgen
Intel AVX-512/富岳SVE用SIMDコード生成ライブラリsimdgenIntel AVX-512/富岳SVE用SIMDコード生成ライブラリsimdgen
Intel AVX-512/富岳SVE用SIMDコード生成ライブラリsimdgenMITSUNARI Shigeo
 
AVX-512(フォーマット)詳解
AVX-512(フォーマット)詳解AVX-512(フォーマット)詳解
AVX-512(フォーマット)詳解MITSUNARI Shigeo
 
第11回 配信講義 計算科学技術特論B(2022)
第11回 配信講義 計算科学技術特論B(2022)第11回 配信講義 計算科学技術特論B(2022)
第11回 配信講義 計算科学技術特論B(2022)RCCSRENKEI
 
Intro to SVE 富岳のA64FXを触ってみた
Intro to SVE 富岳のA64FXを触ってみたIntro to SVE 富岳のA64FXを触ってみた
Intro to SVE 富岳のA64FXを触ってみたMITSUNARI Shigeo
 
第5回 配信講義 計算科学技術特論B(2022)
第5回 配信講義 計算科学技術特論B(2022)第5回 配信講義 計算科学技術特論B(2022)
第5回 配信講義 計算科学技術特論B(2022)RCCSRENKEI
 
Halide による画像処理プログラミング入門
Halide による画像処理プログラミング入門Halide による画像処理プログラミング入門
Halide による画像処理プログラミング入門Fixstars Corporation
 
DTrace for biginners part(1)
DTrace for biginners part(1)DTrace for biginners part(1)
DTrace for biginners part(1)Shoji Haraguchi
 
並列対決 Elixir × Go × C# x Scala , Node.js
並列対決 Elixir × Go × C# x Scala , Node.js並列対決 Elixir × Go × C# x Scala , Node.js
並列対決 Elixir × Go × C# x Scala , Node.jsYoshiiro Ueno
 
kagamicomput201705
kagamicomput201705kagamicomput201705
kagamicomput201705swkagami
 

Similar to AVX命令を用いたLJの力計算のSIMD化 (20)

Prosym2012
Prosym2012Prosym2012
Prosym2012
 
条件分岐とcmovとmaxps
条件分岐とcmovとmaxps条件分岐とcmovとmaxps
条件分岐とcmovとmaxps
 
TVM の紹介
TVM の紹介TVM の紹介
TVM の紹介
 
フラグを愛でる
フラグを愛でるフラグを愛でる
フラグを愛でる
 
llvm入門
llvm入門llvm入門
llvm入門
 
LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)
LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)
LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)
 
8 並列計算に向けた pcセッティング
8 並列計算に向けた pcセッティング8 並列計算に向けた pcセッティング
8 並列計算に向けた pcセッティング
 
200625material naruse
200625material naruse200625material naruse
200625material naruse
 
Intel AVX-512/富岳SVE用SIMDコード生成ライブラリsimdgen
Intel AVX-512/富岳SVE用SIMDコード生成ライブラリsimdgenIntel AVX-512/富岳SVE用SIMDコード生成ライブラリsimdgen
Intel AVX-512/富岳SVE用SIMDコード生成ライブラリsimdgen
 
AVX-512(フォーマット)詳解
AVX-512(フォーマット)詳解AVX-512(フォーマット)詳解
AVX-512(フォーマット)詳解
 
Rを用いたGIS
Rを用いたGISRを用いたGIS
Rを用いたGIS
 
第11回 配信講義 計算科学技術特論B(2022)
第11回 配信講義 計算科学技術特論B(2022)第11回 配信講義 計算科学技術特論B(2022)
第11回 配信講義 計算科学技術特論B(2022)
 
Intro to SVE 富岳のA64FXを触ってみた
Intro to SVE 富岳のA64FXを触ってみたIntro to SVE 富岳のA64FXを触ってみた
Intro to SVE 富岳のA64FXを触ってみた
 
第5回 配信講義 計算科学技術特論B(2022)
第5回 配信講義 計算科学技術特論B(2022)第5回 配信講義 計算科学技術特論B(2022)
第5回 配信講義 計算科学技術特論B(2022)
 
LLVM最適化のこつ
LLVM最適化のこつLLVM最適化のこつ
LLVM最適化のこつ
 
Halide による画像処理プログラミング入門
Halide による画像処理プログラミング入門Halide による画像処理プログラミング入門
Halide による画像処理プログラミング入門
 
DTrace for biginners part(1)
DTrace for biginners part(1)DTrace for biginners part(1)
DTrace for biginners part(1)
 
並列対決 Elixir × Go × C# x Scala , Node.js
並列対決 Elixir × Go × C# x Scala , Node.js並列対決 Elixir × Go × C# x Scala , Node.js
並列対決 Elixir × Go × C# x Scala , Node.js
 
kagamicomput201705
kagamicomput201705kagamicomput201705
kagamicomput201705
 
HPC Phys-20201203
HPC Phys-20201203HPC Phys-20201203
HPC Phys-20201203
 

AVX命令を用いたLJの力計算のSIMD化

  • 2. University of Tokyo 2/29 SIMDとは何か? (1/4) 一つのサイクルで複数の命令を実行するしかない 計算機の仕組み 命令 デコーダ 実行 ユニット キャッシュ メモリ メモリからデータと命令を取ってきて、デコーダが実行ユニットに渡す 動作周波数を上げずに演算性能を上げたい CPUの動作周波数向上は2000年頃から頭打ちに http://cacm.acm.org/magazines/2012/4/147359-cpu-db-recording-microprocessor-history/fulltext
  • 3. University of Tokyo 3/29 解決案1: スーパースカラ 命令 デコーダ 実行 ユニット キャッ シュ メモリ 実行 ユニット 欠点:  ・ 実行ユニットが増えると、振り分けの手間が指数関数的に増大  ・ 整数演算4つ、浮動小数点演算2つくらいまでが限界 SIMDとは何か? (2/4) 実行ユニットの数を増やす 命令をたくさんロードしてキューに詰める スケジューラが依存関係をチェックし、実行可能なものを振り分ける 長所: ・ 命令セットの変更を伴わない (後方互換性) ・ コンパイラはこれまで通りの命令を吐けば良い ハードウェアにがんばらせる 命令 キュー 振り分け
  • 4. University of Tokyo 4/29 解決案2: VLIW 命令 デコーダ 実行 ユニット キャッ シュ メモリ 実行 ユニット コンパイラにがんばらせる 命令A 命令B 実行ユニットの数は複数用意しておく コンパイラが予め並列実行可能な命令を並べておき、そのまま実行ユニットに流す 長所: ・ 依存関係チェックが不要になるため、ハードウェアは簡単になる ・ コード全体を調べるため、より積極的な最適化が可能 短所: ・ コンパイラ作るのが死ぬほど大変 ・ 後方互換性を失う (命令セットが変わるため) SIMDとは何か? (3/4)
  • 5. University of Tokyo 5/29 SIMDとは何か? (4/4) 命令 デコー ダ 実行 ユニット キャッ シュ メモリ 解決案3: SIMD プログラマにがんばらせる 実行ユニットの数は増やさない 複数のデータに、同じ演算を一度に行う 長所: ・ ハードウェアが簡単になる ・ SIMDは命令セットの拡張という形で入るため、後方互換性もそれなり 短所: ・ コンパイラがSIMD命令を効率的に吐くのは難しい ・ プログラマが明示的にSIMD命令を使う必要がある 現在はスーパースカラ+SIMDが主流 実行ユニットの数は増えず、SIMD幅が増えていく傾向
  • 6. University of Tokyo 6/29 http://news.mynavi.jp/photo/articles/2016/09/08/hc28_arm2/images/009l.jpg ポスト京 ソフトウェア:  ・ SVE (Scalable Vector Extension)  ・ 512〜2048bitの可変長ベクトル命令 ハードウェア:  ・512bit (倍精度64bit × 8個)で実装 なんでSIMD化するの? A: SIMD化しないと性能が出なくなっていくから システムB Haswell、AVX命令 ・256bit (倍精度64bit × 4個) (2016年8月公表@Hot Chips 28) 京 SPARC-VIIIxfx, HPC-ACE ・128bit (倍精度64bit × 2個) 128bitくらいまでならスルーできたが、512bitだと真面目にやらないと苦しい?
  • 9. University of Tokyo 9/29 ペアリストとBookkeeping法 (1/2) 相互作用ペアリスト カットオフ距離以内にある相互作用原子ペアを探す 全探索するとO(N^2)となるので、空間をセルに区切ってO(N)に落とす 空間をセルに切る 原子をセルに登録する セル内、隣接セルで相互作用ペアを探索する セルの大きさは、相互作用が次近接のセルに届かないようにとる
  • 10. University of Tokyo 10/29 Bookkeepingによるペアリスト再利用 ペアリストとBookkeeping法 (2/2) 相互作用ペア探索は重い処理 → 探索距離を長めにとって何ステップか再利用する 原子がマージンを横切るまでこのペアリストは再利用できる 相互作用距離 探索距離 マージン ・ マージンを「ペアリストの寿命」とする ・ 系の最速の原子を探し、その速度をvとする ・ マージンから v*2*dtだけ引く (dtは時間刻み) ・ まだマージンが残っていればペアリストを再利用 ・ マージンが無くなったらペアリスト再構築 相互作用距離 マージン 最悪のケース 最速と次最速の原子が、お互いに近づく時 → 系の最速の原子がマージンの半分を   横切るまではペアリストが有効 有効期限判定
  • 11. University of Tokyo 11/29 相互作用ペアソート (1/2) 力の計算とペアリスト 力の計算はペアごとに行う 相互作用範囲内にあるペアは配列に格納 ペアの番号の若い方をi粒子、相手をj粒子と呼ぶ 得られた相互作用ペア 相互作用ペアの配列表現 1 0 0 2 3 3 1 1 2 3 0 2 9 2 1 7 9 5 2 4 8 4 5 6 このまま計算すると 2個の粒子の座標を取得 (48Byte) 運動量の読み書き (96Byte) 力の計算が50演算程度とすると、B/F〜3.0を要求 1 9 0 2 0 1 2 7 3 9 3 5 1 2 1 4 2 8 3 4 0 5 2 6 i粒子 j粒子 i粒子 j粒子
  • 12. University of Tokyo 12/29 相互作用相手でソート 相互作用ペア 相互作用ペアソート (2/2) 1 9 0 2 0 1 2 7 3 9 3 5 1 2 1 4 2 8 3 4 0 5 2 6 i粒子でソート 1 2 5 2 4 9 6 7 8 4 5 9 Sorted List 0 1 2 5 1 2 4 9 2 6 7 8 3 4 5 9 配列表現 0 1 2 3 i粒子の情報がレジスタにのる → 読み込み、書き込みがj粒子のみ → メモリアクセスが半分に キャッシュに乗る領域でも10%前後の高速化 i粒子 j粒子 i粒子 j粒子
  • 13. University of Tokyo 13/29 AVX命令によるSIMD化 前提条件:  ・ 相互作用相手はペアリストにより間接参照、インデックスは不連続  ・ Bookkeeping法により、相互作用していないペアも含まれる
  • 14. University of Tokyo 14/29 レジスタとメモリ A[2] 全ての計算は原則としてレジスタ上で行う 「C = A + B」を計算する例: (1)  メモリからAとBをレジスタにロード (2)  レジスタでA+Bを計算 (3)  結果Cをレジスタからメモリにストア A[1] SIMD SIMD: 複数のデータに対して、一度に同じタイプの演算を行う仕組み SIMD用レジスタ:複数の値を同時に保持、演算できるレジスタ C[1] = A[1]+B[1] C[2] = A[2]+B[2] A B C 1 2 メモリ レジスタ 3 1 2 + 3 ロード ストア B[2] B[1] + C[2] C[1] = 二つ以上の演算を一度に行うことができる x86レジスタ (1/3)
  • 16. University of Tokyo 16/29 xmmレジスタは倍精度実数二つ分保持できるが、下位64bitを普段使いに使う double func(double a, double b){ return a+b; } func(double, double): addsd %xmm1, %xmm0 ret ソース アセンブリ 関数の引数のdoubleは、順番にxmm0,xmm1に値を入れる 返り値がdoubleの時はxmm0に値を入れる (xmmレジスタの下位64bitだけ使う) 浮動小数点演算 整数演算 int func(int a, int b){ return a+b; } func(int, int): addl %esi, %eax ret ※ 実際にはlealが使われる ソース アセンブリ 関数の引数のint(32bit)は、順番にeax, esi, edx, ecx, ...に値を入れる 返り値がintの時はeaxに値を入れる x86レジスタ (3/3)
  • 17. University of Tokyo 17/29 Lennard-Jonesの力計算 (1/2) V (r) = 4 r 12 r 6 f(r) = 48 r13 24 r7 r dx dy ポテンシャル 力 力積 Ix = f ⇥ dx r ⇥ dt ⌘ df ⇥ dx df = ✓ 48 r14 24 r8 ◆ dt ここをまとめる 計算したい量 ~r = (dx, dy, dz)相対座標 r = |~r|相対距離
  • 18. University of Tokyo 18/29 Lennard-Jonesの力計算 (2/2) ~qi = (qi x, qi y, qi z) ~qj = (qj x, qj y, qj z) ~dq = ~qj ~qi r2 = ~dq 2 r6 = r2 ⇥ r2 ⇥ r2 r14 = r6 ⇥ r6 ⇥ r2 減算*3 乗算*3 + 加算*2 乗算*2 乗算*2 df = (48 24 ⇥ r6 ) ⇥ dt r14 乗算*2 + 減算*1 + 除算1 乗算*3 + 加算*3 乗算*3 + 加算*3 ~pi = ~pi df ⇥ ~dq ~pj = ~pj + df ⇥ ~dq 加減乗算 * 27 + 除算*1 LJの力計算は軽い
  • 19. University of Tokyo 19/29 力計算の単純SIMD化 (1/2) ナイーブな実装 ˆqi x qi x 以下、SIMDベクトルレジスタをハットで表現する ˆqj x qj xqj+1 xqj+2 xqj+3 x qi+1 xqi+2 xqi+3 x 4つの座標データをymmレジスタにロードする 4つの座標データをymmレジスタにロードする ※ y, zも同様 ※ y, zも同様 ˆdx = ˆqj x ˆqi x ˆr2 = ˆdx 2 + ˆdy 2 + ˆdz 2 あとは同様に計算することで、4対の粒子間の力を同時に計算できる
  • 20. University of Tokyo 20/29 相互作用粒子のインデックスは連続ではない → 4つのデータをバラバラにロード D C B A D C B A メモリ レジスタ D C B A A メモリ xmm0 D C B A B A メモリ xmm0 vmovsd vmovhpd D C B A C メモリ D C B A D C メモリ vmovsd vmovhpd B A ymm0 xmm1 xmm1 D C D C xmm1 (1) Aをxmm0下位にロード (2) Bをxmm0上位にロード (3) Cをxmm1下位にロード (4) Dをxmm1上位にロード (5) xmm1全体をymm0上位128bitにコピー vinsertf128 実際に起きること 問題点 ※ これをx,y,z座標それぞれでやる ※ データの書き戻しも同様 力計算の単純SIMD化 (2/2) ※ vgatherdpdでなんとかできるかもしれないが・・・
  • 21. University of Tokyo 21/29 やったこと データを粒子数*4成分の二次元配列で宣言 double q[N][4], p[N][4]; z y x z y x メモリ z y x 0 1 2 z y x 3 粒子番号 うれしいこと (x,y,z)の3成分のデータをymmレジスタに一発ロード ただし、1成分(64bit) は無駄になる z y x z y x メモリ z y x 0 1 2 z y x 3 粒子番号 z y x movupd/movapd ymm0 力計算のSIMD化 (1/5)
  • 22. University of Tokyo 22/29 力の計算(1ペア) qj xqj yqj z qi xqi yqi z ˆqj ˆqi ˆdq = ˆqj ˆqi ˆdq 2 dx2dy2 dz2 dxdydz ここから r2 = dx2 + dy2 + dz2 を作りたい SIMDのシャッフル命令を使う 力計算のSIMD化 (2/5)
  • 23. University of Tokyo 23/29 シャッフル系命令 レジスターメモリ間の転送は極めてコストが高い なので、レジスタの中でデータを並び替えたい → 豊富なシャッフル系命令が用意されている D C B A ベクトルの並び替え (vpermpd) A B D B 同じ要素の重複可 二つのベクトルの要素を混ぜる (blendpd) D2 C2 B2 A2 D1 C1 B1 A1 D1 C2 B2 A1 どちらの要素をコピーするか選択化 力計算のSIMD化 (3/5)
  • 24. University of Tokyo 24/29 力の計算(1ペア) cont. dx2dy2 dz2 dx2 dx2 dy2 dz2 dy2 dz2 相対ベクトルの自乗を並び替える 全部足す r2 r2 r2 力の計算(4ペア) これを4つのペアについて行う r2 A r2 B r2 C r2 D r2 Ar2 A r2 Br2 B r2 Cr2 C r2 Dr2 D r2 Ar2 A r2 Cr2 C r2 Br2 B r2 Dr2 D unpacklpd vshufpd r2 Ar2 C r2 Br2 D あとは4ペア同時に力の計算ができる vpermpd 力計算のSIMD化 (4/5)
  • 25. University of Tokyo 25/29 力積の書き戻し dfAdfBdfCdfD dfAdfAdfAdfA ~pi = ~pi df ⇥ ~dq dxAdyAdzA (1) Aペアの力だけ取り出す vpermpd dfAdfAdfAdfApi xpi ypi z pi x pi ypi z= - × (2) 運動量をロード (3) 力積ベクトルの計算 pi xpi ypi z pi xpi ypi z メモリ ymmレジスタ (4) 運動量の書き戻し pi xpi ypi z pi xpi ypi z メモリ ymmレジスタ これを4ペアについて行う vfnmadd213pd vmovupd vmovupd 力計算のSIMD化 (5/5)
  • 26. University of Tokyo 26/29 マスク処理 Bookkeeping法により、相互作用範囲外のペアもいる→マスク処理 D2 C2 B2 A2 D1 C1 B1 A1 負 正 正 負 src1 src2 mask D2 C1 B1 A2 vblendvpd: マスクの要素の正負により要素を選ぶ ※ 実際にはmaskの最上位bitが0か1かで判定している 相互作用距離とカットオフ距離でマスクを作成し、力をゼロクリア dfAdfBdfCdfD 0 0 0 0 src1 src2 dfBdfC0 0 ペアAとDが相互作用範囲外 カットオフのマスク処理
  • 27. University of Tokyo 27/29 1 9 0 2 0 1 2 7 3 9 3 5 1 2 1 4 2 8 3 4 0 5 2 6 0 1 2 5 1 2 4 9 2 6 7 8 3 4 5 9 pair: ペア毎に力計算 sorted: 相互作用相手でソート next: 手で二段ソフトウェア パイプライニング intrin: 手でSIMD化 計算条件: ・密度1.0 ・カットオフ3.0 ・探索範囲3.3 ・12万粒子, 100回の力計算にかかった時間 86% 83% 70% 47% 実行結果 ソースファイル https://github.com/kaityo256/lj_simd
  • 28. University of Tokyo 28/29 SIMD化前 (33行) SIMD化後 (98行) ホットスポットのチューニングとしては許容範囲・・・? 実際のソースコード 行数は3倍に ここを4倍展開
  • 29. University of Tokyo 29/29 まとめと感想 ・ AVX命令を使ってLennard-Jones系の力計算をSIMD化した ・ レジスタとメモリの間のやり取りは高コスト  → ロード/ストアを減らすため、データ構造を工夫  → なるべくレジスタで処理をするため、シャッフル命令を活用 ・ SIMD化無しの最速コードに比べて速度向上は33% まとめ 感想 ・ やろうと思い立ってから、SIMD化が完成するまで1ヶ月ちょっと ・ 実働2週間程度? ・ 難しくはないが極めて面倒くさい  → 実際に早くなるかはやってみないとわからない ・ 「京」では128bit SIMD化により10〜15%程度の性能向上 ・ Intel Xeonでは256bit SIMD化により 30〜40%程度の性能向上 ・ 512bit SIMDでは二倍程度は差がでるのではないか?