122
10Poisson方程式の求解 (線形連立一次方程式) 長岡技術科学大学 電気電子情報工学専攻 出川智啓

2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

  • Upload
    -

  • View
    245

  • Download
    2

Embed Size (px)

Citation preview

Page 1: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

第10回 Poisson方程式の求解(線形連立一次方程式)

長岡技術科学大学 電気電子情報工学専攻 出川智啓

Page 2: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

今回の内容

2015/06/18先端GPGPUシミュレーション工学特論2

偏微分方程式の分類

Laplace方程式とその解法 Jacobi法,Gauss‐Seidel法,SOR法

2次元Laplace方程式

共役勾配法

SOR法(RB‐SOR法)

Page 3: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

偏微分方程式の簡単な分類

2015/06/18先端GPGPUシミュレーション工学特論3

2個の独立変数f(x,y)に対する2階線形偏微分方程式 A, B, C, D, E, F, Gは定数もしくはx, yの関数

高階(2階)微分の係数による分類

02

22

2

2

GFf

yfE

xfD

yfC

yxfB

xfA

B2‐4AC 型 物理的挙動

=0 放物型 時間発展

>0 双曲型 時間発展

<0 楕円型 空間平衡

Page 4: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

移流拡散方程式

−A=(>0), D=c, E=1, B=C=F=G=0 yをtと形式的に置換

移流項によってfが形を保ったまま速度cで移流

拡散項によってfの形状がなだらかに減衰

計算するためには初期値とt>0における境界値が必要

初期値・境界値問題

放物型

2015/06/18先端GPGPUシミュレーション工学特論4

2

2

xf

xfc

tf

Page 5: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

双曲型

2015/06/18先端GPGPUシミュレーション工学特論5

波動方程式

−A=c2, C=1, B=D=E=F=G=0 yをtと形式的に置換

時間的に振動する問題を記述

fは時刻t,位置xにおける振動の変位

cは振動の位相速度

計算するためには初期値とt>0における境界値が必要

初期値・境界値問題

2

22

2

2

xfc

tf

Page 6: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

楕円型

2015/06/18先端GPGPUシミュレーション工学特論6

Laplace方程式

A=1, C=1, B=D=E=F=G=0 G≠0の場合はPoisson方程式

式中に時間微分項が存在しない

fの平衡状態(時間的変化が0の定常状態)を表す

計算するためには境界値が重要

境界値問題

02

2

2

2

yf

xf

Page 7: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

Laplace方程式

2015/06/18先端GPGPUシミュレーション工学特論7

順問題 関数fの値・形が既知

2階微分を計算

逆問題 関数fのラプラシアンが0 関数fの形状を推定

?2

2

2

2

yf

xf

f

02

2

2

2

yf

xf

?f

Page 8: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

Laplace方程式の離散化

x方向2階偏微分の離散化 y方向を固定してx方向に偏微分

y方向2階偏微分の離散化 x方向を固定してy方向に偏微分

2,1,,1

22

2 2),(),(2),(Δx

fffΔx

yΔxxfyxfyΔxxfxf jijiji

21,,1,

22

2 2),(),(2),(Δy

fffΔy

ΔyyxfyxfΔyyxfyf jijiji

先端GPGPUシミュレーション工学特論8 2015/06/18

Page 9: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

Laplace方程式の離散化

Laplace方程式

離散化までは拡散方程式と同じ fが未知

離散化されたf同士の関係(差分式)と境界条件から推定

022

21,,1,

2,1,,1

2

2

2

2

Δyfff

Δxfff

yf

xf jijijijijiji

先端GPGPUシミュレーション工学特論9 2015/06/18

Page 10: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

1次元Laplace方程式

2015/06/18先端GPGPUシミュレーション工学特論10

x方向のみを考慮

L=4を5個の離散点に分割 各位置iでの差分式(i=1,5では境界条件が必要)

02

02

02

2543

2432

2321

Δxfff

Δxfff

Δxfff

022

112

2

Δxfff

xf iii

Page 11: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

1次元Laplace方程式

2015/06/18先端GPGPUシミュレーション工学特論11

境界条件(左の境界でf=0, 右の境界でf=1)を課す

f1~f5を未知数とした連立一次方程式

1

02

02

020

5

2543

2432

2321

1

fΔx

fffΔx

fffΔx

ffff

L

f

Page 12: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

1次元Laplace方程式

2015/06/18先端GPGPUシミュレーション工学特論12

行列を用いた表記 係数行列Aの逆行列A−1を左からかければfが求められる

逆行列の計算は計算負荷が高く,多くの誤差が混入

連立一次方程式の求解法を利用してfを求める

10000

1121

121121

1

5

4

3

2

1

fffff

Ax=b

Page 13: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

連立一次方程式の解法

2015/06/18先端GPGPUシミュレーション工学特論13

直接法

係数行列を単位行列(や上三角,下三角行列)に変形することで未知数を求める方法

所定の計算回数で解が得られる

計算量が多く,大規模な問題には適用できない

反復法

係数行列を変更せず,未知数に推定値を代入して所定の計算を行い,推定値が厳密解に十分近づくまで計算を繰り返す方法

よい推定値を選べば非常に高速に解が得られる

Page 14: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

Jacobi法

2015/06/18先端GPGPUシミュレーション工学特論14

未知数=...の形に変形し近似値を繰り返し計算 初期の推定値f(0)を基にf(1), f(2), f(3),..., f(m)を計算

f(m)の誤差が十分小さくなればf(m)を解とする(反復が収束)

f(m)を元の方程式に代入して右辺と比較する 等

5.020

020020

5)0(

3)1(

4

)0(4

)0(2

)1(3

)0(31

)1(2

fffffffff

1

02

02

020

5

2543

2432

2321

1

fΔx

fffΔx

fffΔx

ffff

Page 15: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

Jacobi法

2015/06/18先端GPGPUシミュレーション工学特論15

未知数=...の形に変形し近似値を繰り返し計算 初期の推定値f(0)を基にf(1), f(2), f(3),..., f(m)を計算

f(m)の誤差が十分小さくなればf(m)を解とする(反復が収束)

f(m)を元の方程式に代入して右辺と比較する 等

5.020

25.020020

5)1(

3)2(

4

)1(4

)1(2

)2(3

)1(31

)2(2

fffffffff

1

02

02

020

5

2543

2432

2321

1

fΔx

fffΔx

fffΔx

ffff

Page 16: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

Jacobi法

2015/06/18先端GPGPUシミュレーション工学特論16

未知数=...の形に変形し近似値を繰り返し計算 初期の推定値f(0)を基にf(1), f(2), f(3),..., f(m)を計算

f(m)の誤差が十分小さくなればf(m)を解とする(反復が収束)

f(m)を元の方程式に代入して右辺と比較する 等

625.020

25.020125.020

5)2(

3)3(

4

)2(4

)2(2

)3(3

)2(31

)3(2

fffffffff

1

02

02

020

5

2543

2432

2321

1

fΔx

fffΔx

fffΔx

ffff

Page 17: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

Jacobi法

2015/06/18先端GPGPUシミュレーション工学特論17

未知数=...の形に変形し近似値を繰り返し計算 初期の推定値f(0)を基にf(1), f(2), f(3),..., f(m)を計算

f(m)の誤差が十分小さくなればf(m)を解とする(反復が収束)

f(m)を元の方程式に代入して右辺と比較する 等

625.020

375.020125.020

5)4(

3)4(

4

)4(4

)4(2

)4(3

)4(31

)4(2

fffffffff

1

02

02

020

5

2543

2432

2321

1

fΔx

fffΔx

fffΔx

ffff

Page 18: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

Gauss-Seidel法

2015/06/18先端GPGPUシミュレーション工学特論18

既に計算したf(m+1)の値を同一反復内で利用 更新した値を順次使用するため収束が速くなる

5.020

020020

5)1(

3)1(

4

)0(4

)1(2

)1(3

)0(31

)1(2

fffffffff

625.020

25.020020

5)2(

3)2(

4

)1(4

)2(2

)2(3

)1(31

)2(2

fffffffff

Gauss‐Seidel法Jacobi法

5.020

020020

5)0(

3)1(

4

)0(4

)0(2

)1(3

)0(31

)1(2

fffffffff

5.020

25.020020

5)1(

3)2(

4

)1(4

)1(2

)2(3

)1(31

)2(2

fffffffff

Page 19: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

Gauss-Seidel法

2015/06/18先端GPGPUシミュレーション工学特論19

既に計算したf(m+1)の値を同一反復内で利用 更新した値を順次使用するため収束が速くなる

0.68820

0.37520125.020

5)3(

3)3(

4

)2(4

)3(2

)3(3

)2(31

)3(2

fffffffff

0.71920

0.438200.187520

5)4(

3)4(

4

)3(4

)4(2

)4(3

)3(31

)4(2

fffffffff

Gauss‐Seidel法Jacobi法

625.020

25.020125.020

5)2(

3)3(

4

)2(4

)2(2

)3(3

)2(31

)3(2

fffffffff

625.020

375.020125.020

5)3(

3)4(

4

)3(4

)3(2

)4(3

)3(31

)4(2

fffffffff

Page 20: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

SOR法(逐次過緩和法, Successive 0ver-Relaxation)

2015/06/18先端GPGPUシミュレーション工学特論20

近似解の修正量に係数をかけて過剰に修正 加速係数が0<<2の範囲で収束

1<<2を取ると収束が加速

0<<1なら収束が減速

696.020

36.020020

)1(45

)2(3

)1(4

)2(4

)1(3

)1(4

)2(2

)1(3

)2(3

)1(2

)1(31

)1(2

)2(2

fffffffffffffff

6.020

020020

)0(45

)1(3

)0(4

)1(4

)0(3

)0(4

)1(2

)0(3

)1(3

)0(2

)0(31

)0(2

)1(2

fffffffffffffff

2.1

を採用

Page 21: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

SOR法(逐次過緩和法, Successive 0ver-Relaxation)

2015/06/18先端GPGPUシミュレーション工学特論21

近似解の修正量に係数をかけて過剰に修正 加速係数が0<<2の範囲で収束

1<<2を取ると収束が加速

0<<1なら収束が減速

749.020

498.020242.020

)3(45

)4(3

)3(4

)4(4

)3(3

)3(4

)4(2

)3(3

)4(3

)3(2

)3(31

)3(2

)4(2

fffffffffffffff

746.020

475.020216.020

)2(45

)3(3

)2(4

)3(4

)2(3

)2(4

)3(2

)2(3

)3(3

)2(2

)2(31

)2(2

)3(2

fffffffffffffff

2.1

を採用

Page 22: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

共役勾配法

2015/06/18先端GPGPUシミュレーション工学特論22

Jacobi法などとは異なる種類の反復解法

係数行列が対称である連立一次方程式が対象

丸め誤差が無ければ所定の回数で収束 丸め誤差に弱く,所定の回数で収束しないこともある

Page 23: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

共役勾配法のアルゴリズム

2015/06/18先端GPGPUシミュレーション工学特論23

連立一次方程式Ax=bに対する共役勾配法

Compute r0=b−Ax0. Set p0−1=0,−1=0.

For m=0,1,…, until ||r||/||b|| < , Do

p(m) = r(m)+(m−1)p(m−1)

(m) = (r(m), r(m))/(p(m), Ap(m))

x(m+1) = x(m)+(m)p(m)

r(m+1) = r(m)−(m)Ap(m)

(m) = (r(m+1), r(m+1))/{(m)(p(m), Ap(m))}

EndDo

Ap 係数行列Aとベクトルpの積

( , ) ベクトル同士の内積

A 係数行列x 解ベクトルb 右辺ベクトルr 残差ベクトルp 補助ベクトル||・|| l2−ノルム

Page 24: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

2次元Laplace方程式

2015/06/18先端GPGPUシミュレーション工学特論24

1方向から加熱される金属板の温度分布 Laplace方程式

境界条件

1℃

0℃0℃

0℃

B2

B1

B3

B4

4

3

2

1

on 0on 0on 1on 0

BTBTBTBT

02

2

2

2

yT

xT

xy

Page 25: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

2次元Laplace方程式

2015/06/18先端GPGPUシミュレーション工学特論25

1方向から加熱される金属板の温度分布 Laplace方程式

計算条件

計算領域 Lx=2, Ly=2 離散点の数 Nx=3, Ny=3 格子間隔 x=y=h

02

2

2

2

yT

xT

xy

0

i

1 20

1

2

j

Page 26: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

2次元Laplace方程式

2015/06/18先端GPGPUシミュレーション工学特論26

1方向から加熱される金属板の温度分布 Laplace方程式

Laplace方程式の差分式

02

2

2

2

yT

xT

0

i

1 2

0

1

2

j

T[i][j]

022

21,,1,

2,1,,1

yTTT

xTTT jijijijijiji

04

21,,1,1,,1

hTTTTT jijijijiji

Page 27: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

2次元Laplace方程式

2015/06/18先端GPGPUシミュレーション工学特論27

1方向から加熱される金属板の温度分布 Laplace方程式

Laplace方程式の差分式

0

i

1 2

0

1

2

j

T[]

0 1 2

3 4 5

6 7 8

0222

1472

345

yTTT

xTTT

042

13475

h

TTTTT

02

2

2

2

yT

xT

Page 28: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

連立一次方程式

2015/06/18先端GPGPUシミュレーション工学特論28

Tに関する9元連立一次方程式を解く

111000000

11

11

114111

11

1

8

7

6

5

4

3

2

1

0

TTTTTTTTT

Ax=b

Page 29: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

連立一次方程式

2015/06/18先端GPGPUシミュレーション工学特論29

行列Aを保持する必要は無い SOR法はT=… の形を作り,反復計算を行う

変形した式をプログラムに記述周囲が全て固定値の境界条件なので1回の反復で収束

1110

40000

7531

8

7

6

5

)(4

3

2

1

0

TTTT

TTTTTTTTT

m

Page 30: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

連立一次方程式

2015/06/18先端GPGPUシミュレーション工学特論30

行列Aを保持する必要は無い 共役勾配法は行列-ベクトル積Axの結果がわかればよい

行列-ベクトル積を計算して得られた式をプログラムに記述

8

7

6

5

75431

3

2

1

0

8

7

6

5

4

3

2

1

0

4

11

11

114111

11

1

TTTT

TTTTTTTTT

TTTTTTTTT

Page 31: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

#include<stdio.h>#include<stdlib.h>#include<math.h>

#define Lx 2.0#define Ly Lx#define Nx 11#define Ny Ny#define dx (Lx/(Nx‐1))#define dy dx#define dxdx (dx*dx)#define dydy (dy*dy)#define Nbytes (Nx*Ny*sizeof(double))#define ERR_TOL 1e‐12#define Accel 1.0

void sor(double *T);void cg(double *T);void init(double *T){

for(int j=0;j<Ny;j++){for(int i=0;i<Nx;i++){

T[i+Nx*j] = 0.0;}}

}

int main(void){

double *T;T = (double *)malloc(Nbytes);

init(T);sor(T)//cg(T);

return 0;}

CPUプログラム(メイン・初期化)

2015/06/18先端GPGPUシミュレーション工学特論31

laplace.c

Page 32: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

void sor(double *T){int ite_SOR=0;double err_n,err_d,err_relative;double d_t;int ij,ip1j,im1j,ijm1,ijp1;//境界条件の適用for(int i=0;i<Nx;i++){ij = i+Nx*(Ny‐1); //j=Ny‐1T[i+Nx*j] = 1.0;

}

do{err_n = 0.0;err_d = 0.0;

for(int j=1;j<Ny‐1;j++){for(int i=1;i<Nx‐1;i++){ij = i+Nx*j;ip1j = (i+1)+Nx*(j  );im1j = (i‐1)+Nx*(j  );

ijp1 = (i )+Nx*(j+1);ijm1 = (i )+Nx*(j‐1);d_t =( (T[im1j]+T[ip1j])

+(T[ijm1]+T[ijp1]))/(‐4.0) ‐T[ij];

T[ij] += Accel*d_t;err_n += d_t*d_t;err_d += T[ij]*T[ij];

}}

if(err_d<1e‐20)err_d=1.0;err_relative = sqrt(err_n/err_d);ite_SOR++;

}while(err_relative > ERR_TOL);}

