CAF (CoArray Fortran) で Halo Exchange
CAF (CoArray Fortran) で境界のヘリの交換(Halo Exchange)をやってみました。もしくは後光の交換。
Halo のイメージ なんとなくビザンチンのモザイク画
Parallel Programming with Co-arrays (Chapman & Hall/CRC Computational Science)
- 作者: Robert W. Numrich
- 出版社/メーカー: Chapman and Hall/CRC
- 発売日: 2018/09/24
- メディア: ハードカバー
- この商品を含むブログを見る
10世紀末頃ビザンチンで編纂された百科全書的辞書。『スーダ』 Suda
Stoa | Welcome to the Suda On Line (SOL)
ソース・プログラム1
Intel Fortran Ver.18
コア数9個に設定 3*3 の coshape とした。上下方向には周期境界条件を、左右方向は普通の境界を設定した。各イメージ固有の配列サイズは 2*2 として、その周囲を囲むように幅 1 の縁を置いた。
以下のプログラムでは、各列ないし各行毎にシリアルな順序つき実行になっている。
program CAF001 implicit none real, allocatable :: a(:, :)[:, :] integer :: me, ne, nx = 2, ny = 2 integer :: ix, iy, ipos(2) ne = num_images() me = this_image() allocate(a(0:nx + 1, 0:ny + 1)[3, *]) ix = this_image(a, 1) iy = this_image(a, 2) ! ! initial value a = me a(:, 0 ) = 0.0 a(:, ny + 1) = 50.0 ! ! Halo exchange ! up <--> down sync all if (ix < ucobound(a, 1)) then sync images ( image_index(a, [ix + 1, iy]) ) a(0 , :)[ix + 1, iy] = a(ny, :) end if if (lcobound(a, 1) < ix) then a(ny + 1, :)[ix - 1, iy] = a( 1, :) sync images ( image_index(a, [ix - 1, iy]) ) end if ! periodic boundary condition if (ix == ucobound(a, 1)) then sync images ( image_index(a, [lcobound(a, 1), iy]) ) a(0 , :)[lcobound(a, 1), iy] = a(ny, :) end if if (ix == lcobound(a, 1)) then a(ny + 1, :)[ucobound(a, 1), iy] = a( 1, :) sync images ( image_index(a, [ucobound(a, 1), iy]) ) end if ! ! left <--> right sync all if (iy < ucobound(a, 2)) then sync images ( image_index(a, [ix, iy + 1]) ) a(:, 0)[ix, iy + 1] = a(:, ny) end if if (lcobound(a, 2) < iy) then a(:, ny + 1)[ix, iy - 1] = a(:, 1) sync images ( image_index(a, [ix, iy - 1]) ) end if ! ordered output 1..ne if ( 1 < me) sync images (me - 1) print *, 'image=', me print '(4f5.1)', transpose(a) if (me < ne) sync images (me + 1) end program CAF001
個々の配列要素の重なりさえ避けられれば、基本的に sync はあまり必要ない。しかし要所要所で sync all することになるので、同期がモッサリする。
- 作者: Michael Metcalf,John Reid,Malcolm Cohen
- 出版社/メーカー: Oxford Univ Pr
- 発売日: 2018/11/06
- メディア: ハードカバー
- この商品を含むブログを見る
ソース・プログラム2
細かい sync をせず、区切りごとに sync all した場合。
どうするのが一番いいのか、よく分からない。coarray 代入には PUT 形式の方が GET 形式より、一般に性能が出やすいらしいが・・・ (PUT形式: a[i] = b, GET形式: a = b[j])
program CAF001 implicit none real, allocatable :: a(:, :)[:, :] integer :: me, ne, nx = 2, ny = 2 integer :: ix, iy, ix1, ix2, iy1, iy2 ne = num_images() me = this_image() print *, me, '/', ne allocate( a(0:nx + 1, 0:ny + 1)[3, *] ) ! ix = this_image(a, 1) iy = this_image(a, 2) ! ! periodic configuration ! if (ix == lcobound(a, 1)) then ix1 = ucobound(a, 1) else ix1 = ix - 1 end if if (ix == ucobound(a, 1)) then ix2 = lcobound(a, 1) else ix2 = ix + 1 end if if (iy == lcobound(a, 2)) then iy1 = ucobound(a, 2) else iy1 = iy - 1 end if if (iy == ucobound(a, 2)) then iy2 = lcobound(a, 2) else iy2 = iy + 1 end if ! ! initial value ! a = me a(:, 0 ) = 0.0 a(:, ny + 1) = 50.0 ! ! Halo exchange ! ! up <--> down : periodic boundary condition sync all a(nx + 1, :)[ix1, iy] = a( 1, :) a(0 , :)[ix2, iy] = a(nx, :) ! ! left <--> right sync all if ( iy > lcobound(a, 2) ) a(:, ny + 1)[ix, iy1] = a(:, 1) if ( iy < ucobound(a, 2) ) a(:, 0)[ix, iy2] = a(:, ny) ! ! ordered output 1..ne ! sync all if ( 1 < me) sync images (me - 1) print *, 'image=', me print '(4f5.1)', transpose(a) if (me < ne) sync images (me + 1) end program CAF001
実行結果
イメージ番号配置 (処理系により勝手に設定される?)
1 4 7
2 5 8
3 6 9
上下方向には周期境界条件。左右方向は普通の境界。
4 4 : 3 3 4 4 : 3 3 4 4 : 3 3 4 4 : 3 3 4 4 : 3 3 4 4 : 3 3 4 4 : 3 3 4 4 : 3 3 4 4 : 3 3 image= 1 0.0 3.0 3.0 6.0 0.0 1.0 1.0 4.0 0.0 1.0 1.0 4.0 0.0 2.0 2.0 5.0 image= 2 0.0 1.0 1.0 4.0 0.0 2.0 2.0 5.0 0.0 2.0 2.0 5.0 0.0 3.0 3.0 6.0 image= 3 0.0 2.0 2.0 5.0 0.0 3.0 3.0 6.0 0.0 3.0 3.0 6.0 0.0 1.0 1.0 4.0 image= 4 3.0 6.0 6.0 9.0 1.0 4.0 4.0 7.0 1.0 4.0 4.0 7.0 2.0 5.0 5.0 8.0 image= 5 1.0 4.0 4.0 7.0 2.0 5.0 5.0 8.0 2.0 5.0 5.0 8.0 3.0 6.0 6.0 9.0 image= 6 2.0 5.0 5.0 8.0 3.0 6.0 6.0 9.0 3.0 6.0 6.0 9.0 1.0 4.0 4.0 7.0 image= 7 6.0 9.0 9.0 50.0 4.0 7.0 7.0 50.0 4.0 7.0 7.0 50.0 5.0 8.0 8.0 50.0 image= 8 4.0 7.0 7.0 50.0 5.0 8.0 8.0 50.0 5.0 8.0 8.0 50.0 6.0 9.0 9.0 50.0 image= 9 5.0 8.0 8.0 50.0 6.0 9.0 9.0 50.0 6.0 9.0 9.0 50.0 4.0 7.0 7.0 50.0