openmp という、Fortran にコメント文の形でコマンドを挿入して
調べてみたら、何の事は無い gfortran に既に実装されていた。
こんな感じで簡単に使える。
tama@tama[114] cat test_1.f90 program omp use omp_lib write(*,*) 'before' !$omp parallel write(*,*) 'Hello OMP' !$omp end parallel write(*,*) 'after' end program tama@tama[115] gfortran43 -fopenmp test_1.f90 tama@tama[116] setenv OMP_NUM_THREADS 6 tama@tama[117] ./a.out before Hello OMP Hello OMP Hello OMP Hello OMP Hello OMP Hello OMP after6つ動作しているのが分かる。
ここ(京都大学) に、フォートランでの openmp の使い方もありました。
これで、数値モデルが書けない言い訳は無くなって行く。。。。
integer, parameter :: n=1000 integer :: i real :: x(n) !$omp parallel !$omp do do i=1, n x(i) = i end do !$omp end do open(unit=10, file="OUT") !$omp do do i=2, n x(i) = log(abs(cos(sin(x(i)+x(i-1))))) write(10,*) i, x(i) end do !$omp end do !$omp end parallel close(10) endこんなのを実行すると、出力 OUT には見事にばらばらの情報が書かれる。 setenv OMP_NUM_THREADS 4; ./a.out した結果は
cat -n OUT | xgraph -P -nlの結果 (を convert で jpg にしたもの) は
うーん、当り前! (2009.11) こういう時の安直な解決方法は、oedered を使って、do ループ内の出力順序を 決めることであるらしい。 (でも、下手をすると実行速度は落ちていくようだ。 他のスレッドが安直に待ってしまって実質1スレッド計算になる? 2009.12)
integer, parameter :: n=1000 integer :: i real :: x(n) !$omp parallel !$omp do do i=1, n x(i) = i end do !$omp end do open(unit=10, file="OUT") !$omp do ordered do i=2, n x(i) = log(abs(cos(sin(x(i)+x(i-1))))) !$omp ordered write(10,*) i, x(i) !$omp end ordered end do !$omp end do !$omp end parallel close(10)というように、!$omp do ordered 〜 !$omp end ordered で囲んだループ内の 出力文を !$omp ordered 〜 !$omp end ordered で囲んでやると、順番通り出力する。 (2009.11)
implicit none integer, parameter :: N=1000, M=1000, NN=10, MAX_THREAD=10 integer :: i, j, i1, j1 real, allocatable :: x(:,:), y(:,:) !$use omp_lib character(len=1024) :: omp_num_threads integer, external :: omp_get_thread_num integer :: i_omp_num_threads, i_thread integer :: ifile character(len=1024) :: filename integer :: neach, istart, iend call getenv("OMP_NUM_THREADS", omp_num_threads) read(omp_num_threads, *) i_omp_num_threads write(0,*) 'OMP_NUM_THREADS ', i_omp_num_threads !allocate( x(N,M) ) !allocate( y(N,M) ) neach = N/i_omp_num_threads !$omp parallel private(i_thread, istart, iend, filename, ifile, i, j, x, y ) i_thread = omp_get_thread_num() write(*,*) 'thread num = ', i_thread istart = neach * i_thread + 1 iend = neach * (i_thread+1) ifile = 10+i_thread write(filename, '("OUT-", I1)') i_thread allocate( x(neach,M) ) allocate( y(neach,M) ) do i=istart, iend do j=1, M x(i,j) = log(abs( sin(0.2*i*j))) end do end do open(unit=ifile, file=filename(1:len_trim(filename))) if( istart < NN+1 ) istart = NN+1 if( iend > N-NN ) iend = N-NN do i=istart, iend do j=NN+1, M-NN y(i,j) = 0 do i1=-NN, NN do j1 = -NN, NN y(i, j) = y(i,j) + x(i+i1, j+j1) end do end do y(i,j) = y(i,j) / ((2*NN+1)*(2*NN+1)) end do write(ifile, *) i, (y(i,j), j=NN+1, M-NN) end do close(ifile) !$omp end parallel endメモのトップへ