CPUプログラム(SOR法)

2015/06/18先端GPGPUシミュレーション工学特論32

laplace.c

Page 33: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

void cg(double *T){double err;int ij,ip1j,im1j,ijm1,ijp1;double *p,*r,*Ap;double alph,beta,rr,pAp;//境界条件の適用for(int i=0;i<Nx;i++){ij=i+Nx*(Ny‐1);//j=Ny‐1T[i+Nx*j] = 1.0;

}

p  = (double *)malloc(Nbytes);r  = (double *)malloc(Nbytes);Ap = (double *)malloc(Nbytes);for(int j=0;j<Ny;j++){for(int i=0;i<Nx;i++){ij = i+Nx*j;p [ij] = 0.0;r [ij] = 0.0;Ap[ij] = 0.0;

}}alph=0.0;beta=0.0;

rr = 0.0;for(int j=1;j<Ny‐1;j++){for(int i=1;i<Nx‐1;i++){ij = i+Nx*j;ip1j = (i+1)+Nx*(j  );im1j = (i‐1)+Nx*(j  );ijp1 = (i )+Nx*(j+1);ijm1 = (i )+Nx*(j‐1);r[ij] = ‐( (T[im1j]‐2*T[ij]+T[ip1j])/dxdx

+(T[ijm1]‐2*T[ij]+T[ijp1])/dydy);

rr += r[ij]*r[ij];}}

CPUプログラム(共役勾配法)

2015/06/18先端GPGPUシミュレーション工学特論33

laplace.c

Page 34: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

do{for(int j=0;j<Ny;j++){for(int i=0;i<Nx;i++){ij = i+Nx*j;p [ij] = r[ij] + beta*p[ij];

}}

pAp = 0.0;for(int j=1;j<Ny‐1;j++){for(int i=1;i<Nx‐1;i++){ij = i+Nx*j;ip1j = (i+1)+Nx*(j  );im1j = (i‐1)+Nx*(j  );ijp1 = (i )+Nx*(j+1);ijm1 = (i )+Nx*(j‐1);Ap[ij] = (p[im1j]‐2*p[ij]+p[ip1j])/dxdx

+(p[ijm1]‐2*p[ij]+p[ijp1])/dydy;

pAp += p[ij]*Ap[ij];

}}alph = rr/pAp;

rr = 0.0;for(int j=0;j<Ny;j++){for(int i=0;i<Nx;i++){ij = i+Nx*j;T[ij] = T[ij] + alph* p[ij];r[ij] = r[ij] ‐ alph*Ap[ij];rr += r[ij]*r[ij];

}}err = sqrt(rr);beta = rr/(alph*pAp);

}while(err > ERR_TOL);}

CPUプログラム(共役勾配法)

2015/06/18先端GPGPUシミュレーション工学特論34

laplace.c

Page 35: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

反復の収束判定

2015/06/18先端GPGPUシミュレーション工学特論35

誤差 真の値からのズレ

近似値 =真値r+誤差

誤差

絶対誤差

相対誤差

rr ˆ

rr ˆ

rrr ˆ

Page 36: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

反復の収束判定

2015/06/18先端GPGPUシミュレーション工学特論36

ベクトル量における誤差の評価 lp−ノルム(pは整数)

l1−ノルム

l2−ノルム

l∞−ノルム

pN

i

p

iip xxl ˆx2

x1

x

22111 ˆˆ xxxxl

2

22

2

112 ˆˆ xxxxl

2211 ˆ,ˆmax xxxxl

11 x̂x

22 x̂x

x1方向のズレとx2方向のズレの合計

2次元平面における距離

x1方向のズレとx2方向のズレの大きい方

Page 37: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

反復の収束判定

2015/06/18先端GPGPUシミュレーション工学特論37

l2−ノルムを用いた相対誤差評価

m+1回目の反復の値が真値になれば誤差と一致

反復中に変化量が十分小さくなれば収束と判定

x2

y x

y x

N

j

N

i

mji

N

j

N

i

