fortran66のブログ

fortran について書きます。

【メモ帳】CAF 例題

何故なら image 1 は特別な存在だからです

Fortran の coarray は SPMD 型の並列モデルで、それぞれのイメージはほぼ等価で違いは無いのですが、標準入力だけは image 1 番が担っていて、他のイメージが標準入力をしようとすると実行時エラーが出て叱られます。思いつく限り、これだけが例外の気がします。

なお標準出力の方は、どのイメージでも可能です。

ヴェルタースオリジナル「特別な存在」篇

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

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

プログラム

    program CAF05
        implicit none
        integer :: m[*]
        integer :: ne, me
        
        ne = num_images()
        me = this_image()
        
        if (me == 1) then 
            print *, 'input integer'
            read *, m
        end if    
        
        sync all
        m = m[1] * me
        
        print *, me, m
    end program CAF05

実行結果

 input integer
3
           1           3
           4          12
           7          21
           8          24
           5          15
           6          18
           2           6
           3           9
続行するには何かキーを押してください . . .

排他制御

critical / lock (blocking) / lock (non-blocking)

プログラム

[訂正:H30.9.2] critical 前の sync all が抜けていました。

    program CAF06
        use, intrinsic :: iso_fortran_env, only : lock_type
        implicit none
        type (lock_type) :: lck[*]
        logical :: success
        integer :: ne, me, m[*]
        
        ne = num_images()
        me = this_image()
        m = 0

        sync all 
        critical
            print *, 'critical     ; this_image()=', me
            m[1] = m[1] + 1        
        end critical
        sync all
        if (me == 1) print '(4g0/)', ' sum= ', m, ' num_images()=', ne
        
        
        lock (lck[1])
            print *, 'lock:blocking; this_image()=', me
            m[2] = m[2] + 1        
        unlock (lck[1])
        sync all
        if (me == 2) print '(4g0/)', ' sum= ', m, ' num_images()=', ne
        
        
        lock (lck[1], acquired_lock = success)
        if (success) then 
            print *, 'lock:non-blocking; this_image()=', me
            m[3] = m[3] + 1        
            unlock (lck[1])
        end if    
        sync all
        if (me == 3) print '(4g0)', ' sum= ', m, ' num_images()=', ne
    end program CAF06

実行結果

 critical     ; this_image()=           1
 critical     ; this_image()=           7
 critical     ; this_image()=           5
 critical     ; this_image()=           6
 critical     ; this_image()=           4
 critical     ; this_image()=           8
 critical     ; this_image()=           3
 critical     ; this_image()=           2
 sum= 8 num_images()=8

 lock:blocking; this_image()=           1
 lock:blocking; this_image()=           4
 lock:blocking; this_image()=           3
 lock:blocking; this_image()=           2
 lock:blocking; this_image()=           7
 lock:blocking; this_image()=           5
 lock:blocking; this_image()=           6
 lock:blocking; this_image()=           8
 sum= 8 num_images()=8

 lock:non-blocking; this_image()=           1
 lock:non-blocking; this_image()=           6
 lock:non-blocking; this_image()=           5
 sum= 3 num_images()=8
続行するには何かキーを押してください . . .

image 番号と多次元 coarray の対応

image_index(coarray, [d1, d2..]) と this_image(coarray) で求めます。

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

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

プログラム

Format に無駄な技巧を使いました。/ と : の前後の , は省略できます。(The Fortran 2003 Hnadbook, §10.2)

毎回数値の後に閉じ括弧 ] を書き出します。これ以上データがないときは format は ] 直後の : 位置で終了します。データがまだあれば、TL1 (左に1文字分相対タブ)で1文字カーソル位置を戻して ] が , で上書きされて次のデータの読み込みに戻ります。

コンソール・スクリーンなら問題ないですが、テレタイプ端末などだと上書きされても消えないので問題あるかもw

    program CAF07
        implicit none
        integer :: n1[*], n2[2, *], n3[2, 2, *]
        integer :: ne, me, m2(2), m3(3)
        
        ne = num_images()
        me = this_image()
        !
        if (me == 1) then 
            print *, 'image_index', image_index(n1, [1]), image_index(n2, [2, 3]), image_index(n3, [2, 2, 1])
        end if
        !
        if (me > 1) sync images(me - 1)
        print '(/2g0)', ' image = ', me
        print '( " [", *( g0,"]":TL1, ", ") )', this_image(n1)
        print '( " [", *( g0,"]":TL1, ", ") )', this_image(n2)
        print '( " [", *( g0,"]":TL1, ", ") )', this_image(n3)
        if (me < ne) sync images(me + 1)
    end program CAF07

The Fortran 2003 Handbook: The Complete Syntax, Features and Procedures

The Fortran 2003 Handbook: The Complete Syntax, Features and Procedures

  • 作者: Jeanne C. Adams,Walter S. Brainerd,Richard A. Hendrickson,Richard E. Maine,Jeanne T. Martin,Brian T. Smith
  • 出版社/メーカー: Springer
  • 発売日: 2014/11/30
  • メディア: ペーパーバック
  • この商品を含むブログを見る

実行結果

 image_index           1           6           4

 image = 1
 [1]
 [1, 1]
 [1, 1, 1]

 image = 2
 [2]
 [2, 1]
 [2, 1, 1]

 image = 3
 [3]
 [1, 2]
 [1, 2, 1]

 image = 4
 [4]
 [2, 2]
 [2, 2, 1]

 image = 5
 [5]
 [1, 3]
 [1, 1, 2]

 image = 6
 [6]
 [2, 3]
 [2, 1, 2]

 image = 7
 [7]
 [1, 4]
 [1, 2, 2]

 image = 8
 [8]
 [2, 4]
 [2, 2, 2]
続行するには何かキーを押してください . . .

イメージ 整列 シリアル実行

まず 1~ne の順番で、次に n~1 の順番で。

プログラム

    program CAF007
        implicit none
        integer :: me, ne 
        
        me = this_image()
        ne = num_images()
        !
        ! 1,2,3....,ne
        !
        if (me >  1) sync images (me - 1)
        print *, me
        if (me < ne) sync images (me + 1)
        !
        !
        ! ne, ne-1, ne-2,...,1
        !
        if (me < ne) sync images (me + 1)
        print *, me
        if (me >  1) sync images (me - 1)
    end program CAF007

実行結果

           1
           2
           3
           4
           5
           6
           7
           8
           8
           7
           6
           5
           4
           3
           2
           1
続行するには何かキーを押してください . . .