Fortranでプログラムを開発する際に、いくつかの反復プロシージャを使用するため、反復を手動で停止する必要がありました(プログラム終了なしで反復ループを終了する必要があります)。信号がFortranでトラップされたときに変数値を変更する
私はプロセスに信号を送信することにしました。私はSIGALRMを選んだ。私はそれが予期せぬ結果なしに閉じ込めることができることを確認しました。
受信信号を受信すると、フラグの値が変更されます。このフラグは繰り返しループ内でチェックされ、flagがtrueの場合は終了します。そのようなコードのサンプルを以下に示します。
!file mymod.f90
module mymod
use ifport
integer*4 :: err
integer*4 :: SIGNSET
integer*4, parameter :: mySignal=14
logical*1 :: toStopIteration
contains
! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ !
integer*4 function setTrap() result(ret)
implicit none
call PXFSTRUCTCREATE('sigset',SIGNSET,err)
call PXFSIGADDSET(SIGNSET,mySignal,err) !add my signal to the set.
ret=0; return
end function setTrap
! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ !
integer*4 function onTrap(sig_num) result(rcode)
implicit none
integer*4 :: sig_num,err
rcode=0
select case (sig_num)
case(mySignal)
write (*,*) 'Signal occurred. Stop iteration called'
write (*,*) 'flag: ',toStopIteration
toStopIteration=.true.
write (*,*) 'flag: ',toStopIteration
rcode=1
return
case (SIGINT) ; stop
case (SIGTERM); stop
case (SIGABRT); stop
end select
end function onTrap
! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ !
end module mymod
!file main.f90
program main
use mymod
implicit none
integer*4 :: i,j,N,Niters,sum1
err=setTrap()
err=signal(mySignal, onTrap, -1)
toStopIteration=.false.
open (1,file='output')
write (*,*) 'PID=',getpid()
write (1,*) 'Outside',toStopIteration
N=5000000; Niters=100000
do i = 1,Niters
if (toStopIteration) then
toStopIteration=.false.
exit
endif
sum1=0
do j = 1,N
sum1=sum1+j
enddo
write (1,*) i,toStopIteration,sum1
enddo
write (*,*) 'Procedure was terminated due to signal received. The last iteration was', i
write (*,*) 'Now I will do other job for you.'
stop
end program main
アプリケーションはifort:ifort -c -O2 -traceback
でコンパイルされました。私はプロセスkill -14 pid
、 に信号を送信すると 私は、端末への出力を得る:
Signal occurred. Stop iteration called
flag: F
flag: T
しかし、反復ループがまだ実行され、ファイルに書かれたように、変数「toStopIterationは」偽等しいです。
-O0 -traceback
パラメータでコンパイルすると、うまく動作することがわかりました。 どうしてですか?このような最適化レベルでは、変数 "toStopIteration"はローカルになりますか?それを正しく動作させるために何ができるのですか?
ありがとうございます。 MuKeP。
詳細については、この質問をご覧ください。 'logical * 1、volatile :: toStopIteration'文を使う必要があります。しかし、私が正しく理解したように、それは2003年のFortran標準に登場した機能です。 – MuKeP