mji

mji

T

TT

2)1(,

2)(,

)1(,

err_n = 0.0;err_d = 0.0;

for(int j=1;j<Ny‐1;j++){for(int i=1;i<Nx‐1;i++){

d_t =( (T[im1j]+T[ip1j])+(T[ijm1]+T[ijp1])

)/(‐4.0)  ‐T[ij];T[ij] += Accel*d_t;err_n += d_t*d_t;err_d += T[ij]*T[ij];

}}

if(err_d<1e‐20)err_d=1.0;err_relative = sqrt(err_n/err_d);

Page 38: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

反復の収束判定

2015/06/18先端GPGPUシミュレーション工学特論38

残差 方程式の解に近似値を用いたことによって生じる不整合

残差rの定義

誤差と残差 誤差の計算には真の解が必要

残差は方程式の係数と右辺値がわかれば計算できる

xAbr ˆ

Page 39: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

反復の収束判定

2015/06/18先端GPGPUシミュレーション工学特論39

残差の2乗ノルムを用いた収束判定 右辺の2乗ノルムを用いた相対残差を計算 x2

y x

y x

N

j

N

iji

N

j

N

i

mji

b

r

2,

2)1(,

rr = 0.0;for(int j=1;j<Ny‐1;j++){for(int i=1;i<Nx‐1;i++){

ij = i+Nx*j;ip1j = (i+1)+Nx*(j  );im1j = (i‐1)+Nx*(j  );ijp1 = (i )+Nx*(j+1);ijm1 = (i )+Nx*(j‐1);r[ij] = ‐( (T[im1j]‐2*T[ij]+T[ip1j])/dxdx

+(T[ijm1]‐2*T[ij]+T[ijp1])/dydy);rr += r[ij]*r[ij];

}}・・・//右辺が0でなければ右辺のl2ノルムbbで//割った値の平方根sqrt(rr/bb)を評価err = sqrt(rr);

Page 40: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

計算結果

2015/06/18先端GPGPUシミュレーション工学特論40

前回授業で用いたgnuplotのanim_2d.gplを流用して2次元分布を確認

set xrange [0:2] x軸の表示範囲を0~2に固定set yrange [0:2] y軸の表示範囲を0~2に固定set zrange [0:1] z軸の表示範囲を0~1に固定set view 0,0 真上から見下ろすset size 1,1 グラフの縦横比を1:1set contour 2次元等高線を表示unset surface 3次元で等値面を表示しないunset pm3d カラー表示しないset cntrparam levels incremental 0,0.1,1

等高線を0から1まで0.1刻みに設定以下でファイルを読み込み,3次元表示splot 'T.txt' with line  

Page 41: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

計算結果

2015/06/18先端GPGPUシミュレーション工学特論41

前回授業で用いたgnuplotのanim_2d.gplを流用して2次元分布を確認

set xrange [0:2] x軸の表示範囲を0~2に固定set yrange [0:2] y軸の表示範囲を0~2に固定set zrange [0:1] z軸の表示範囲を0~1に固定set view 0,0 真上から見下ろすset size 1,1 グラフの縦横比を1:1unset contour 2次元等高線を表示unset surface 3次元で等値面を表示しないset pm3d カラー表示しない以下でファイルを読み込み,3次元表示splot 'T.txt' with line  

Page 42: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

Poisson方程式への拡張

2015/06/18先端GPGPUシミュレーション工学特論42

Poisson方程式

離散化 右辺が0ではなく関数gの値

gyf

xf

2

2

2

2

jijijijijijiji g

Δyfff

Δxfff

yf

xf

.21,,1,

2,1,,1

2

2

2

2 22

Page 43: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

SOR法で用いる式の拡張

2015/06/18先端GPGPUシミュレーション工学特論43

xとyが等しくない場合 差分式を変形してfi,j=… の形に変形

jijijijijijiji g

Δyfff

Δxfff

.21,,1,

2,1,,1 22

21,1,

2,1,1

.,22

112Δyff

Δxff

gfΔyΔx

jijijijijiji

22

22

21,1,

2,1,1

.,2

ΔyΔxΔyΔx

Δyff

Δxff

gf jijijijijiji

Page 44: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

#define dxdxdydy (dxdx*dydy)#define dxdy2 (2.0*(dxdx+dydy))

void sor(double *f, double *g){int ite_SOR=0;double err_n,err_d,err_relative;double d_f;int ij,ip1j,im1j,ijm1,ijp1;do{err_n = 0.0;err_d = 0.0;for(int j=1;j<Ny‐1;j++){for(int i=1;i<Nx‐1;i++){ij = i+Nx*j;ip1j = (i+1)+Nx*(j  );im1j = (i‐1)+Nx*(j  );ijp1 = (i )+Nx*(j+1);ijm1 = (i )+Nx*(j‐1);d_f =( (f[im1j]+f[ip1j])/dxdx

+(f[ijm1]+f[ijp1])/dydy‐(g[ij]) //右辺の影響)*dxdxdydy/dxdy2 ‐f[ij];

f[ij] += Accel*d_f;err_n += d_f*d_f;err_d += f[ij]*f[ij];

}}

if(err_d<1e‐20)err_d=1.0;err_relative = sqrt(err_n/err_d);ite_SOR++;

}while(err_relative > ERR_TOL);

}

CPUプログラム(SOR法)

2015/06/18先端GPGPUシミュレーション工学特論44

poisson.c

Page 45: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

void cg(double *f, double *g){double err;int ij,ip1j,im1j,ijm1,ijp1;double alph,beta,rr,pAp,bb;

double *p  = (double *)malloc(Nx*Ny*sizeof(double));

double *r  = (double *)malloc(Nx*Ny*sizeof(double));

double *Ap = (double *)malloc(Nx*Ny*sizeof(double));

for(int j=0;j<Ny;j++){for(int i=0;i<Nx;i++){ij = i+Nx*j;p [ij] = 0.0;r [ij] = 0.0;Ap[ij] = 0.0;

}}

alph=0.0;beta=0.0;

bb = 0.0;rr = 0.0;for(int j=1;j<Ny‐1;j++){for(int i=1;i<Nx‐1;i++){ij = i+Nx*j;ip1j = (i+1)+Nx*(j  );im1j = (i‐1)+Nx*(j  );ijp1 = (i )+Nx*(j+1);ijm1 = (i )+Nx*(j‐1);r[ij] = g[ij] //右辺の影響‐( (f[im1j]‐2*f[ij]+f[ip1j])/dxdx

+(f[ijm1]‐2*f[ij]+f[ijp1])/dydy);rr += r[ij]*r[ij];bb += g[ij]*g[ij];

}}

CPUプログラム(共役勾配法)

2015/06/18先端GPGPUシミュレーション工学特論45

poisson.c

Page 46: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

do{for(int j=0;j<Ny;j++){for(int i=0;i<Nx;i++){ij = i+Nx*j;p [ij] = r[ij] + beta*p[ij];

}}

pAp = 0.0;for(int j=1;j<Ny‐1;j++){for(int i=1;i<Nx‐1;i++){ij = i+Nx*j;ip1j = (i+1)+Nx*(j  );im1j = (i‐1)+Nx*(j  );ijp1 = (i )+Nx*(j+1);ijm1 = (i )+Nx*(j‐1);//右辺の影響は入らないAp[ij] = (p[im1j]‐2*p[ij]+p[ip1j])/dxdx

+(p[ijm1]‐2*p[ij]+p[ijp1])/dydy;

pAp += p[ij]*Ap[ij];}}alph = rr/pAp;

rr = 0.0;for(int j=0;j<Ny;j++){for(int i=0;i<Nx;i++){ij = i+Nx*j;f[ij] = f[ij] + alph* p[ij];r[ij] = r[ij] ‐ alph*Ap[ij];rr += r[ij]*r[ij];

}}err = sqrt(rr/bb);beta = rr/(alph*pAp);

}while(err > ERR_TOL);}

CPUプログラム(共役勾配法)

2015/06/18先端GPGPUシミュレーション工学特論46

poisson.c

Page 47: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

CPUプログラム

右辺(ソース項)g

境界条件

for(i=0;i<Nx;i++){for(j=0;j<Ny;j++){

x = (double)i*dx;y = (double)j*dy;g[i*Ny+j] = 2.0*sin(2.0*M_PI*x/Lx)

*sin(2.0*M_PI*y/Ly);}}

先端GPGPUシミュレーション工学特論47 2015/06/18

yxg sinsin2

0sinsin22 yxf

2

2

g2−2

Page 48: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

#include<stdio.h>#include<stdlib.h>#include<math.h>

#define Lx (2.0*M_PI)#define Ly Lx#define Nx 11#define Ny Ny#define dx (Lx/(Nx‐1))#define dy dx#define dxdx (dx*dx)#define dydy (dy*dy)#define dxdxdydy (dxdx*dydy)#define dxdy2 (2.0*(dxdx+dydy))#define Nbytes (Nx*Ny*sizeof(double))#define ERR_TOL 1e‐12#define Accel 1.0void sor(double *f,double *g);void cg(double *f,double *g);

void init(double *f,double *g){for(int j=0;j<Ny;j++){for(int i=0;i<Nx;i++){g[i+Nx*j] = 2.0*sin(2.0*M_PI*x/Lx)

*sin(2.0*M_PI*y/Ly);f[i+Nx*j] = 0.0;

}}

}int main(void){

double *f, *g;f = (double *)malloc(Nbytes);g = (double *)malloc(Nbytes);

init(f,g);sor(f,g)//cg(f,g);return 0;

}

CPUプログラム(メイン・初期化)

2015/06/18先端GPGPUシミュレーション工学特論48

poisson.c

Page 49: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

void sor(double *f, double *g){int ite_SOR=0;double err_n,err_d,err_relative;double d_f;int ij,ip1j,im1j,ijm1,ijp1;

//境界値は全て0固定なので何もしない

do{err_n = 0.0;err_d = 0.0;for(int j=1;j<Ny‐1;j++){for(int i=1;i<Nx‐1;i++){ij = i+Nx*j;ip1j = (i+1)+Nx*(j  );im1j = (i‐1)+Nx*(j  );ijp1 = (i )+Nx*(j+1);ijm1 = (i )+Nx*(j‐1);

d_f =( (f[im1j]+f[ip1j])/dxdx+(f[ijm1]+f[ijp1])/dydy‐(g[ij]))*dxdxdydy/dxdy2 ‐f[ij];

f[ij] += Accel*d_f;err_n += d_f*d_f;err_d += f[ij]*f[ij];

}}

if(err_d<1e‐20)err_d=1.0;err_relative = sqrt(err_n/err_d);ite_SOR++;

}while(err_relative > ERR_TOL);

}

CPUプログラム(SOR法)

2015/06/18先端GPGPUシミュレーション工学特論49

poisson.c

Page 50: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

void cg(double *f, double *g){double err;int ij,ip1j,im1j,ijm1,ijp1;double *p,*r,*Ap;double alph,beta,rr,pAp,bb;

p  = (double *)malloc(Nbytes);r  = (double *)malloc(Nbytes);Ap = (double *)malloc(Nbytes);for(int j=0;j<Ny;j++){for(int i=0;i<Nx;i++){ij = i+Nx*j;p [ij] = 0.0;r [ij] = 0.0;Ap[ij] = 0.0;

}}alph=0.0;beta=0.0;

//境界値は全て0固定なので何もしないbb = 0.0;rr = 0.0;for(int j=1;j<Ny‐1;j++){for(int i=1;i<Nx‐1;i++){ij = i+Nx*j;ip1j = (i+1)+Nx*(j  );im1j = (i‐1)+Nx*(j  );ijp1 = (i )+Nx*(j+1);ijm1 = (i )+Nx*(j‐1);r[ij] = g[ij]‐((f[im1j]‐2*f[ij]+f[ip1j])/dxdx

+(f[ijm1]‐2*f[ij]+f[ijp1])/dydy);

rr += r[ij]*r[ij];bb += g[ij]*g[ij];

}}

