2.2 ハイブリッド非構造格子 CFD ソルバのメモリ階層構造への対応および有限体積法における再帰参照と SIMD 化
宇宙航空研究開発機構
坂下雅秀

ポストペタアプリ WG の会合で報告した内容の概要について、以下に示す。
第四回会合（2014 年 12 月 10 日）では、「ハイブリッド非構造格子 CFD ソルバのメモリ階層構造への対応」と題して、CFD ソルバにおける固有の問題点と、キャッシュメモリへの対応方法についてまとめた。キャッシュの有効利用とは、キャッシュに乗せたデータでいかに多くの計算を行うかに尽きるが、CFD ソルバの採用する、いわゆるステンシル系の計算では、そもそもデータの再利用回数が少ないため、なかなか効率の良い方法が存在しないのが現状であり、前途多難である。
第七回会合（2015 年 10 月 8 日）では、「有限体積法における再帰参照と SIMD 化」と題して、多くの CFD ソルバが採用する有限体積法において SIMD 化に際して問題となる再帰参照と、その対処方法についてまとめた。また、実機（FX100）が利用可能となったため、非構造格子 CFD ソルバにおけて、実際に FX100 を使用した SIMD 化チューニングの一例について報告した。この例では、当該ソルバがサポートするいくつかの機能を諦めることによって SIMD 化の促進を図り、SIMD 化前に比べて計算時間で 1.5 倍、理論ピーク性能比では 6.3%という期待以上の性能が得られた。
一般に、実用に供するアプリは多数のユーザの多様な要求に答えるため、多くの機能を実装する必要に迫られる運命にある。このため、SIMD 化したい主要な DO ループが SIMD化の障害となりうる複雑な構造を持たざるを得なくなることが多い。そこで、特定ユーザを念頭に、思い切って機能を絞り込み、主要な DO ループを簡素化することによって SIMD化を促進し性能向上を図ることは、有力な選択肢のひとつである。
一方で、単純な DO ループしか SIMD 化できず性能の出ない SIMD アーキテクチャのシステムでは実用的とはいえない。そこで、いっさいの機能を諦めることなく、FX100 でどこまで SIMD 化し性能を出せるかについても重要なテーマであるといえる。

29 / 253

ハイブリッド非構造格子CFDソルバのメモリ階層構造への対応

宇宙航空研究開発機構
坂下雅秀

1

SS研ポストペタアプリ性能WG第4回会合資料2014年12月10日

非構造格子CFDソルバにおける問題点• 主要ループはすべてランダムアクセス
FACOM230-75 APUの時代から性能が出ない
とりあえず、キャッシュ（オンチップメモリ）にのせてreordering
メモリ階層構造への対応
やらなければいけないことはPhiでもGPUでもSX-ACEでもあまり変わらない• 時間積分に陰解法が使われることが多い
並列化が困難陽解法にしてしまうという方法はある
Krylov部分空間法を使うことにして前処理は？
2

SS研ポストペタアプリ性能WG第4回会合資料2014年12月10日
30 / 253

キャッシュに「のっていない」状態••••

データ xが 計算に必要となるメモリ（オフチップメモリ）→キャッシュ→レジスタ
データ yが 計算に必要となるメモリ→キャッシュ→レジスタ：• キャッシュがいっぱいになりデータxが追い出される：• 再びデータ xが 計算に必要となる• メモリ→キャッシュ→レジスタ

メモリ―キャッシュ間の転送回数が多い状態
3

SS研ポストペタアプリ性能WG第4回会合資料2014年12月10日

キャッシュに「のっている」状態
データ xが 計算に必要となる
メモリ→キャッシュ→レジスタ
データ yが 計算に必要となる
メモリ→キャッシュ→レジスタ：• 再びデータ xが 計算に必要となる• xがキャッシュに残っている••••

メモリ―キャッシュ間の転送回数が少ない状態
4

SS研ポストペタアプリ性能WG第4回会合資料2014年12月10日
31 / 253• 要するにキャッシュに「のっていない」 「のっている」とは転送回数が「多い」「少ない」ということ• 当該データが１回しか使われないなら意味がない

5

SS研ポストペタアプリ性能WG第4回会合資料2014年12月10日

回数で考えるメリット• 直観的でわかりやすいPAで出してくれたらいいな

6

