並列有限要素法による三次元定常熱伝導解析プログラム
演習編
中島 研吾
東京大学情報基盤センター

pFEM3D-22

対象とする問題：三次元定常熱伝導  T    T    T          Q  x, y , z   0
x  x  y  y  z  z 

• 定常熱伝導＋発熱• 一様な熱伝導率 • 直方体

ZT=0@Z=zmax– 一辺長さ1の立方体（六面体）要素– 各方向にNX・NY・NZ個NZ

YNX
NYX

• 境界条件– T=0@Z=zmax• 体積当たり発熱量は位置（メッシュの中心の座標 xc,yc）に依存– Q  x, y, z   QVOL xC  yC

pFEM3D-23

並列有限要素法の手順（並列計算実行）
pfem3d/run/
INPUT.DAT

pfem3d/pmesh/pcube.*

pfem3d/run/sol

局所分散メッシュファイル
pmeshで生成

pfem3d/run/test.inp
ParaView 出力：名称固定

pFEM3D-2

4

課題（1/2）• 自分で問題設定を行い，「sol」の挙動を分析してみよ• 例– Strong Scaling• 問題サイズを固定，PE数を変化させて時間（全体，各部分）を測定。

– Weak Scaling• PEあたりの問題サイズを固定，1反復あたりの計算時間を求める。

– 考慮すべき項目• 問題サイズ• 領域分割手法（RCB，K-METIS，P-METIS，1D～3D）の影響。

– メッシュ生成，領域分割におけるFX10の性能低い• 1283くらいが限界（領域分割に15分以上かかる）• 「*.inp」の出力に時間がかかる場合がある。
– OUTPUT_UCDの呼び出しのコメントアウト– src，partpFEM3D-2

5

１D～3D分割
どの方法が良いか考えて見よ

1D型

2D型

3D型

pFEM3D-2

6

１D～3D分割
通信量の総和（各辺4N，8領域とする）

1D型

2D型

3D型

16 N2 x 7 = 112 N2

16 N2 x 4 = 64 N2

16 N2 x 3 = 48 N2

pFEM3D-2

7

１D～3D分割
mesh.inp

1D型

2D型

3D型

64 64 648 1 1pcube

64 64 64
4 2 1pcube

64 64 64
2 2 2pcube

pFEM3D-2

8

課題（2/2）• 領域間通信（solver_SR）の性能改善ができないかどうか考えてみよ。
– Recv. Bufferへのコピーを効率的に実施できないか?
do neib= 1, NEIBPETOT
istart= IMPORT_INDEX(neib-1)
inum = IMPORT_INDEX(neib ) - istartcall MPI_Irecv (WR(istart+1), inum, MPI_DOUBLE_PRECISION,&NEIBPE(neib), 0, MPI_COMM_WORLD, req2(neib),&ierr)enddo
call MPI_Waitall (NEIBPETOT, req2, sta2, ierr)do neib= 1, NEIBPETOT
istart= IMPORT_INDEX(neib-1)
inum = IMPORT_INDEX(neib ) - istart
do k= istart+1, istart+inum
ii = IMPORT_ITEM(k)X(ii)= WR(k)
enddo
enddo

&&

pFEM3D-1

SEND/RECV (Original)!C!C-- INIT.
allocate (sta1(MPI_STATUS_SIZE,NEIBPETOT), sta2(MPI_STATUS_SIZE,NEIBPETOT))
allocate (req1(NEIBPETOT), req2(NEIBPETOT))!C!C-- SEND
do neib= 1, NEIBPETOT
istart= STACK_EXPORT(neib-1)
inum = STACK_EXPORT(neib ) - istart
do k= istart+1, istart+inum
WS(k)= X(NOD_EXPORT(k))
enddocall MPI_ISEND (WS(istart+1), inum, MPI_DOUBLE_PRECISION,&&NEIBPE(neib), 0, MPI_COMM_WORLD, req1(neib), ierr)enddo!C!C-- RECEIVE
do neib= 1, NEIBPETOT
istart= STACK_IMPORT(neib-1)
inum = STACK_IMPORT(neib ) - istartcall MPI_IRECV (WR(istart+1), inum, MPI_DOUBLE_PRECISION,&&NEIBPE(neib), 0, MPI_COMM_WORLD, req2(neib), ierr)enddo
call MPI_WAITALL (NEIBPETOT, req2, sta2, ierr)do neib= 1, NEIBPETOT
istart= STACK_IMPORT(neib-1)
inum = STACK_IMPORT(neib ) - istart
do k= istart+1, istart+inum
X(NOD_IMPORT(k))= WR(k)
enddo
enddo
call MPI_WAITALL (NEIBPETOT, req1, sta1, ierr)