CPUプログラム(共役勾配法)

2015/06/18先端GPGPUシミュレーション工学特論50

poisson.c

Page 51: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

do{for(int j=0;j<Ny;j++){for(int i=0;i<Nx;i++){ij = i+Nx*j;p [ij] = r[ij] + beta*p[ij];

}}

pAp = 0.0;for(int j=1;j<Ny‐1;j++){for(int i=1;i<Nx‐1;i++){ij = i+Nx*j;ip1j = (i+1)+Nx*(j  );im1j = (i‐1)+Nx*(j  );ijp1 = (i )+Nx*(j+1);ijm1 = (i )+Nx*(j‐1);

Ap[ij] = (p[im1j]‐2*p[ij]+p[ip1j])/dxdx

+(p[ijm1]‐2*p[ij]+p[ijp1])/dydy;

pAp += p[ij]*Ap[ij];}}alph = rr/pAp;

rr = 0.0;for(int j=0;j<Ny;j++){for(int i=0;i<Nx;i++){ij = i+Nx*j;f[ij] = f[ij] + alph* p[ij];r[ij] = r[ij] ‐ alph*Ap[ij];rr += r[ij]*r[ij];

}}err = sqrt(rr/bb);beta = rr/(alph*pAp);

}while(err > ERR_TOL);}

CPUプログラム(共役勾配法)

2015/06/18先端GPGPUシミュレーション工学特論51

poisson.c

Page 52: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

計算結果

2015/06/18先端GPGPUシミュレーション工学特論52

前回授業で用いたgnuplotのanim_2d.gplを流用して2次元分布を確認

set xrange [0:2*pi] x軸の表示範囲を0~2に固定set yrange [0:2*pi] y軸の表示範囲を0~2に固定set zrange [‐1:1] z軸の表示範囲を‐1~1に固定set view 0,0 真上から見下ろすset size 1,1 グラフの縦横比を1:1set contour 2次元等高線を表示unset surface 3次元で等値面を表示しないunset pm3d カラー表示しないset cntrparam levels incremental ‐1,0.1,1

等高線を0から1まで0.1刻みに設定以下でファイルを読み込み,3次元表示splot 'f.txt' with line  

Page 53: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

計算結果

2015/06/18先端GPGPUシミュレーション工学特論53

前回授業で用いたgnuplotのanim_2d.gplを流用して2次元分布を確認

set xrange [0:2*pi] x軸の表示範囲を0~2に固定set yrange [0:2*pi] y軸の表示範囲を0~2に固定set zrange [‐1:1] z軸の表示範囲を‐1~1に固定set view 0,0 真上から見下ろすset size 1,1 グラフの縦横比を1:1unset contour 2次元等高線を表示unset surface 3次元で等値面を表示しないset pm3d カラー表示しない以下でファイルを読み込み,3次元表示splot 'f.txt' with line  

Page 54: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

GPUへの移植

2015/06/18先端GPGPUシミュレーション工学特論54

共役勾配法のGPU移植は比較的簡単 これまでの授業内容の知識で実装可能

第7回総和計算

第8回偏微分方程式の差分計算(拡散方程式)

SOR法のGPU移植は非常に困難 処理の過程で格子点のデータに依存性が存在

fi,j(m+1)の値を計算するためにfi−1,j(m+1), fi,j−1

(m+1)の値を利用

特殊な並列化方法を導入

Page 55: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

void cg(double *f, double *g){double err;int ij,ip1j,im1j,ijm1,ijp1;double *p,*r,*Ap;double alph,beta,rr,pAp,bb;

p  = (double *)malloc(Nbytes);r  = (double *)malloc(Nbytes);Ap = (double *)malloc(Nbytes);for(int j=0;j<Ny;j++){for(int i=0;i<Nx;i++){ij = i+Nx*j;p [ij] = 0.0;r [ij] = 0.0;Ap[ij] = 0.0;

}}alph=0.0;beta=0.0;

共役勾配法の並列化・GPU移植

2015/06/18先端GPGPUシミュレーション工学特論55

1スレッドが配列の1要素に0を代入容易に並列化・GPU移植可能

Page 56: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

bb = 0.0;rr = 0.0;for(int j=1;j<Ny‐1;j++){for(int i=1;i<Nx‐1;i++){ij = i+Nx*j;ip1j = (i+1)+Nx*(j  );im1j = (i‐1)+Nx*(j  );ijp1 = (i )+Nx*(j+1);ijm1 = (i )+Nx*(j‐1);

r[ij] = g[ij]‐((f[im1j]‐2*f[ij]+f[ip1j])/dxdx

+(f[ijm1]‐2*f[ij]+f[ijp1])/dydy);

rr += r[ij]*r[ij];bb += g[ij]*g[ij];

}}

共役勾配法の並列化・GPU移植

2015/06/18先端GPGPUシミュレーション工学特論56

残差を計算するカーネルと内積を計算するカーネルに分離・残差の計算には拡散方程式のカーネル・内積の計算は総和計算のカーネルを流用

容易ではないが,これまでの知識で並列化・GPU移植可能

Page 57: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

do{for(int j=0;j<Ny;j++){for(int i=0;i<Nx;i++){ij = i+Nx*j;p [ij] = r[ij] + beta*p[ij];

}}

共役勾配法の並列化・GPU移植

2015/06/18先端GPGPUシミュレーション工学特論57

ベクトル和と同様に1スレッドが配列の1要素の計算を実行容易に並列化・GPU移植可能

Page 58: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

pAp = 0.0;for(int j=1;j<Ny‐1;j++){for(int i=1;i<Nx‐1;i++){ij = i+Nx*j;ip1j = (i+1)+Nx*(j  );im1j = (i‐1)+Nx*(j  );ijp1 = (i )+Nx*(j+1);ijm1 = (i )+Nx*(j‐1);

Ap[ij] = (p[im1j]‐2*p[ij]+p[ip1j])/dxdx+(p[ijm1]‐2*p[ij]+p[ijp1])/dydy;

pAp += p[ij]*Ap[ij];}}alph = rr/pAp;

共役勾配法の並列化・GPU移植

2015/06/18先端GPGPUシミュレーション工学特論58

残差を計算するカーネルと内積を計算するカーネルに分離・残差の計算には拡散方程式のカーネル・内積の計算は総和計算のカーネルを流用

容易ではないが,これまでの知識で並列化・GPU移植可能

Page 59: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

rr = 0.0;for(int j=0;j<Ny;j++){for(int i=0;i<Nx;i++){ij = i+Nx*j;f[ij] = f[ij] + alph* p[ij];r[ij] = r[ij] ‐ alph*Ap[ij];rr += r[ij]*r[ij];

}}err = sqrt(rr/bb);beta = rr/(alph*pAp);

}while(err > ERR_TOL);

}

共役勾配法の並列化・GPU移植

2015/06/18先端GPGPUシミュレーション工学特論59

ベクトル和と同様に1スレッドが配列の1要素の計算を実行容易に並列化・GPU移植可能

Page 60: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

//メモリの確保・解放は比較的負荷が高いので,mainで確保して関数に渡すvoid cg(double *f, double *g, double *r, double *p, double *Ap){double err;double alph,beta,rr,pAp,bb;

initAuxVectors<<<Block, Thread>>>(r,p,Ap); cudaDeviceSynchronize();alph=0.0;beta=0.0;

bb = dot_product(g,g); cudaDeviceSynchronize();computeResidual<<<Block, Thread>>>(f,g,r); cudaDeviceSynchronize();rr = dot_product(r,r); cudaDeviceSynchronize();

do{computeAuxVector<<<Block, Thread>>>(p,r,beta);cudaDeviceSynchronize();

共役勾配法の並列化・GPU移植

2015/06/18先端GPGPUシミュレーション工学特論60

GPUの全スレッドを同期(不要な箇所もある)

Page 61: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

computeMxV<<<Block, Thread>>>(Ap,p); cudaDeviceSynchronize();pAp = dot_product(p,Ap); cudaDeviceSynchronize();alph = rr/pAp;

update<<<Block, Thread>>>(f,r); cudaDeviceSynchronize();rr = dot_product(r,r); cudaDeviceSynchronize();

err = sqrt(rr/bb);beta = rr/(alph*pAp);

}while(err > ERR_TOL);

}

共役勾配法の並列化・GPU移植

