Global⇒Localが必要になる場合 「並列」有限要素法

Global⇒Localが必要になる場合
「並列」有限要素法
2008年4月2日
中島研吾
普通は・・・(1/2)
• データはもともと分散している
• 分散したデータを個別に読み込む
PE #0
PE #1
PE #2
PE #M-1
Program
Program
Program
Program
Data #0
Data #1
Data #2
Data #M-1
2
普通は・・・(2/2)
• そして,ローカルに計算する
real, dimension(:), allocatable :: X, Y
real, dimension(:), allocatable :: PROP
integer, dimension (:,:), allocatable :: ELEM
character (len=80):: HEADER, filename
character (len= 1):: SUBindex1
…
!C ローカルファイル名の指定
write(SUBindex1 ,'(i1.1)') my_rank
LENGTH= len_trim(HEADER)
filename= HEADER(1:LENGTH)//'.'//SUBindex1
…
!C ローカルファイルのオープン,読み込み
open (IN, file= filename, …)
read (IN,*) n_node, n_elem
allocate (X(n_node), Y(n_node))
allocate (PROP(n_elem), ELEM(8,n_elem))
…
3
しかし,時々・・・(1/3)
• 全体ファイルを読み込んで
real, dimension(:), allocatable :: Xg
real, dimension(:), allocatable :: Xl
integer, dimension(:,:), allocatable :: IDg
integer, dimension(:),
allocatable :: NEWtoOLDl
…
!C 全体ファイルの読み込み
open (IN, file= filename, …)
read (IN,*) Ng
allocate (Xg(Ng))
read (IN,*) Xg(:)
4
しかし,時々・・・(2/3)
• 領域分割を内部でやって
real, dimension(:), allocatable :: Xg
real, dimension(:), allocatable :: Xl
integer, dimension(:,:), allocatable :: IDg
integer, dimension(:),
allocatable :: NEWtoOLDl
…
!C 全体ファイルの読み込み
open (IN, file= filename, …)
read (IN,*) Ng
allocate (Xg(Ng))
read (IN,*) Xg(:)
…
!C 領域分割
call PARTITION (Ng, Nl, MPROC …)
5
しかし,時々・・・(3/3)
• ローカルデータを生成して計算したくなることがある
real, dimension(:), allocatable :: Xg
real, dimension(:), allocatable :: Xl
integer, dimension(:,:), allocatable :: IDg
integer, dimension(:),
allocatable :: NEWtoOLDl
…
!C 全体ファイルの読み込み
open (IN, file= filename, …)
read (IN,*) Ng
allocate (Xg(Ng))
read (IN,*) Xg(:)
…
!C 領域分割
call PARTITION (Ng, Nl, MPROC …)
…
!C ローカルなデータの生成
allocate (Xl(Nl))
Xg => Xl
6
ローカルデータの生成は簡単ではない
• グローバル配列の「順番」に分割するわけではない:
– 特に複雑形状:
real, dimension(:), allocatable :: Xg
real, dimension(:), allocatable :: Xl
integer, dimension(:,:), allocatable :: IDg
integer, dimension(:),
allocatable :: NEWtoOLDl
…
!C 全体ファイルの読み込み
open (IN, file= filename, …)
read (IN,*) Ng
allocate (Xg(Ng))
read (IN,*) Xg(:)
…
!C 領域分割
call PARTITION (Ng, Nl, NPE …)
…
!C ローカルなデータの生成
allocate (Xl(Nl))
Xg => Xl
7
ローカルデータの生成法:その1
• ローカルな配列「NEWtoOLDl」
– サイズ (Nl)
– NEWtoOLDl(ローカル番号)=グローバル番号
– 「Nl」が予めわかっていないので,「NEWtoOLDl」の割付
には工夫が必要
real, dimension(:), allocatable :: Xg
real, dimension(:), allocatable :: Xl
integer, dimension(:,:), allocatable :: IDg
integer, dimension(:),
allocatable :: NEWtoOLDl
…
!C ローカルなデータの生成
allocate (Xl(Nl))
do i= 1, Ng
if (IDg(i,2).eq.my_rank) then
Xl(IDg(i,1))= Xg(i)
endif
enddo
8
ローカルデータの生成法:その2
• グローバルな配列「IDg」:Double Numbering
–
–
–
–
サイズ (Ng,2)
IDg(グローバル番号,1)=ローカル番号
IDg(グローバル番号,2)=所属領域番号
コーディングはラク
real, dimension(:), allocatable :: Xg
real, dimension(:), allocatable :: Xl
integer, dimension(:,:), allocatable :: IDg
integer, dimension(:),
allocatable :: NEWtoOLDl
…
!C ローカルなデータの生成
allocate (Xl(Nl))
do i= 1, Ng
if (IDg(i,2).eq.my_rank) then
Xl(IDg(i,1))= Xg(i)
endif
enddo
9
まとめ
• 「全体ファイル」をまず読み込むような場合
– 「Nl」は領域分割するまでわからない
– ローカル配列は「allocatable」属性であるのが普通で
– p.8の「NEWtoOLDl」のような配列を生成するには工夫が必
要:ユーティリティ,ライブラリで隠蔽
• ・・・で結局のところ
– こういう計算の仕方はあまりしない
– 初心者が比較的小規模な問題を解くときに使う・・・という可能
性もあるが,p.8・p.9に書いたように結構技巧的である
• このようなことができるのであれば,既に初心者では無いといえる
• 次ページのように,グローバル配列を領域番号順に並
び替えられていれば,初診者にも扱いやすい
10
ローカルデータの生成法:その3
• グローバルな配列「NDIVg」
– サイズ (0:NPE)
– NDIVg(my_rank)+1~NDIVg(my_rank+1) に相当する
部分が「my_rank」の領域で処理されるローカルデータ
• 「Xg」等の配列が各領域で連続となるように並び替えられている
必要がある
real, dimension(:), allocatable :: Xg
real, dimension(:), allocatable :: Xl
integer, dimension(:),
allocatable :: NDIVg
…
allocate (NDIVg(0:NPE))
…
!C ローカルなデータの生成
Nl= NDIVg(my_rank+1) – NDIVg(my_rank)
allocate (Xl(Nl))
do i= 1, Nl
Xl(i)= Xg(i+NDIVg(my_rank))
enddo
11