openMP fortran 回文数ソースプログラム

Last update:2018/03/02    Build:2018/03/02
! cpu を マルチで使う
! openmpを使ってみる do文を実行 -->
! 2018/2/16 read文で引っかかる。open文のみはOK
! なぜか? openmpを使わない場合のread文はOK
! 8バイト精度整数 integer(i_8)をやめることで実行可能となった --> 2018/2/17
!
! 8バイト精度整数 integer(i_8)が使えないので倍精度実数でかけ算を行う
! 1031130番目までの素数を全て読み込み倍精度でかけ算を行う
! 2018/2/17  100万個を読み込むとエラーがでるので 20万個で試す
!      うまくいかない。エラーで止まる
! appcrash c00000fd  00002b73
!  [見解]例外コード:ソフトウェア例外「0xC00000FD」は、
! Windowsアプリケーション実行時にスタックオーバーフローエラーが発生したことを意味しています。
!      ↓
! 動的に割り当てるとスタックを使わないとの記述があり試してみる (2018/2/19→ 
! うまくいった。エラーが出ない(2018/2/19)
!
! 回文のチェック
! 2018/2/19 --> OK
! ただし、複数のCPUを動かしてファイルアウトプットを行うと、おかしくなる
!
! privite変数を使うことと、共通変数を使うために排他的使用(critical)
! を使ってみる(2018/2/20)
! 実行はするが、回文数がマイナスになってエラーとなる。intがおかしいようだ
! 出力のフォーマット文で回文数のI22をF25.0に変更してOK
!
! 3万番目まで計算するとエラーがでる
! 倍精度実数の切り捨てにint()を使っていたのをaint()に変更してみる openmp-13.f90
! うまくいった。(2018/2/20)  -->素数20万番目の積まで回文数をチェック(openmp-16.f90)
!
! 2018/2/21 -->
! openmp-17.f90 スケジュールをダイナミックでスレッドを均等化 schedule
!  openmp-40-3.f90 schedule( dynamic 20000 ) 10万番目までチェック
!


program helloOpenMP
!$ use omp_lib

implicit none

character(30) seki,fmt,fmt2
integer , parameter :: i_8=8                     ! 8バイト型の整数をためす
integer(i_8) , parameter :: i_prime_end  = 1031130    ! 素数の最後の番数(○番目) 2018/2/19
integer :: i_long                         ! 8バイト型整数の宣言 18桁まで
integer :: kosu
integer :: i_p_end       =  100000  ! 仮の最後

integer , allocatable :: i_prime(:)   ! 配列の動的割り当て  i_prime_end(1031130)番目までの素数を入れる 2018/2/19
integer , allocatable :: m_n(:,:)     ! 配列の動的割り当て  回文数となるm、nを入れる  2018/2/19
double precision , allocatable :: kaibun(:)     ! 配列の動的割り当て  回文数を入れる  2018/2/19

integer :: i_prime_tochu = 1031110                  ! 素数の途中の番数(○番目)
integer :: kazu = 0      !  回文数の数をカウント
real :: t1, t2           ! 時間計測用
integer i,j,k,l,l2,m,n   ! 9桁まで
integer  dmy
double precision  dd ,ddd,ww,rev

allocate( i_prime( i_prime_end ) )  !  動的に割り当てる スタックを使わない
allocate( m_n( i_prime_end,2 ) )  !  動的に割り当てる スタックを使わない
allocate( kaibun( i_prime_end ) )  !  動的に割り当てる スタックを使わない

fmt='(i8,i8,i10,i8,i10,"  ",f25.0)'
fmt2='(i10)'

print *,"START"

! call sleep(2)

  call cpu_time( t1 ) ! 時間計測開始

print *,"Read Prime START 2"

open(51,file='prime_1600.txt',status='old',err=100)

do  i=1 , i_prime_end       ! ファイルを読み込むとエラーが出る
!  read(51,*) dmy        ! dmyに読み込むのではエラーなし
  read(51,*) i_prime(i) ! ここをコメントアウトするとエラーなし
end do

close(51)

! 途中時間計測
call cpu_time( t2 )
print *, "cpu time:", t2-t1, "seconds."

print *,"OpenMP START 3"

kosu=0
!  素数のかけ算の繰り返しで時間計測
!$omp parallel  private(dd,ddd,rev,ww) 
!$omp do schedule( dynamic , 20000 ) 
do m=1,i_p_end
  do n=m,i_p_end
    dd =dble(i_prime(m) ) * dble(i_prime(n) )
    ddd=dd
    rev=0
    do while ( ddd>0 )  ! 数字を逆転する
      ww=aint(ddd/10)
      rev=rev * 10 + (ddd - 10*ww )
      ddd=ww
    end do  
    if ( rev == dd ) then
!$omp critical            ! kosu を排他的に処理
      kosu= kosu + 1
      m_n( kosu ,1)=m
      m_n( kosu ,2)=n
      kaibun( kosu ) = dd
!$omp end critical
    end if

  end do  !  n
end do !  m
!$omp end do
!$omp end parallel

! 途中時間計測
call cpu_time( t2 )
print *, "cpu time:", t2-t1, "seconds."
print *,"File out START 4"


open(61,file='out.txt',status='replace',err=200)
do i=1,kosu
  write(61,fmt) i , m_n(i,1), i_prime(m_n(i,1)) ,m_n(i,2),i_prime(m_n(i,2)) , kaibun(i) 
end do
close(61)



! 時間計測終了
call cpu_time( t2 )
print *, "cpu time:", t2-t1, "seconds."


stop

100 write(*,*) "file open error"
stop

200 write(*,*) "output file open err"
stop

end





電子工作へ     HomePage     このページのトップ