2015/06/18先端GPGPUシミュレーション工学特論61

Page 62: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

SOR法の並列化

2015/06/18先端GPGPUシミュレーション工学特論62

SOR法の処理の手順 更新手順に依存性が存在

Jacobi法なら依存性問題は回避できるが収束が遅すぎる

並列化の影響で反復毎に更新順序が変化すると収束が保証されない

配列順序・計算順序の並び替え(オーダリング)を導入

f[]

i

j

22

22

2

)1(1,

)(1,

2

)1(,1

)(,1

.

)1(, 2

ΔyΔxΔyΔx

Δyff

Δxff

g

f

mji

mji

mji

mji

ji

mji

Page 63: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

Red-Blackオーダリング

2015/06/18先端GPGPUシミュレーション工学特論63

更新順序を2段階に分離 赤色の要素を参照し,黒色の要素全てを更新

黒色の要素を参照し,赤色の要素全てを更新f[]

i

j

i

j

i

fr[] fb[]

Page 64: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

Red-Blackオーダリング

2015/06/18先端GPGPUシミュレーション工学特論64

更新順序を2段階に分離 赤色の要素を参照し,黒色の要素全てを更新

黒色の要素を参照し,赤色の要素全てを更新f[]

i

j

fr[]

i

j

fb[]

i

Page 65: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

Red-Black SOR法

2015/06/18先端GPGPUシミュレーション工学特論65

赤色もしくは黒色の要素は常にm+1の値を用いて計算 SOR法よりも速く収束

22

22

2

)(1,

)(1,

2

)(,1

)(,1

.)1(

,2

ΔyΔxΔyΔx

Δyff

Δxff

gfmji

mji

mji

mji

jimji

22

22

2

)1(1,

)1(1,

2

)1(,1

)1(,1

.)1(

,2

ΔyΔxΔyΔx

Δyff

Δxff

gfmji

mji

mji

mji

jimji

even is when ,...5,3,1odd is when ,...6,4,2

,1,2,...,2,1jiji

NNj yy

odd is when ,...5,3,1even is when ,...6,4,2

,1,2,...,2,1jiji

NNj yy

Page 66: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

void rbsor(double *f, double *g){

int ite_SOR=0;double err_n,err_d,err_relative;double d_f;int ij,ip1j,im1j,ijm1,ijp1;

do{err_n = 0.0;err_d = 0.0;//赤色要素を計算for(int j=1;j<Ny‐1;j++){for(int i=1+j%2;i<Nx‐1;i+=2){ij = i+Nx*j;ip1j = (i+1)+Nx*(j  );im1j = (i‐1)+Nx*(j  );ijp1 = (i )+Nx*(j+1);ijm1 = (i )+Nx*(j‐1);d_f =( (f[im1j]+f[ip1j])/dxdx

+(f[ijm1]+f[ijp1])/dydy

‐(g[ij]))*dxdxdydy/dxdy2 ‐f[ij];

f[ij] += Accel*d_f;err_n += d_f*d_f;err_d += f[ij]*f[ij];

}}

CPUプログラム(RB-SOR法)

2015/06/18先端GPGPUシミュレーション工学特論66

poisson.c

Page 67: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

CPUプログラム(RB-SOR法)

2015/06/18先端GPGPUシミュレーション工学特論67

poisson.c

//黒色要素を計算for(int j=1;j<Ny‐1;j++){for(int i=1+(j‐1)%2;i<Nx‐1;i+=2){ij = i+Nx*j;ip1j = (i+1)+Nx*(j  );im1j = (i‐1)+Nx*(j  );ijp1 = (i )+Nx*(j+1);ijm1 = (i )+Nx*(j‐1);d_f =( (f[im1j]+f[ip1j])/dxdx

+(f[ijm1]+f[ijp1])/dydy‐(g[ij]))*dxdxdydy/dxdy2 ‐f[ij];

f[ij] += Accel*d_f;err_n += d_f*d_f;err_d += f[ij]*f[ij];

}}

if(err_d<1e‐20)err_d=1.0;err_relative = sqrt(err_n/err_d);ite_SOR++;

}while(err_relative > ERR_TOL);

}

Page 68: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

赤色要素の計算

2015/06/18先端GPGPUシミュレーション工学特論68

j=1(奇数)のときに計算するiは2,4,6 j=2(偶数)のときに計算するiは1,3,5 計算の範囲は0<i<Nx‐1,0<j<Ny‐1

f[]

0  1  2  3  4  5  6  70 

1  2  3 

4  5  6  7

iの 小値は1,jが奇数の時+1,偶数の時+0jを2で割った剰余を利用してiの開始点を決定i=1+j%2

for(int j=1;j<Ny‐1;j++){for(int i=1+j%2;i<Nx‐1;i+=2){ij = i+Nx*j;ip1j = (i+1)+Nx*(j  );im1j = (i‐1)+Nx*(j  );ijp1 = (i )+Nx*(j+1);ijm1 = (i )+Nx*(j‐1);d_f =( (f[im1j]+f[ip1j])/dxdx

+(f[ijm1]+f[ijp1])/dydy‐(g[ij]))*dxdxdydy/dxdy2 ‐f[ij];

f[ij] += Accel*d_f;}}

剰余(j%2)をアンド演算(j&1)に置き換えると実行速度はどうなる?

Page 69: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

黒色要素の計算

2015/06/18先端GPGPUシミュレーション工学特論69

j=1(奇数)のときに計算するiは1,3,5 j=2(偶数)のときに計算するiは2,4,6 計算の範囲は0<i<Nx‐1,0<j<Ny‐1

for(int j=1;j<Ny‐1;j++){for(int i=1+(j+1)%2;i<Nx‐1;i+=2){ij = i+Nx*j;ip1j = (i+1)+Nx*(j  );im1j = (i‐1)+Nx*(j  );ijp1 = (i )+Nx*(j+1);ijm1 = (i )+Nx*(j‐1);d_f =( (f[im1j]+f[ip1j])/dxdx

+(f[ijm1]+f[ijp1])/dydy‐(g[ij]))*dxdxdydy/dxdy2 ‐f[ij];

f[ij] += Accel*d_f;}}

f[]

0  1  2  3  4  5  6  70 

1  2  3 

4  5  6  7

iの 小値は1,jが奇数の時+0,偶数の時+1jを2で割った剰余を利用してiの開始点を決定i=1+(j+1)%2 (=2‐j%2とも書ける)

Page 70: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

GPUへの移植

2015/06/18先端GPGPUシミュレーション工学特論70

赤色要素を計算するカーネルと黒色要素を計算するカーネルを分離

反復のループ制御や収束判定はCPUで実行

収束判定の誤差の指標にはl∞−ノルムを採用 l2−ノルムを用いると内積計算が発生

収束判定用の変数を用意(値を1に初期化)

各スレッドが計算した誤差が許容値より大きい場合は収束判定用変数に0を書き込む

収束していない格子点があれば反復を繰り返す

Page 71: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

#include<stdio.h>#include<stdlib.h>#include<math.h>

#define Lx  (2.0*M_PI)#define Ly  (2.0*M_PI)#define Nx 256#define Ny Nx#define Nbytes (Nx*Ny*sizeof(double))#define dx  (Lx/(Nx‐1))#define dy (Ly/(Ny‐1))

#define THREADX 16#define THREADY 16#define BLOCKX (Nx/THREADX)#define BLOCKY (Ny/THREADY)

void output(double *value, char *name);

#include"rbsor.cu"

__global__ void init(double *f, double *g){int i=blockIdx.x*blockDim.x+threadIdx.x;int j=blockIdx.y*blockDim.y+threadIdx.y;int ij = i+Nx*j;

double x = (double)i*dx;double y = (double)j*dy;g[ij] = 2.0*sin(2.0*M_PI*x/Lx)

*sin(2.0*M_PI*y/Ly);f[ij] = 0.0; 

}

GPUプログラム(メイン)

2015/06/18先端GPGPUシミュレーション工学特論71

poisson.cu

Page 72: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

int main(void){

double *f,*g;double *dev_f,*dev_g;dim3 Block, Thread;

cudaSetDevice(3);cudaSetDeviceFlags(cudaDeviceMapHost);

cudaMalloc((void **)&dev_f, Nbytes);cudaMalloc((void **)&dev_g, Nbytes);

Thread = dim3(THREADX,THREADY,1);Block  = dim3(BLOCKX,BLOCKY,1);init<<<Block, Thread >>>(dev_f,dev_g);

printf("iteration = %d¥n",rbsor(dev_f,dev_g));

f=(double *)malloc(Nbytes);g=(double *)malloc(Nbytes);

cudaMemcpy(f,dev_f,Nbytes, cudaMemcpyDeviceToHost);cudaMemcpy(g,dev_g,Nbytes, cudaMemcpyDeviceToHost);

output(f,"f.txt");output(g,"g.txt");

cudaFree(dev_f);cudaFree(dev_g);free(f);free(g);return 0;

}

GPUプログラム(メイン)

2015/06/18先端GPGPUシミュレーション工学特論72

poisson.cu

Page 73: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

int rbsor(double *f, double *g){

int ite_SOR=0;int *converged,*conv=(int *)malloc(sizeof(int));dim3 Block= dim3(SORBx,SORBy,1), Thread= dim3(SORTx,SORTy,1);cudaMalloc((void **)&converged, sizeof(int));

do{ite_SOR++;*conv = 1; //1なら収束,0ならどこかの要素の値が収束していないcudaMemcpy(converged, conv, sizeof(int),cudaMemcpyHostToDevice);computeRed <<<Block, Thread>>>(f,g,converged);computeBlack<<<Block, Thread>>>(f,g,converged);//cudaDeviceSynchronize();cudaMemcpy(conv, converged, sizeof(int),cudaMemcpyDeviceToHost);

}while(*conv == 0 && ite_SOR<1024*1024*1024);//反復回数が230を超えると反復終了

free(conv);cudaFree(converged);return ite_SOR;

}

RB-SOR法(ループ制御部分)

2015/06/18先端GPGPUシミュレーション工学特論73

rbsor.cu

Page 74: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

