fortran66のブログ

fortran について書きます。

CAF event

CAF event post / event wait

Intel Fortran ver.19 beta に導入されている Fortran2018 の CAF の event 機能を試してみます。

Parallel Programming with Co-arrays (Chapman & Hall/CRC Computational Science)

Parallel Programming with Co-arrays (Chapman & Hall/CRC Computational Science)

プログラム

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

Modern Fortran Explained: Incorporating Fortran 2018 (Numerical Mathematics and Scientific Computation)

Modern Fortran Explained: Incorporating Fortran 2018 (Numerical Mathematics and Scientific Computation)

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