SS研ポストペタアプリ性能WG第4回会合資料2014年12月10日
32 / 253回数の計算方法• スループットを使うと，データ転送がオーバーラップして隠れている部分は回数にカウントされない• キャッシュミス回数を使うと実際に転送されている回数が計算される
隠れているのならカウントされなくていい？
7

SS研ポストペタアプリ性能WG第4回会合資料2014年12月10日

回数の計算• L1⇔L2キャッシュ間データ転送量[byte]（PA）
L1$⇔L2$間スループット[GB/s]×浮動小数点L2$ヒット[s]• L2キャッシュ⇔メモリ間データ転送量[byte]（PA）メモリスループット[GB/s]×浮動小数点L2$ミス[s]• 定義・参照データサイズ
定義・参照データ（配列）のサイズ[byte]
直観的な指標なのでどんぶり勘定でOK

回数＝データ転送量÷定義・参照データサイズ
8

SS研ポストペタアプリ性能WG第4回会合資料2014年12月10日
33 / 253

例題：行列・行列積の計算C=AB
implicit NONE
integer, parameter :: N= 4096
!行列のサイズ
real*8,allocatable :: A(:,:), B(:,:), C(:,:)
integer :: i, j, k
allocate(A(N,N),B(N,N),C(N,N))(snip)
do j=1,N
do k=1,N
do i=1,NC(i,j) = C(i,j) + A(i,k)*B(k,j)
end doend doend do(snip)
9

SS研ポストペタアプリ性能WG第4回会合資料2014年12月10日

PA測定結果時間 (sec)

時間 (sec)
1.5E+02

3.0E-02

1.0E+022.0E-02

5.0E+01

1.0E-02

0.0E+00

0.0E+00

Process 0

Process 0

行列・行列積の計算N=4096

平均の計算 C(i)=0.5*(A(i)+B(i)), i=1, 107

L1$⇔L2$間転送回数≒65=4.08×109×69.0÷(8×32×40962)
L2$⇔メモリ間転送回数≒0.2=4.05×109×0.20÷(8×32×40962)
10

L1$⇔L2$間転送回数≒0.6=8.61×109×0.016÷(8×3×107)
L2$⇔メモリ間転送回数≒0.2=11.57×109×6.62×10‐4÷(8×3×107)
SS研ポストペタアプリ性能WG第4回会合資料2014年12月10日
34 / 253• 回数が多く性能に不満がある
タイリング（＋アクセスの連続化）
etc.

• 回数が少なく性能に不満がある
データの再利用が図れるようなループの融合
etc.
あとは具体的な事例集があればなんとかなる？
11

SS研ポストペタアプリ性能WG第4回会合資料2014年12月10日

行列・行列積のタイリング
implicit NONE
integer, parameter :: NN = 4096 ! 行列のサイズ
integer, parameter :: NT = 256 ! タイル（小行列）の数
integer, parameter :: NB = NN/NT ! タイル（小行列）のサイズreal*8,allocatable :: A(:,:,:,:), B(:,:,:,:), C(:,:,:,:)
integer :: i , j , k , l, m, nallocate( A(NB,NB,NT,NT), B(NB,NB,NT,NT), C(NB,NB,NT,NT) )(snip)
do n=1,NT; do m=1,NT; do l=1,NT
do j=1,NB
do k=1,NB
do i=1,NB
C(i,j,l,n) = C(i,j,l,n) + A(i,k,l,m)*B(k,j,m,n)
end doend doend doend do; end do; end do
12

SS研ポストペタアプリ性能WG第4回会合資料2014年12月10日
35 / 253

PA測定結果（N=4096、NB=16）100

時間 (sec)

806040200Process 0

行列・行列積の計算N=4096,NB=16
L1$⇔L2$間転送回数≒4.3(←65)=1.11×109×16.7÷(8×32×40962)
L2$⇔メモリ間転送回数≒2.4(←0.2)=0.9×109×11.6÷(8×32×40962)
13

ピーク性能比11%↓
ピーク性能比17%
ちなみにIvy Bride E5 2643V2ではNB=64のときピーク性能比28%

SS研ポストペタアプリ性能WG第4回会合資料2014年12月10日

行列・行列積の性質• ループ1回当たり2演算を大量（NB3回）に繰り返す• 計算に必要なデータは3 NB2語
配列要素aij（or bij）をNB回繰り返し利用
簡単な計算を大量に行うのでレジスタに余裕がある
データの利用回数が多いのでキャッシュにのせれば効果大
上手くいけばレジスタ上のデータも再利用してくれる？