int rbsor(double *f, double *g){

int ite_SOR=0;int *converged,*conv;dim3 Block= dim3(SORBx,SORBy,1), Thread= dim3(SORTx,SORTy,1);

//ホストメモリに置かれたconvをGPUから読み書きcudaHostAlloc((void **)&conv, sizeof(int),cudaHostAllocMapped);cudaHostGetDevicePointer(&converged, conv, 0);

do{ite_SOR++;*conv = 1; //1なら収束,0ならどこかの要素の値が収束していないcomputeRed <<<Block, Thread>>>(f,g,converged);computeBlack<<<Block, Thread>>>(f,g,converged);//cudaDeviceSynchronize();

}while(*conv == 0 && ite_SOR<1024*1024*1024);//反復回数が230を超えると反復終了

cudaFreeHost(conv);return ite_SOR;

}

RB-SOR法(ループ制御部分)

2015/06/18先端GPGPUシミュレーション工学特論74

rbsor.cu

Page 75: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

__global__ void computeRed(double *f,double *g, int *converged){

int j = blockIdx.y* blockDim.y + threadIdx.y;int i = blockIdx.x*(blockDim.x*2) + threadIdx.x*2 + (j+1)%2;int ij = i+Nx*j;int ip1j = (i+1)+Nx*(j  );int im1j = (i‐1)+Nx*(j  );int ijp1 = (i )+Nx*(j+1);int ijm1 = (i )+Nx*(j‐1);double d_f;

if(0<i && i<Nx‐1 && 0<j && j<Ny‐1){d_f =( (f[im1j]+f[ip1j])/dxdx

+(f[ijm1]+f[ijp1])/dydy‐(g[ij])

)*dxdxdydy/dxdy2 ‐f[ij];f[ij] += Accel*d_f;if(abs(d_f) > ERR_TOL) *converged = 0;

}}

RB-SOR法(赤色要素の計算)

2015/06/18先端GPGPUシミュレーション工学特論75

rbsor.cu

Page 76: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

__global__ void computeBlack(double *f,double *g, int *converged){

int j = blockIdx.y* blockDim.y + threadIdx.y;int i = blockIdx.x*(blockDim.x*2) + threadIdx.x*2 + (j)%2;int ij = i+Nx*j;int ip1j = (i+1)+Nx*(j  );int im1j = (i‐1)+Nx*(j  );int ijp1 = (i )+Nx*(j+1);int ijm1 = (i )+Nx*(j‐1);double d_f;

if(0<i && i<Nx‐1 && 0<j && j<Ny‐1){d_f =( (f[im1j]+f[ip1j])/dxdx

+(f[ijm1]+f[ijp1])/dydy‐(g[ij])

)*dxdxdydy/dxdy2 ‐f[ij];f[ij] += Accel*d_f;if(abs(d_f) > ERR_TOL) *converged = 0;

}}

RB-SOR法(黒色要素の計算)

2015/06/18先端GPGPUシミュレーション工学特論76

rbsor.cu

Page 77: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

並列度の指定

2015/06/18先端GPGPUシミュレーション工学特論77

初期化 1スレッドが一つの配列要素を計算

f[]

0  1  2  3  4  5  6  7

0 1  2  3 

4  5  6  7#define THREADX 16

#define THREADY 16#define BLOCKX (Nx/THREADX)#define BLOCKY (Ny/THREADY)

Thread = dim3(THREADX,THREADY,1);Block  = dim3(BLOCKX,BLOCKY,1);init<<<Block, Thread >>>

(dev_f,dev_g);

i=blockIdx.x*blockDim.x+threadIdx.x;j=blockIdx.y*blockDim.y+threadIdx.y;

Page 78: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

並列度の指定

2015/06/18先端GPGPUシミュレーション工学特論78

RB‐SOR法 i方向の計算に必要なスレッド数は初期化の1/2 必要なブロック数は同じ

f[]

0  1  2  3  4  5  6  7

0 1  2  3 

4  5  6  7#define SORTx (THREADX/2)

#define SORTy (THREADY)#define SORBx (BLOCKX)#define SORBy (BLOCKY)

dim3 Block, Thread;Thread = dim3(SORTx,SORTy,1);Block  = dim3(SORBx,SORBy,1);computeRed<<<Block, Thread>>>

(f,g,converged);

Page 79: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

並列度の指定

2015/06/18先端GPGPUシミュレーション工学特論79

RB‐SOR法 スレッド番号と配列添字をどう対応させるか

j方向は変更無し,i方向のみ変化

f[]

0  1  2  3  4  5  6  7

0 1  2  3 

4  5  6  7#define SORTx (THREADX/2)

#define SORTy (THREADY)#define SORBx (BLOCKX)#define SORBy (BLOCKY)

dim3 Block, Thread;Thread = dim3(SORTx,SORTy,1);Block  = dim3(SORBx,SORBy,1);computeRed<<<Block, Thread>>>

(f,g,converged);

Page 80: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

ストライドアクセス時の配列添字の決定

N=12, <<<3, 2>>>で実行

2015/06/18先端GPGPUシミュレーション工学特論80

c[i]

a[i]

b[i]

0 1 0

+ + + +

1

gridDim.x=3

blockDim.x=2

0 1

+ +

blockDim.x=2 blockDim.x=2blockIdx.x=0 blockIdx.x=1 blockIdx.x=2

threadIdx.x=

i=  0   1   2   3   4   5  6   7  8   9  10 11

Page 81: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

配列の要素番号iの計算

2015/06/18先端GPGPUシミュレーション工学特論81

threadIdx.xとiの対応

iの決定 配列サイズ=ブロックの数×1ブロックあたりのスレッドの数

配列サイズ=ブロックの数×1ブロックあたりのスレッドの数×計算する点の間隔

blockIdx.x 0 1 2

threadIdx.x 0 1 0 1 0 1

i 0 2 4=4+0

6=4+2

8=8+0

10=8+2

i+threadIdx.x×2

Page 82: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

ストライドアクセス時の配列添字の決定

N=12, <<<3, 2>>>で実行

2015/06/18先端GPGPUシミュレーション工学特論82

c[i]

a[i]

b[i]

0 1 0

+ + + +

1

gridDim.x=3

blockDim.x=2

0 1

+ +

blockDim.x=2 blockDim.x=2blockIdx.x=0 blockIdx.x=1 blockIdx.x=2

threadIdx.x=

i=  0   1   2   3   4   5  6   7  8   9  10 11= blockIdx.x*(blockDim.x*2) + threadIdx.x*2

計算する点の間隔 計算する点の間隔

Page 83: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

並列度の指定

2015/06/18先端GPGPUシミュレーション工学特論83

i方向のスレッド番号と配列添字の対応 ストライドアクセス

f[]

0  1  2  3  4  5  6  7

0 1  2  3 

4  5  6  7

j = blockIdx.y* blockDim.y + threadIdx.y;i = blockIdx.x*(blockDim.x*2) + threadIdx.x*2;

j

Page 84: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

並列度の指定

2015/06/18先端GPGPUシミュレーション工学特論84

i方向のスレッド番号と配列添字の対応 ストライドアクセス

開始点の変化(jが奇数のとき0開始,偶数のときは1開始)

f[]

0  1  2  3  4  5  6  7

0 1  2  3 

4  5  6  7

+0+1+0+1

j

(j+1)%2

j = blockIdx.y* blockDim.y + threadIdx.y;i = blockIdx.x*(blockDim.x*2) + threadIdx.x*2

+ (j+1)%2;

Page 85: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

並列度の指定

2015/06/18先端GPGPUシミュレーション工学特論85

RB‐SOR法 スレッド番号と配列添字をどう対応させるか

j方向は変更無し,i方向のみ変化

f[]

0  1  2  3  4  5  6  7

0 1  2  3 

4  5  6  7#define SORTx (THREADX/2)

#define SORTy (THREADY)#define SORBx (BLOCKX)#define SORBy (BLOCKY)

dim3 Block, Thread;Thread = dim3(SORTx,SORTy,1);Block  = dim3(SORBx,SORBy,1);computeBlack<<<Block, Thread>>>

(f,g,converged);

Page 86: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

並列度の指定

2015/06/18先端GPGPUシミュレーション工学特論86

i方向のスレッド番号と配列添字の対応 ストライドアクセス

f[]

0  1  2  3  4  5  6  7

0 1  2  3 

4  5  6  7

j = blockIdx.y* blockDim.y + threadIdx.y;i = blockIdx.x*(blockDim.x*2) + threadIdx.x*2;

j

Page 87: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

並列度の指定

2015/06/18先端GPGPUシミュレーション工学特論87

i方向のスレッド番号と配列添字の対応 ストライドアクセス

開始点の変化(jが奇数のとき0開始,偶数のときは1開始)

f[]

0  1  2  3  4  5  6  7

0 1  2  3 

4  5  6  7

+1+0+1+0

j

(j)%2

j = blockIdx.y* blockDim.y + threadIdx.y;i = blockIdx.x*(blockDim.x*2) + threadIdx.x*2

+ (j)%2;

剰余(j%2)をアンド演算(j&1)に置き換えると実行速度はどう変わるだろうか

Page 88: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

RB-SOR法の性能改善

2015/06/18先端GPGPUシミュレーション工学特論88

赤色要素,黒色要素の計算はストライドアクセス グローバルメモリにコアレスアクセスできない

読み込み速度が低下

赤色要素,黒色要素の計算でカーネルを切り替えるため,共有メモリが利用できない

メモリアクセスを改善したい グローバルメモリにコアレスアクセスしたい

赤色要素を格納する配列と黒色要素を格納する配列を分離

Page 89: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

配列の分離

2015/06/18先端GPGPUシミュレーション工学特論89

色ごとに格納する配列を区別 ストライドアクセスを排除

元の配列を分離,出力時に結合するカーネルを作成

f[]

i

j

fr[]

i

j

fb[]

i

Page 90: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