9pFEM3D-1

10

If numbering of external nodes iscontinuous in each neighboringprocess ...
84818582838688879657585960616263647395495051525354555674944142434445464748809333343536373839407992

25262728293031327891

17181920212223247790

91011121314151676

89

1234567875

65

66

67

68

69707172

Parallel FEM 3D-2
pFEM3D-1

11

SEND/RECV (NEW:1)!C!C-- INIT.
allocate (sta1(MPI_STATUS_SIZE,2*NEIBPETOT))
allocate (req1(2*NEIBPETOT))!C!C-- SEND
do neib= 1, NEIBPETOT
istart= STACK_EXPORT(neib-1)
inum = STACK_EXPORT(neib ) - istart
do k= istart+1, istart+inum
WS(k)= X(NOD_EXPORT(k))
enddo
enddo
do neib= 1, NEIBPETOT
istart= STACK_EXPORT(neib-1)
inum = STACK_EXPORT(neib ) - istartcall MPI_ISEND (WS(istart+1), inum, MPI_DOUBLE_PRECISION,&NEIBPE(neib), 0, MPI_COMM_WORLD, req1(neib), ierr)
enddo&!C!C-- RECEIVE
do neib= 1, NEIBPETOT
inum = STACK_IMPORT(neib) - STACK_IMPORT(neib-1)
istart= NOD_IMPORT(STACK_IMPORT(neib-1)+1)&call MPI_IRECV (X(istart), inum, MPI_DOUBLE_PRECISION,&NEIBPE(neib), 0, MPI_COMM_WORLD, req1(NEIBPETOT+neib), ierr)enddo
call MPI_WAITALL (2*NEIBPETOT, req1, sta1, ierr)

pFEM3D-1

SEND/RECV (NEW:2), N0: int. node #!C!C-- INIT.
allocate (sta1(MPI_STATUS_SIZE,2*NEIBPETOT))
allocate (req1(2*NEIBPETOT))!C!C-- SEND
do neib= 1, NEIBPETOT
istart= STACK_EXPORT(neib-1)
inum = STACK_EXPORT(neib ) - istart
do k= istart+1, istart+inum
WS(k)= X(NOD_EXPORT(k))
enddo
enddo

N0: 内点総数do neib= 1, NEIBPETOT
istart= STACK_EXPORT(neib-1)
inum = STACK_EXPORT(neib ) - istartcall MPI_ISEND (WS(istart+1), inum, MPI_DOUBLE_PRECISION,&NEIBPE(neib), 0, MPI_COMM_WORLD, req1(neib), ierr)
enddo

&!C
!C-- RECEIVE
do neib= 1, NEIBPETOT
inum = STACK_IMPORT(neib) - STACK_IMPORT(neib-1)
istart= STACK_IMPORT(neib-1) + N0 + 1&

call MPI_IRECV (X(istart), inum, MPI_DOUBLE_PRECISION,&NEIBPE(neib), 0, MPI_COMM_WORLD, req1(NEIBPETOT+neib), ierr)enddo
call MPI_WAITALL (2*NEIBPETOT, req1, sta1, ierr)

12

pFEM3D-2

13

計算例（通信最適化済）@東大
Strong Scaling• 192×192×128節点（4,718,592節点，4,633,087要素）• 16～192コア• Solver計算時間
core #sec.
(speed-up)

16 （4x2x2）
32 （4x4x2）

16.6 （16.0）
8.69 （30.5）

64 （4x4x4）
96 （6x4x4）
128 （8x4x4）
192 （8x6x4）

4.55 （59.6）
3.54 （74.7）
2.69 （98.4）
1.84 （144.）

pFEM3D-2

14

例題：１D～3D分割
どの方法が良いか考えて見よ

1D型

2D型

3D型

15

手順（1/4）>$ cd ~/pFEM/pfem3d/pmesh(1.”mesh.inp”を変更)

1D型
80 80
81pcube2D型
80
180 8042pcube3D型
80
180 8022pcube80216

手順（2/4）(2.”mg.sh”を変更)#!/bin/sh#PJM -L “node=1“#PJM -L “elapse=00:10:00“#PJM -L “rscgrp=small“#PJM #PJM -o “mg.lst“#PJM --mpi “proc=8“
mpiexec ./pmesh