タイリングの効果が出易い
行列・行列積の計算は演算量が計算に必要なデータ量に比べて多い計算
14

SS研ポストペタアプリ性能WG第4回会合資料2014年12月10日
36 / 253

オンチップメモリとタイリング• 本来の？オンチップメモリの使い方
計算とメモリアクセスのオーバーラップ（そもそも、オーバーラップするのに最低限必要なメモリ帯域が「（アプリケーションが）要求（する）メモリ帯域（B／F）」だったような？）オンチップメモリにのせるには、まずは小分け（タイリング）する必要がある
ユーザの手でオーバーラップさせるのはハードルが高いので• キャッシュメモリの場合、ハードおよびコンパイラが頼り性能が出ればそれでおしまい出なければ？

• タイル内のデータの利用回数を増やすことを考える
15

SS研ポストペタアプリ性能WG第4回会合資料2014年12月10日• プリフェッチはload/storeネックのアプリでは効果が薄い？
• 一番効果が出てほしいのは、そういうアプリだったりする

16

SS研ポストペタアプリ性能WG第4回会合資料2014年12月10日
37 / 253

ハイブリッド非構造格子の性質
ハイブリッド非構造格子とはピラミッド（4面体）、プリズム（三角柱）、六面体等種々の格子を組み合わせて形成された空間格子

性質
・複雑形状まわりの格子を精度よく生成し易い・領域分割が難しい（METISなどPDSを利用）
タイリングには再帰的領域分割が必須
17

SS研ポストペタアプリ性能WG第4回会合資料2014年12月10日

非構造格子の性質• ランダムアクセス
そんなハイブリッド非構造格子CFDソルバで性能を出すには？

18

SS研ポストペタアプリ性能WG第4回会合資料2014年12月10日
38 / 253

非構造格子CFDにおける移流項の計算• データの利用回数は10程度で少ない（2次精度）
タイリングによる効果が出難い
再帰的領域分割だけでは、あまり意味がない「袖」まで計算すれば同じデータを利用するループが統合できて利用回数を増やせる（マルチコアクラスタWG）• 演算量はループ1回あたり1,000程度で多い
計算式が複雑で途中結果が大量に発生
物理的に意味のあるループに分割し整理
19

SS研ポストペタアプリ性能WG第4回会合資料2014年12月10日

本当に早くなる？
試にやってみるにはハードルが高い
とりあえず移流項の計算部分を抜きだして格子点数を変化させてサブリージョンの生成を代用
境界条件の計算は無視
性能をリミットする要因が明確になっていないので果たして実アプリの傾向を継承しているのか不明
20

SS研ポストペタアプリ性能WG第4回会合資料2014年12月10日
39 / 253

ループの統合は有効か？
一連の計算の物理的に意味のある要素計算への分割は可能か？
くらいは見られる？
21

SS研ポストペタアプリ性能WG第4回会合資料2014年12月10日

おまけ（新システム評価結果の一部）

22

SS研ポストペタアプリ性能WG第4回会合資料2014年12月10日
40 / 253行列・行列積における配列の静的確保（Static）と動的確保（Dynamic）
StaticDynamic100

ピーク性能比[%]8060

4020FX1で測定

0101001,000

10,000

行列サイズN23

SS研ポストペタアプリ性能WG第4回会合資料2014年12月10日

タイリングを行った場合の行列・行列積の性能演算量と実行時間から計算した結果（tiling）とPAによる測定結果（tiling PA）
tilingtilingPA

25

ピーク性能比[%]2015105FX1で測定

01

10

100

1,000

タイルの数NT（行列サイズN=4096固定）
24

SS研ポストペタアプリ性能WG第4回会合資料2014年12月10日
41 / 253

有限体積法における再帰参照とSIMD化
宇宙航空研究開発機構
坂下 雅秀

SS研ポストペタアプリ性能WG第7回会合資料2015年10月8日

有限体積法における典型的な定義参照関係：勾配の計算
例： Green-Gauss公式（Gaussの発散定理）
1
xdV
x
dS

x

x  dS
V
S

V S
1
1
xi  x j S  nx


i
差分表記
Vi j 2CVjxj

CVixi(xi +xj)S・n/2