int rbsor(double *f, double *g){

double *fr,*fb,*gr,*gb;int ite_SOR=0;int *converged,*conv;

dim3 BlockSplit= dim3(SplitBx,SplitBy,1),ThreadSplit= dim3(SplitTx,SplitTy,1);dim3 BlockMerge= dim3(MergeBx,MergeBy,1),ThreadMerge= dim3(MergeTx,MergeTy,1);dim3 BlockSOR = dim3(  SORBx,  SORBy,1),ThreadSOR = dim3(  SORTx,  SORTy,1);

cudaHostAlloc((void **)&conv, sizeof(int),cudaHostAllocMapped);cudaHostGetDevicePointer(&converged, conv, 0);

cudaMalloc((void **)&fr, Nbytes/2);cudaMalloc((void **)&fb, Nbytes/2);cudaMalloc((void **)&gr, Nbytes/2);cudaMalloc((void **)&gb, Nbytes/2);

split<<<BlockSplit, ThreadSplit>>>(f,fr,fb);split<<<BlockSplit, ThreadSplit>>>(g,gr,gb);

RB-SOR法(ループ制御部分)

2015/06/18先端GPGPUシミュレーション工学特論90

rbsor_split.cu

Page 91: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

do{ite_SOR++;*conv = 1;

computeRed <<<BlockSOR, ThreadSOR>>>(fr, fb, gr, gb,converged);computeBlack<<<BlockSOR, ThreadSOR>>>(fb, fr, gb, gr, converged);cudaDeviceSynchronize();

}while(*conv == 0 && ite_SOR<1024*1024*1024);

merge<<<BlockMerge, ThreadMerge>>>(f,fr,fb);

cudaFreeHost(conv);cudaFree(fr);cudaFree(fb);cudaFree(gr);cudaFree(gb);

return ite_SOR;}

配列を分離するRB-SOR法(ループ制御部分)

2015/06/18先端GPGPUシミュレーション工学特論91

rbsor_split.cu

Page 92: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

__global__ void split(double *f, double *fr,double *fb){

__shared__ double sf[THREADX][THREADY];__shared__ double sfrb[THREADX][THREADY];

int tx = threadIdx.x;int ty = threadIdx.y;

int j = blockIdx.y* blockDim.y + threadIdx.y;int i = blockIdx.x*(blockDim.x*2) + threadIdx.x;int ij = i+Nx*j;

sf[tx][ty] = f[ij];__syncthreads();

i = blockIdx.x*(blockDim.x*2) + threadIdx.x+ blockDim.x;

ij = i+Nx*j;sf[tx+blockDim.x][ty] = f[ij];__syncthreads();

sfrb[tx ][ty]= sf[tx*2+(j+1)%2][ty];

sfrb[tx+blockDim.x][ty]= sf[tx*2+(j  )%2][ty];

__syncthreads();

i = blockIdx.x*blockDim.x + threadIdx.x;ij= i+Nx/2*j;fr[ij] = sfrb[tx ][ty];fb[ij] = sfrb[tx+blockDim.x][ty];

}

配列を分離するRB-SOR法(配列分離)

2015/06/18先端GPGPUシミュレーション工学特論92

rbsor_split.cu

Page 93: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

配列の分離

2015/06/18先端GPGPUシミュレーション工学特論93

共有メモリ上に配列を宣言

グローバルメモリからコピーするための配列

並び替え後のデータを格納する配列

f[]__shared__ double sf[THREADX][THREADY];__shared__ double sfrb[THREADX][THREADY];

int tx = threadIdx.x;int ty = threadIdx.y;int j = blockIdx.y* blockDim.y + threadIdx.y;int i = blockIdx.x*(blockDim.x*2) + threadIdx.x;int ij = i+Nx*j;

sf[tx][ty] = f[ij];__syncthreads();

sf[][]

sfrb[][]

Page 94: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

配列の分離

2015/06/18先端GPGPUシミュレーション工学特論94

共有メモリ上に配列を宣言

グローバルメモリからコピーするための配列

並び替え後のデータを格納する配列

グローバルメモリから共有メモリにコピーして同期を取る

f[]__shared__ double sf[THREADX][THREADY];__shared__ double sfrb[THREADX][THREADY];

int tx = threadIdx.x;int ty = threadIdx.y;int j = blockIdx.y* blockDim.y + threadIdx.y;int i = blockIdx.x*(blockDim.x*2) + threadIdx.x;int ij = i+Nx*j;

sf[tx][ty] = f[ij];__syncthreads();

sf[][]

0  1  2  3

0 1  2  3

Page 95: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

配列の分離

2015/06/18先端GPGPUシミュレーション工学特論95

i方向の位置を変更してさらにグローバルメモリから共有メモリにコピー

f[]

i = blockIdx.x*(blockDim.x*2) + threadIdx.x+ blockDim.x;

ij = i+Nx*j;sf[tx+blockDim.x][ty] = f[ij];__syncthreads();

sf[][]

0  1  2  3

0 1  2  3

Page 96: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

配列の分離

2015/06/18先端GPGPUシミュレーション工学特論96

共有メモリ上でストライドアクセスして赤色要素と黒色要素を並び替え

jの位置に応じてiの位置を変更

f[]

sfrb[tx ][ty]= sf[tx*2+(j+1)%2][ty];

sf[][]

0  1  2  3

0 1  2  3

sfrb[][]

二つ目の共有メモリsfrb[][]を利用しないと性能はどのように変化するだろうか?

Page 97: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

配列の分離

2015/06/18先端GPGPUシミュレーション工学特論97

共有メモリ上でストライドアクセスして赤色要素と黒色要素を並び替え

jの位置に応じてiの位置を変更

並び替え後の配列に赤色要素を書込

f[]

sfrb[tx ][ty]= sf[tx*2+(j+1)%2][ty];

sf[][]

0  1  2  3

0 1  2  3

sfrb[][]

+0+1+0+1

(j+1)%2

0  1  2  3

0 1  2  3

二つ目の共有メモリsfrb[][]を利用しないと性能はどのように変化するだろうか?

Page 98: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

配列の分離

2015/06/18先端GPGPUシミュレーション工学特論98

共有メモリ上でストライドアクセスして赤色要素と黒色要素を並び替え

jの位置に応じてiの位置を変更

f[]

sfrb[tx+blockDim.x][ty]= sf[tx*2+(j  )%2][ty];

__syncthreads();

sf[][]

0  1  2  3

0 1  2  3

sfrb[][]

0  1  2  3

0 1  2  3

二つ目の共有メモリsfrb[][]を利用しないと性能はどのように変化するだろうか?

Page 99: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

配列の分離

2015/06/18先端GPGPUシミュレーション工学特論99

共有メモリ上でストライドアクセスして赤色要素と黒色要素を並び替え

jの位置に応じてiの位置を変更

並び替え後の配列に黒色要素を書込

f[]

sfrb[tx+blockDim.x][ty]= sf[tx*2+(j  )%2][ty];

__syncthreads();

sf[][]

0  1  2  3

0 1  2  3

sfrb[][]

+1+0+1+0

(j )%2

0  1  2  3

0 1  2  3

二つ目の共有メモリsfrb[][]を利用しないと性能はどのように変化するだろうか?

Page 100: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

配列の分離

2015/06/18先端GPGPUシミュレーション工学特論100

共有メモリの赤色,黒色要素を分離した配列に書込

各配列にコアレスアクセスで書込

i = blockIdx.x*blockDim.x + threadIdx.x;ij= i+Nx/2*j;fr[ij] = sfrb[tx ][ty];fb[ij] = sfrb[tx+blockDim.x][ty];

fr[] fb[]

sfrb[][]

0  1  2  3

0 1  2  3

二つ目の共有メモリsfrb[][]を利用しないと性能はどのように変化するだろうか?

Page 101: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

配列の分離

2015/06/18先端GPGPUシミュレーション工学特論101

共有メモリの赤色,黒色要素を分離した配列に書込

各配列にコアレスアクセスで書込

i = blockIdx.x*blockDim.x + threadIdx.x;ij= i+Nx/2*j;fr[ij] = sfrb[tx ][ty];fb[ij] = sfrb[tx+blockDim.x][ty];

fr[] fb[]

sfrb[][]

0  1  2  3

0 1  2  3

二つ目の共有メモリsfrb[][]を利用しないと性能はどのように変化するだろうか?

Page 102: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

__global__ void merge(double *f, double *fr,double *fb){

__shared__ double sf[THREADX][THREADY];__shared__ double sfrb[THREADX][THREADY];

int tx = threadIdx.x;int ty = threadIdx.y;

int j = blockIdx.y*blockDim.y + threadIdx.y;int i = blockIdx.x*blockDim.x + threadIdx.x;int ij = i+Nx/2*j;

sfrb[tx ][ty] = fr[ij];sfrb[tx+blockDim.x][ty] = fb[ij];__syncthreads();

sf[tx*2+(j+1)%2][ty]= sfrb[tx ][ty];

sf[tx*2+(j  )%2][ty]= sfrb[tx+blockDim.x][ty];

__syncthreads();

i = blockIdx.x*(blockDim.x*2) + threadIdx.x;ij= i+Nx*j;f[ij] = sf[tx ][ty];

i = blockIdx.x*(blockDim.x*2) + threadIdx.x+ blockDim.x;

ij= i+Nx*j;f[ij] = sf[tx+blockDim.x][ty];

}

配列を分離するRB-SOR法(配列結合)

2015/06/18先端GPGPUシミュレーション工学特論102

rbsor_split.cu

Page 103: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

配列の結合

2015/06/18先端GPGPUシミュレーション工学特論103

赤色要素をグローバルメモリから読み込み,共有メモリへ書込

コアレスアクセスで書込

__shared__ double sf[THREADX][THREADY];__shared__ double sfrb[THREADX][THREADY];

int tx = threadIdx.x;int ty = threadIdx.y;int j = blockIdx.y*blockDim.y + threadIdx.y;int i = blockIdx.x*blockDim.x + threadIdx.x;sfrb[tx ][ty] = fr[ij];sfrb[tx+blockDim.x][ty] = fb[ij];__syncthreads();

fr[] fb[]

sfrb[][]

0  1  2  3

0 1  2  3

二つ目の共有メモリsfrb[][]を利用しないと性能はどのように変化するだろうか?

Page 104: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

配列の結合

2015/06/18先端GPGPUシミュレーション工学特論104

黒色要素をグローバルメモリから読み込み,共有メモリへ書込

