在Fortran上開發程序時,使用某種迭代過程時,我面臨必須手動停止迭代(從程序終止時退出迭代循環)的必要性。在Fortran中捕獲信號時更改變量值
我決定發送一個信號給進程。我選擇了SIGALRM。我已經檢查過它可以被捕獲而沒有任何意外的後果。
當收到信號時,標誌值被改變。該標誌在迭代循環內被檢查並且如果標誌爲真則退出。下面給出了這種代碼的示例。
!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