CVj’
xj’
(xi +xj’)S・n/2(xi+xj)S・n/2はControl Volume（CV）表面で求まり
CViとCVj両方の計算で参照される
242 / 253コーディング・パターン
パターンI

パターンIIdo icol=1,num_color
do jcol=col_list(1,icol),col_list(2,icol)
iface =face_list(jcol,icol)
icl=face2CV(1,iface)
icr=face2CV(2,iface)wdx=0.5*(x(icl)+x(icr))*Sn(iface)dx(icl)=dx(icl)+wdx
dx(icr)=dx(icr)+wdx
end doend dodo iface=1,num_face
icl=face2CV(1,iface)
icr=face2CV(2,iface)wdx=0.5*(x(icl)+x(icr))*Sn(iface)dx(icl)=dx(icl)+wdx
dx(icr)=dx(icr)+wdx
end do全ての面 iface で(xi+xj)Sn/2を計算
同時に左右のCVに計算結果を配る“パターンI”の再帰参照をcolorlingにより回避•非構造格子向き•スレッド並列化可能•収束性低下？
•キャッシュミス率高•もっとも素直なコーディング•スレッド並列化不可（再起参照）•キャッシュミス率低3

コーディング・パターン
パターンIII

パターンIVdo iface=1,num_face
icl=face2CV(1,iface)
icr=face2CV(2,iface)
wdx(iface)=0.5*(x(icl)+x(icr))*Sn(iface)end do!$omp parallel do schedule(dynamic,1000)
do icv=1,num_CV
do ifc=1,num_face_into_CV(icv)
iface=CV2face(ifc,icv)
dx(icv)=dx(icv)+wdx(iface)end doend dodo icv=1,num_CVdo ifc=1,num_face_into_CV(icv)
iface =CV2face(1,ifc,icv)
icr=CV2face(2,ifc,icv)
dx(icv)=dx(icv)+0.5*(x(icv)+x(icr))*Sn(iface)end doend do全ての面 iface で(xi+xj)Sn/2 を計算作業用配列に保存したのち各CVで和を計算

全てのCVで一度にΣ(xi+xj)Sn/2を計算•構造格子向き（二番目のloopが展開可能）•一番目のloopは高速・二番目のloopは低速•openMP(OMP)の動的割り当て適用により性能改善•スレッド並列化可能•計算量2倍•スレッド並列化可能•キャッシュミス率低443 / 253

非構造格子CFDソルバの処理の流れ
Ｎａｖier‐Stokes方程式 → 連立方程式：Ax=b・右辺（ベクトル）bの計算
勾配▽xi計算
CVi表面における物理量xf
勾配制限関数Ψiの計算
xf = xi+Ψi▽xi(ri-rf)
移流項（advection flux）の計算
粘性項（viscous flux）の計算
・時間積分
係数行列Aは配列に保存されずここで計算される（matrix free form）

LU‐SGS（部分因数分解による近似LU分解）陰解法

5移流項（advection）の計算
No.
修正箇所
0 (ASIS)時間
5.9secSIMD SWP
ピーク比
3.9%

1 内部サブルーチンを手動でインライン展開

5.9sec

3.9%

2 If文の削除（置き換え）
最内側ループのインライン展開

3.0sec8.1%

3 ループ分割（パターンIII）SWPのOCL文追加

2.2sec

前半：11.4%
後半： 6.5%○○○

その他、‐prefetch_indirectの追加、‐Nrtrapの削除など、最適化オプションの変更を行ったが、変化は0.1%以下。
644 / 253

移流項（advection）の計算
No.

修正箇所

時間

ピーク比

0(ASIS)

5.9sec

3.9%

SIMD

SWP

修正前（ASIS）

7

移流項（advection）の計算
No.
修正箇所
1 内部サブルーチンを手動でインライン展開

時間

ピーク比

5.9sec

3.9%

SIMD

SWP

faceloop1: do i_face = 1, n_face
call pre_advection_scheme（再構築）call hllew（リーマン解法）
call post_advection_scheme（流束和分）
end do faceloop1

赤字の部分を手動でインライン展開
もともと、コンパイルオプションで展開するようにしているが、その方法だと、最適化がかからない。
しかし、展開するだけでは、SWPやSIMDが有効とならないため、性能は変わらない

845 / 253

移流項の計算（pre_advection_scheme）
修正箇所

時間

2 If文の削除
最内側ループ展開

3.0secNo.

ピーク比

SIMDSWP○

8.1%