コアレスアクセスで書込

__shared__ double sf[THREADX][THREADY];__shared__ double sfrb[THREADX][THREADY];

int tx = threadIdx.x;int ty = threadIdx.y;int j = blockIdx.y*blockDim.y + threadIdx.y;int i = blockIdx.x*blockDim.x + threadIdx.x;sfrb[tx ][ty] = fr[ij];sfrb[tx+blockDim.x][ty] = fb[ij];__syncthreads();

fr[] fb[]

sfrb[][]

0  1  2  3

0 1  2  3

二つ目の共有メモリsfrb[][]を利用しないと性能はどのように変化するだろうか?

Page 105: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

配列の結合

2015/06/18先端GPGPUシミュレーション工学特論105

並び替え後の配列内の赤色要素を並び替え前の配列へ書込

jの位置に応じてiの位置を変更

sf[tx*2+(j+1)%2][ty]= sfrb[tx ][ty];

sfrb[][]

0  1  2  3

0 1  2  3

sf[][]

0  1  2  3

0 1  2  3

二つ目の共有メモリsfrb[][]を利用しないと性能はどのように変化するだろうか?

Page 106: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

配列の結合

2015/06/18先端GPGPUシミュレーション工学特論106

並び替え後の配列内の赤色要素を並び替え前の配列へ書込

jの位置に応じてiの位置を変更

sf[tx*2+(j+1)%2][ty]= sfrb[tx ][ty];

sfrb[][]

0  1  2  3

0 1  2  3

sf[][]

0  1  2  3

0 1  2  3 +0

+1+0+1

(j+1)%2

二つ目の共有メモリsfrb[][]を利用しないと性能はどのように変化するだろうか?

Page 107: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

配列の結合

2015/06/18先端GPGPUシミュレーション工学特論107

並び替え後の配列内の黒色要素を並び替え前の配列へ書込

jの位置に応じてiの位置を変更

sf[tx*2+(j  )%2][ty]= sfrb[tx+blockDim.x][ty];

__syncthreads();

sfrb[][]

0  1  2  3

0 1  2  3

sf[][]

0  1  2  3

0 1  2  3

二つ目の共有メモリsfrb[][]を利用しないと性能はどのように変化するだろうか?

Page 108: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

配列の結合

2015/06/18先端GPGPUシミュレーション工学特論108

並び替え後の配列内の黒色要素を並び替え前の配列へ書込

jの位置に応じてiの位置を変更

sf[tx*2+(j  )%2][ty]= sfrb[tx+blockDim.x][ty];

__syncthreads();

sfrb[][]

0  1  2  3

0 1  2  3

sf[][]

0  1  2  3

0 1  2  3 +1

+0+1+0

(j  )%2

二つ目の共有メモリsfrb[][]を利用しないと性能はどのように変化するだろうか?

Page 109: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

配列の結合

2015/06/18先端GPGPUシミュレーション工学特論109

共有メモリの内容をコアレスアクセスして元の配列に書き込み

f[]i = blockIdx.x*(blockDim.x*2) + threadIdx.x;ij= i+Nx*j;f[ij] = sf[tx ][ty];

i = blockIdx.x*(blockDim.x*2) + threadIdx.x+ blockDim.x;

ij= i+Nx*j;f[ij] = sf[tx+blockDim.x][ty];

sf[][]

0  1  2  3

0 1  2  3

Page 110: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

配列の結合

2015/06/18先端GPGPUシミュレーション工学特論110

共有メモリの内容をコアレスアクセスして元の配列に書き込み

f[] sf[][]

0  1  2  3

0 1  2  3

i = blockIdx.x*(blockDim.x*2) + threadIdx.x;ij= i+Nx*j;f[ij] = sf[tx ][ty];

i = blockIdx.x*(blockDim.x*2) + threadIdx.x+ blockDim.x;

ij= i+Nx*j;f[ij] = sf[tx+blockDim.x][ty];

Page 111: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

__global__ void computeRed(double *fr,double *fb, double *gr,double *gb, int *converged){

int j = blockIdx.y*blockDim.y + threadIdx.y;int i = blockIdx.x*blockDim.x + threadIdx.x;int ij = i+Nx/2*j;int iside = i+1‐(j%2)*2;int isidej = (iside)+Nx/2*(j  );int ijp1   = (i )+Nx/2*(j+1);int ijm1   = (i )+Nx/2*(j‐1);double d_f;

if(1‐(j+1)%2<=i && i<Nx/2‐(j+1)%2 && 0<j && j<Ny‐1){d_f =( (fb[isidej]+fb[ij])/dxdx

+(fb[ijm1  ]+fb[ijp1])/dydy‐(gr[ij])

)*dxdxdydy/dxdy2 ‐fr[ij];fr[ij] += Accel*d_f;

if(abs(d_f) > ERR_TOL) *converged = 0;}

}

配列を分離するRB-SOR法(赤色要素の計算)

2015/06/18先端GPGPUシミュレーション工学特論111

rbsor_split.cu

Page 112: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

__global__ void computeBlack(double *fb,double *fr, double *gb,double *gr, int *converged){

int j = blockIdx.y*blockDim.y + threadIdx.y;int i = blockIdx.x*blockDim.x + threadIdx.x;int ij = i+Nx/2*j;int iside = i‐1+(j%2)*2;int isidej = (iside)+Nx/2*(j  );int ijp1   = (i )+Nx/2*(j+1);int ijm1   = (i )+Nx/2*(j‐1);double d_f;

if(0+(j+1)%2<=i && i<Nx/2‐(j  )%2 && 0<j && j<Ny‐1){d_f =( (fr[isidej]+fr[ij])/dxdx

+(fr[ijm1  ]+fr[ijp1])/dydy‐(gb[ij])

)*dxdxdydy/dxdy2 ‐fb[ij];fb[ij] += Accel*d_f;

if(abs(d_f) > ERR_TOL) *converged = 0;}

}

配列を分離するRB-SOR法(黒色要素の計算)

2015/06/18先端GPGPUシミュレーション工学特論112

rbsor_split.cu

Page 113: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

並列度の指定

2015/06/18先端GPGPUシミュレーション工学特論113

i方向のスレッド番号と配列添字の対応が単純化

fr[] fb[]

0  1  2  3

0 1  2  3 

4  5  6  7

j = blockIdx.y*blockDim.y + threadIdx.y;i = blockIdx.x*blockDim.x + threadIdx.x;

Page 114: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

配列アクセス

2015/06/18先端GPGPUシミュレーション工学特論114

黒色要素の参照点 jに応じてi方向のどちらを見るかが変化

jが奇数の時はi‐1,偶数の時はi+1fr[] fb[]

0  1  2  3

0 1  2  3 

4  5  6  7

f[]

Page 115: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

配列アクセス

2015/06/18先端GPGPUシミュレーション工学特論115

黒色要素の参照点 jに応じてi方向のどちらを見るかが変化

jが奇数の時はi‐1,偶数の時はi+1fr[] fb[]

0  1  2  3

0 1  2  3 

4  5  6  7

f[]

Page 116: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

配列アクセス

2015/06/18先端GPGPUシミュレーション工学特論116

黒色要素の参照点 jに応じてi方向のどちらを見るかが変化

iside = i+1‐(j%2)*2;fr[] fb[]

0  1  2  3

0 1  2  3 

4  5  6  7 +1

+0+1+0+1+0+1+0

j%2 +1‐j%2*2

‐1+1‐1+1‐1+1‐1+1

Page 117: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

配列アクセス

2015/06/18先端GPGPUシミュレーション工学特論117

赤色要素の計算範囲 jに応じて変化(jの範囲は変更無し 0<j && j<Ny‐1) 1‐(j+1)%2<=i && i<Nx/2‐(j+1)%2

fr[]

0  1  2  3

0 1  2  3 

4  5  6  7

f[]

0‐10

‐10

‐10

‐1

‐(j+1)%2 1‐(j+1)%2

1<=0<=1<=0<=1<=0<=1<=0<=

Nx/2‐(j+1)%2

<4<3<4<3<4<3<4<3

Page 118: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

並列度の指定

2015/06/18先端GPGPUシミュレーション工学特論118

i方向のスレッド番号と配列添字の対応が単純化

fr[] fb[]

0  1  2  3

0 1  2  3 

4  5  6  7

j = blockIdx.y*blockDim.y + threadIdx.y;i = blockIdx.x*blockDim.x + threadIdx.x;

Page 119: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

配列アクセス

2015/06/18先端GPGPUシミュレーション工学特論119

赤色要素の参照点 jに応じてi方向のどちらを見るかが変化

jが奇数の時はi+1,偶数の時はi‐1fr[] fb[]

0 1  2  3 

4  5  6  7

f[]

0  1  2  3

Page 120: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

配列アクセス

2015/06/18先端GPGPUシミュレーション工学特論120

赤色要素の参照点 jに応じてi方向のどちらを見るかが変化

jが奇数の時はi+1,偶数の時はi‐1fr[] fb[]

0 1  2  3 

4  5  6  7

f[]

0  1  2  3

Page 121: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

配列アクセス

2015/06/18先端GPGPUシミュレーション工学特論121

赤色要素の参照点 jに応じてi方向のどちらを見るかが変化

iside = i‐1+(j%2)*2;fr[] fb[]

0  1  2  3

0 1  2  3 

4  5  6  7

‐1+j%2*2

+1‐1+1‐1+1‐1+1‐1

+1+0+1+0+1+0+1+0

j%2

Page 122: 2015年度先端GPGPUシミュレーション工学特論 第10回 Poisson方程式の求解(線形連立一次方程式)

配列アクセス

2015/06/18先端GPGPUシミュレーション工学特論122

黒色要素の計算範囲 jに応じて変化(jの範囲は変更無し 0<j && j<Ny‐1) 0+(j+1)%2<=i && i<Nx/2‐(j  )%2

fb[]

0  1  2  3

0 1  2  3 

4  5  6  7

f[] 0+(j+1)%2

0<=1<=0<=1<=0<=1<=0<=1<=

Nx/2‐(j  )%2

<3<4<3<4<3<4<3<4

0+10

+10

+10

+1

+(j+1)%2