CAF event post / event wait
Intel Fortran ver.19 beta に導入されている Fortran2018 の CAF の event 機能を試してみます。
Parallel Programming with Co-arrays (Chapman & Hall/CRC Computational Science)
- 作者: Robert W. Numrich
- 出版社/メーカー: Chapman and Hall/CRC
- 発売日: 2018/09/24
- メディア: ハードカバー
- この商品を含むブログを見る
プログラム
image1 でエラトステネスのふるいで 100 までの素数を求め、その素数の総数分の配列を各イメージで確保しますが、次にそれぞれのイメージ番号目の素数を1個だけコピーします。(意味不明w)
本来は image1 から put してやればいいと思うのですが、学習のためなので意味不明でも許してください。
人為的に image2 を遅延させています。
if (me == 2) call sleep(2) ! non-standard
program CAF09 use, intrinsic :: iso_fortran_env implicit none type (event_type) :: event[*] integer :: me, ne integer :: i, it(100), np[*] integer, allocatable :: ip(:), m(:)[:] me = this_image() ne = num_images() if (me == 1) then ! prime numbers with the sieve of Eratosthenes forall (integer:: i = 1:100) it(i) = i it(1) = 0 do i = 1, int(sqrt(100.0)) if (it(i) /= 0) it(i**2::i) = 0 end do ip = pack(it, it /= 0) np = size(ip) print '(i4, a/, (10i4))', np, ':', ip do i = 2, ne event post (event[i]) end do else event wait (event) np = np[1] end if allocate(m(np)[*]) if (me == 1) then m = ip do i = 2, ne event post (event[i]) end do else if (me == 2) call sleep(2) ! non-standard event wait (event) m(me) = m(me)[1] end if print *, 'me:', me, m(me) end program CAF09
実行結果
image2 だけを眠らせて遅らせたので、image2 以外はさっさと結果を書いて終わりますが、image2 は最後に一人遅れて結果を書き出します。
25: 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 me: 1 2 me: 3 5 me: 4 7 me: 6 13 me: 8 19 me: 5 11 me: 7 17 me: 2 3
- 作者: Michael Metcalf,John Reid,Malcolm Cohen
- 出版社/メーカー: Oxford Univ Pr
- 発売日: 2018/11/06
- メディア: ハードカバー
- この商品を含むブログを見る
sync images (*) / sync images (1) の場合
上記と同内容のことを Fortran2008 の範囲内でやると sync images (*) / sync images (1) の組み合わせで実現出来ますが、この場合 sync のところで不必要な待ち合わせが行われてしまいます。(全員集合するまで待機)
プログラム
program CAF08 use, intrinsic :: iso_fortran_env implicit none ! type (event_type) :: event[*] integer :: me, ne integer :: i, it(100), np[*] integer, allocatable :: ip(:), m(:)[:] me = this_image() ne = num_images() if (me == 1) then ! prime numbers by sieve of eratosthenes forall (integer:: i = 1:100) it(i) = i it(1) = 0 do i = 1, int(sqrt(100.0)) if (it(i) /= 0) it(i**2::i) = 0 end do ip = pack(it, it /= 0) np = size(ip) print '(i4, a/, (10i4))', np, ':', ip sync images(*) ! wait else sync images(1) np = np[1] end if allocate(m(np)[*]) ! implicit sync all if (me == 1) then m = ip sync images(*) ! wait else if (me == 2) call sleep(2) ! non-standard sync images(1) m(me) = m(me)[1] end if print *, 'me:', me, m(me) end program CAF08
実行結果
実行結果は同じですが、image2 を遅らせると、sync のところで全員集合するまで、全 image が待ち合わせするので、全 image が遅れて一気に出力されます。
私は少し勘違いしていて、sync all と違って、sync images(*) / sync images(1) の場合、image1 は全員の点呼を取るまで待機するが、他の image は image1 と sync した後は、そのまま待機せずに通過だと思っておりました。実際は sync all と同様に全 image が集合するまで全員待機の模様です。
25: 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 me: 1 2 me: 4 7 me: 2 3 me: 8 19 me: 5 11 me: 6 13 me: 7 17 me: 3 5