flag_neg = max(0,sign(1,pria_update(1)))*max(0,sign(1,pria_update(5)))!ocl unroll(5)do i = 1,5
pria_update_tmp(i,i_face) = flag_neg*pria_update(i) &&+ (1‐flag_neg)*pria(i)end doflag_neg = max(0,sign(1,prib_update(1)))*max(0,sign(1,prib_update(5)))!ocl unroll(5)do i = 1,5
prib_update_tmp(i,i_face) = flag_neg*prib_update(i) &&+ (1‐flag_neg)*prib(i)end do

If文をmax/min/sign関数で置き換える
面ループの中のdoループはocl文でunrolling←最内側ループは!ocl unrollで展開する←乱流モデルの変数は固定にする（例えば、全部２方程式を解く）

移流項（advection）の計算
No.
修正箇所
3 ループ分割（パターンIII）SWPのOCL文追加

時間

ピーク比
前半：11.4%
2.2sec後半： 6.5%

faceloop11: do i_face = 1, n_face
pre_advection_scheme（再構築）
end do faceloop11← 一時的に配列に保存

faceloop12: do i_face = 1, n_face
hllew（リーマン解法）
end do faceloop12← 一時的に配列に保存

cellloop1: do i_cell = 1, n_cell
post_advection_scheme（流束和分）
end do cellloop1

再帰参照を回避すため、CVループに変更

ループを分割することで、SIMDとSWPが有効になる

46 / 253

SIMD SWP○○

制限関数（limiter）の計算
前半：最大・最小を求める
修正箇所

No.

時間

ピーク比

0(ASIS)

0.8sec0%

1

外側ループでSWP化

0.5sec0%

2

面ループ→CVループ（パターンIV）

0.2sec

0%

SIMD

SWP
○○○

SIMD

SWP

後半：制限関数の計算
修正箇所

No.
0(ASIS)

1

ループ融合を無効化
ループ展開
ループ分割（パターンIII）

2

時間

ピーク比

3.4sec7.0%

2.6sec9.3%

1.9sec

13.7%

○
○

○

11

制限関数（limiter）の計算前半
No.
0

修正箇所
(ASIS)

時間
0.8sec

修正前（ASIS）

47 / 253

ピーク比0%SIMD

SWP

制限関数（limiter）の計算前半
修正箇所

No.

1 ループ融合を無効化
最内側ループの展開

時間

ピーク比0.5sec

0%

SIMD

SWP
○do i_face = 1, num_face!ocl LOOP_NOFUSION!ocl unroll(5)do i = 1, num_var! num_var=5, parameter属性, 引数渡し
cell_states_max(i,ia_cell) = max( cell_states_max(i,ia_cell), prib(i) )end do!ocl LOOP_NOFUSION!ocl unroll(5)do i = 1, num_var! num_var=5, parameter属性, 引数渡し
cell_states_min(i,ia_cell) = min( cell_states_min(i,ia_cell), prib(i) )end doend do!ocl loop_nofusionで、ループ融合を無効化!ocl unrollによりループ展開→面ループがSWP化される→実は、unrollだけでいいかも

制限関数（limiter）の計算前半
No.
修正箇所
2 面ループ→CVループ（パターンIV）

時間ピーク比SIMD

SWP

0.2sec0%○○

do i_cell = 1, num_cell
flag1 = max(0,sign(1,n_cell2face(i_cell)‐1))
flag2 = max(0,sign(1,n_cell2face(i_cell)‐2))（省略）
i0 = i_celli1 = (1‐flag1)*cell2cell(1,i_cell) + flag1*i_celli2 = (1‐flag2)*cell2cell(2,i_cell) + flag2*i_cell（省略）!ocl unroll(5)do i = 1, 5
cell_states_max(i,i_cell) = max ( cell_states(i,i0), &cell_states(i,i1), &cell_states(i,i2), &cell_states(i,i3), &cell_states(i,i4), &cell_states(i,i5), &cell_states(i,i6))
end doend doCVループに変更することで再帰参照を回避
48 / 253

制限関数（limiter）の計算後半
修正箇所(ASIS)

No.
0

時間
ピーク比
3.4sec
7%

SIMD

SWP

修正前（ASIS）

制限関数（limiter）の計算後半
No.
修正箇所
1 外側ループでSWP化