ノード数（≦12）
実行時間（≦15分）
実行キュー名
標準出力
MPIプロセス数（≦192）

17

手順（3/4）>$ cd ../run(3.”go0.sh”を修正)>$ pjsub go0.sh#!/bin/sh#PJM -L “node=1“#PJM -L “elapse=00:10:00“#PJM -L “rscgrp=small“#PJM #PJM -o “mg.lst“#PJM --mpi “proc=8“
mpiexec ./sol0

ノード数（≦12）
実行時間（≦15分）
実行キュー名
標準出力
MPIプロセス数（≦192）

pFEM3D-2

18制御ファイル：INPUT.DAT../pmesh/pcube HEADER
2000
ITER
1.0 1.0
COND, QVOL
1.0e-08RESID• HEADER：• ITER：• COND：• QVOL：• RESID：

局所分散ファイルヘッダ名
pcube.my_rank
反復回数上限熱伝導率
体積当たり発熱量係数
反復法の収束判定値

  T    T    T          Q  x, y , z   0x  x  y  y  z  z Q  x, y, z   QVOL xC  yC

19

手順（4/4）：PCへファイルを移動(4.手元のPCでcygwinもしくはterminalを立ち上げ適当なフォルダへ移動)>$ scp sus15XX@pi.ircpi.kobe-u.ac.jp:~/pFEM/run/test.inp .

（5.Paraviewを立ち上げて，上記”test.inp”を開く）

pFEM3D-2

計算例（通信最適化済）@東大Strong Scaling20• 192×192×128節点（4,718,592節点，4,633,087要素）
core #

sec.
(speed-up)

16 （4x2x2）
32 （4x4x2）

16.6 （16.0）
8.69 （30.5）

64 （4x4x4）
96 （6x4x4）

4.55 （59.6）
3.54 （74.7）

128 （8x4x4）
192 （8x6x4）

2.69 （98.4）
1.84 （144.）

192 192 128
422pcube#!/bin/sh#PJM -L “node=1”#PJM -L “elapse=00:10:00“#PJM -L “rscgrp=small“#PJM #PJM -o “mg.lst“#PJM --mpi “proc=16“
mpiexec ./pmesh#!/bin/sh#PJM -L “node=1”#PJM -L “elapse=00:10:00“#PJM -L “rscgrp=small“#PJM #PJM -o “test.lst“#PJM --mpi “proc=16“
mpiexec ./sol0pFEM3D-2

計算例（通信最適化済）@東大Strong Scaling21• 192×192×128節点（4,718,592節点，4,633,087要素）
core #

sec.
(speed-up)

16 （4x2x2）
32 （4x4x2）

16.6 （16.0）
8.69 （30.5）

64 （4x4x4）
96 （6x4x4）

4.55 （59.6）
3.54 （74.7）

128 （8x4x4）
192 （8x6x4）

2.69 （98.4）
1.84 （144.）

192 192 128
442
pcube
#!/bin/sh#PJM -L “node=2”#PJM -L “elapse=00:10:00“#PJM -L “rscgrp=small“#PJM #PJM -o “mg.lst“#PJM --mpi “proc=32“
mpiexec ./pmesh#!/bin/sh#PJM -L “node=2”#PJM -L “elapse=00:10:00“#PJM -L “rscgrp=small“#PJM #PJM -o “test.lst“#PJM --mpi “proc=32“
mpiexec ./sol0pFEM3D-2

計算例（通信最適化済）@東大Strong Scaling22• 192×192×128節点（4,718,592節点，4,633,087要素）
core #

sec.
(speed-up)

16 （4x2x2）
32 （4x4x2）

16.6 （16.0）
8.69 （30.5）

64 （4x4x4）
96 （6x4x4）

4.55 （59.6）
3.54 （74.7）

128 （8x4x4）
192 （8x6x4）

2.69 （98.4）
1.84 （144.）

192 192 128
864
pcube
#!/bin/sh#PJM -L “node=12”#PJM -L “elapse=00:10:00“#PJM -L “rscgrp=small“#PJM #PJM -o “mg.lst“#PJM --mpi “proc=192“
mpiexec ./pmesh#!/bin/sh#PJM -L “node=12”#PJM -L “elapse=00:10:00“#PJM -L “rscgrp=small“#PJM #PJM -o “test.lst“#PJM --mpi “proc=192“
mpiexec ./sol0