OpenMP* の使用例

次の例では、OpenMP* 機能の使用方法を示します。「OpenMP Fortran バージョン 2.0 仕様」の例も参照してください。

DO: 単純な差分演算子

この例は、各繰返しごとに命令数が異なる単純な並列ループを示したものです。負荷のバランスをとるために、動的スケジューリングを使用しています。並列領域の最後に暗黙的な BARRIER があるため、END DO に NOWAIT が含まれています。

       subroutine do_1 (a,b,n)
real a(n,n), b(n,n)
c$omp parallel
c$omp&   shared(a,b,n)
c$omp&   private(i,j)
c$omp do schedule(dynamic,1)
do i = 2, n
do j = 1, i
b(j,i) = ( a(j,i) + a(j,i-1) ) / 2
enddo
enddo
c$omp end do nowait
c$omp end parallel
end

DO: 2 つの差分演算子

この例では、fork/join のオーバーヘッドを減らすために融合される 2 つの並列領域を示します。2 番目のループで使用するすべてのデータは最初のループで使用されるすべてのデータと異なるため、最初の END DO には NOWAIT を含んでいます。

       subroutine do_2 (a,b,c,d,m,n)
real a(n,n), b(n,n), c(m,m), d(m,m)
c$omp parallel
c$omp&   shared(a,b,c,d,m,n)
c$omp&   private(i,j)
c$omp do schedule(dynamic,1)
do i = 2, n
do j = 1, i
b(j,i) = ( a(j,i) + a(j,i-1) ) / 2
enddo
enddo
c$omp end do nowait
c$omp do schedule(dynamic,1)
do i = 2, m
do j = 1, i
d(j,i) = ( c(j,i) + c(j,i-1) ) / 2
enddo
enddo
c$omp end do nowait
c$omp end parallel
end

SECTIONS: 2 つの差分演算子

この例では、SECTIONS ディレクティブの使用方法を示します。ロジックは、前述の DO の例と同じですが、DO の代わりに SECTIONS を使用します。ここでは、2 つの作業単位しかないため、速度の向上は、2 が限度です。上記の 「do: 2 つの差分演算子」では、作業単位は n-1 + m-1 です。

  subroutine sections_1 (a,b,c,d,m,n)
real a(n,n), b(n,n), c(m,m), d(m,m)
!$omp parallel
!$omp& shared(a,b,c,d,m,n)
!$omp& private(i,j)
!$omp sections
!$omp section
do i = 2, n
do j = 1, i
b(j,i)=( a(j,i) + a(j,i-1) ) / 2
enddo
enddo


!$omp section
do i = 2, m
do j = 1, i
d(j,i)=( c(j,i) + c(j,i-1) ) / 2
enddo
enddo
!$omp end sections nowait
!$omp end parallel
end

SINGLE: 共有スカラの更新

この例では、共有配列 a の要素を更新する SINGLE 構造の使用方法を示します。最初のループの後にくるオプションの NOWAIT は取り除かれています。これは、SINGLE 構造に進む前にループの最後で待機する必要があるためです。

  subroutine sp_1a (a,b,n)
real a(n), b(n)
!$omp parallel
!$omp& shared(a,b,n)
!$omp& private(i)
!$omp do
do i = 1, n
a(i) = 1.0 / a(i)
enddo
!$omp single
a(1) = min( a(1), 1.0 )
!$omp end single
!$omp do
do i = 1, n
b(i) = b(i) / a(i)
enddo
!$omp end do nowait
!$omp end parallel
end