機能の違いをつらつら読んで見ますと、以下のような違いがあります。
critical | no flag | blocking | random order |
lock | lock_type | blocking | random order |
lock+acquired | lock_type+logical | non-blocking | random order |
atom | atomic_logical_kind/atomic_int_kind | non-blocking | user-specified order |
critical
criticalは最もお手軽で、余分な変数がいりません。全imageが対象になります。ひとつの image だけが critical 領域を実行でき、残りの image はブロックされて、lock が順々に解除されるまで待つことになります。
program caf_critical implicit none integer :: m[*] = 0 critical m[1] = m[1] + 1 end critical sync all print *, this_image(), m stop end program caf_critical
lock
lock は lock変数が必要になります。intrinsic な定義型 type(lock_type) 形が lock となります。critical との違いは、lock を image ごとに指定できるので、特定の image 群に関しての処理ができる点だと思います。(critical は全 image 一括での扱い。)
program CAF_lock use iso_fortran_env implicit none integer :: m[*] = 0, imags type(lock_type) :: flag[*] imags = mod(this_image(), 2) + 1 ! images 1 or 2 lock(flag[imags]) m[imags] = m[imags] + 1 unlock(flag[imags]) sync all print *, this_image(), m stop end program CAF_lock
lock+acquired_lock
lock で acuired_lock オプションをつけると、lock を取れなかった image はブロックされて待つことなく実行を続けます。したがって、lock 解放待ちの処理もユーザー側で行わなければなりません。
program CAF_lock_acquire use iso_fortran_env implicit none integer :: m[*] = 0 type(lock_type) :: flag[*] logical :: acloc do lock(flag[3], acquired_lock = acloc) print *, this_image(), acloc if (acloc) exit end do m[3] = m[3] + 1 unlock(flag[3]) sync all print *, this_image(), m stop end program CAF_lock_acquire
atom
atom は一番面倒で、Modern Fortran Explained 非使用奨励になっています。
一番素朴な機能を持っており、lock にあたる操作を行うとき、どの image を lock するかというところからユーザーが決めないとなりません。逆に言うと、どの image の順で実行を行うかユーザー側が指定できます。
program caf_atom use iso_fortran_env implicit none integer :: m[*] = 0 logical :: val logical(atomic_logical_kind) :: atom[*] = .true. integer :: i do i = 1, num_images() if (this_image() == i) then m[4] = m[4] + 1 call atomic_define(atom[4], .false.) print *, this_image(), 'atomic' sync memory else val = .true. do while(val) call atomic_ref(val, atom[4]) end do sync memory end if end do sync all print *, this_image(), m stop end program caf_atom