時間 ピーク比2.6sec9.3%!ocl SWP
faceloop5: do i_face = 1, num_face（省略）!ocl unroll(5)!ocl NOSWP!ocl NOSIMD
do i = 1, num_var! Num_var=5, parameter属性（省略）
slope_limiter(i,ib_cell) = min( slope_limiter(i,ib_cell), phi_tmpb )end doend do faceloop5!ocl unrollにより最内側ループを展開
内部ループのSWP化を無効化
外部ループでSWP化

49 / 253

SIMD

SWP○制限関数（limiter）の計算後半
No.

修正箇所

時間2

ループ分割（パターンIII）

1.9sec!ocl SWP
faceloop5: do i_face = 1, num_face（省略）!ocl unroll(5)do i = 1, 5
（省略）
phi_tmp(2,i,i_face) =end do
end do faceloop5!ocl loop_nofusion!ocl SWP
cellloop5: do i_cell = 1, num_cell（省略）!ocl unroll(5)do i = 1, 5
slope_limiter(i,i_cell) = &&min( (1‐fb1)*phi_tmp(1,i,i1) + fb1*phi_tmp(2,i,i1), &&(1‐fb2)*phi_tmp(1,i,i2) + fb2*phi_tmp(2,i,i2), &&(1‐fb3)*phi_tmp(1,i,i3) + fb3*phi_tmp(2,i,i3), &&(1‐fb4)*phi_tmp(1,i,i4) + fb4*phi_tmp(2,i,i4), &&(1‐fb5)*phi_tmp(1,i,i5) + fb5*phi_tmp(2,i,i5), &&(1‐fb6)*phi_tmp(1,i,i6) + fb6*phi_tmp(2,i,i6) )end doend do cellloop5

ピーク比

SIMD

SWP

13.7%

○

○面のループCVのループ勾配（gradient）の計算
No.

修正箇所

0(ASIS)

12

時間

ピーク比

SIMD

SWP

0.9sec

3.53%面ループを面ループとCVループに分割（パターンIII）

前半：0.4sec
後半：0.9sec

前半：5.8%後半：4.2%

前半：○
後半：○

前半：○
後半：×

後半にprefetch

前半：0.4sec
後半：0.6sec

前半：5.8%後半：5.5%

前半：○
後半：○

前半：○
後半：×

とりあえず、このルーチンだけ、高速化できなかった。

1850 / 253

勾配（gradient）の計算
No.
0

修正箇所
(ASIS)

時間
ピーク比
0.9sec
3.53%

SIMD

SWP

修正前（ASIS）

勾配（gradient）の計算
No.
1

修正箇所
ループ分割（パターンIII）

時間
前半：0.4sec
後半：0.9sec

前半

ピーク比
前半：5.8%後半：4.2%

SIMD

SWP

前半：○ 前半：○
後半：○ 後半：×後半
後半：
jwd8668o‐i "gradient.f90",line 788: 命令数が過剰なため,
ソフトウェ アパイプライニングを適用できません
SWPが効いていないため（？）
後半ループでメモリ待ちが目立つ.

2051 / 253

勾配（gradient）の計算
No.

修正箇所

時間ピーク比

SIMD

SWP

2

後半にprefetch

前半：0.4sec
後半：0.6sec

前半：5.8%後半：5.5%

前半：○
後半：○

前半：○
後半：×

後半

前半

Prefetch指定によりメモリ待ち改善
SWP化されれば、もう少しはマシになる？

21

粘性項（viscous）の計算
No. 修正箇所
0 (ASIS)
1
2

時間
0.9sec

ピーク比
7.0%0.7sec9.3%
If文削除
ループ分割 前半：0.4sec 前半：14.6%（パターンIII） 後半：0.1sec 後半： 4.6%

SIMD

SWP

前半：○
後半：○

○
前半：○
後半：○

2252 / 253

粘性項（viscous）の計算
No.
01

修正箇所
(ASIS)
If文削除

時間
ピーク比
0.9sec7.0%
0.7sec
9.3%

ASIS

SIMD

SWP
○IF文削除

SWP化によって演算待ち時間短縮

23

粘性項（viscous）の計算
No.
2

修正箇所
ループ分割（パターンIII）

時間
ピーク比
前半：0.4sec 前半：14.6%
後半：0.1sec 後半： 4.6%

前半

SIMD

SWP

前半：○
後半：○

前半：○
後半：○

後半

SIMD化によってさらに高速化

2453 / 253