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
© Copyright 2024 ExpyDoc