fortran array=0 优化时未给定值
fortran array=0 not given values when optimized
我有一个相当大的代码(>6000 行)有一个问题,我尝试用以下非常简化的摘录来说明:
program TestFortran
implicit none
real, parameter :: eps = 1d-30
real :: res
real :: tmp
call TestInitialisation(res,tmp)
if (res>0 .and. res <eps) then
write(*,*) "res is small but not zero and tmp = ", tmp
res = 0d0
else
write(*,*) "res is zero and tmp = ", tmp
end if
contains
subroutine TestInitialization(output,out2)
real,intent(out) :: output
real,intent(out) :: out2
real :: origa(10,10)
real :: copya(10,10)
origa = 0d0
copya = origa
call TIS1(copya,output,out2)
end subroutine TestInitialization
subroutine TIS1(arr2d,ret,out2)
real,intent(in) :: arr2d(:,:)
real,intent(out) :: ret
real,intent(out) :: out2
integer :: ii
do ii = 1,size(arr2d,2)
call TIS2(arr2d(:,ii),ii,ret,out2)
if (ret > 0) then
exit
end if
end do
end subroutine TIS1
subroutine TIS2(arr1d,jj,ret,out2)
real,intent(in) :: arr1d(:)
real,intent(out) :: ret
real,intent(out) :: out2
integer :: ii
integer,intent(in):: jj
do ii = 1,size(arr1d)
ret = arr1d(ii)
out2 = real(jj)
if (ret > 0) then
out2 = -1d0
exit
end if
end do
end subroutine TIS2
end program TestFortran
真实程序在调试模式下确实按预期工作。然而,当处于发布模式(visual studio 2017 with intel compiler 2017)时,切换 /O3,res
值只是垃圾(比如 1.0831d-273,但是我不确定天气是否信任变量 explorer调试优化代码时)。我无法用上面的例子重现这种情况,它只是为了说明(tmp
变量在那里,而不是仅仅优化整个事情)。如果我在 真实程序 代码中添加一个 write(*,*) "res in TIS2 =",res
in 子程序 TIS2
,结果是正确的,但这是不想要的(尤其是因为速度下降)。
我已经测试了各种编译器标志组合;即以下内容:
/debug:full /O2 /Qinit:snan /Qinit:arrays /fpe:0 /Qipo /traceback
/check:uninit /arch:SSE3 /real_size:64 /fp:fast=2 /Qvec-threshold:60 /recursive
有人对此有任何提示或意见吗?
我犯了一个错误(错误),其中数组未正确填充。我在调试模式下使用编译器标志发现了这一点:/Qinit:snan
和 /Qinit:arrays
。它没有出现在发布模式中。
所以总而言之,这只是我的代码中一个相当简单的错误,没有引起注意,大多数情况下(在 99% 的情况下)一切顺利,但并非总是如此。奇怪的是它并没有被释放模式捕获。
我有一个相当大的代码(>6000 行)有一个问题,我尝试用以下非常简化的摘录来说明:
program TestFortran
implicit none
real, parameter :: eps = 1d-30
real :: res
real :: tmp
call TestInitialisation(res,tmp)
if (res>0 .and. res <eps) then
write(*,*) "res is small but not zero and tmp = ", tmp
res = 0d0
else
write(*,*) "res is zero and tmp = ", tmp
end if
contains
subroutine TestInitialization(output,out2)
real,intent(out) :: output
real,intent(out) :: out2
real :: origa(10,10)
real :: copya(10,10)
origa = 0d0
copya = origa
call TIS1(copya,output,out2)
end subroutine TestInitialization
subroutine TIS1(arr2d,ret,out2)
real,intent(in) :: arr2d(:,:)
real,intent(out) :: ret
real,intent(out) :: out2
integer :: ii
do ii = 1,size(arr2d,2)
call TIS2(arr2d(:,ii),ii,ret,out2)
if (ret > 0) then
exit
end if
end do
end subroutine TIS1
subroutine TIS2(arr1d,jj,ret,out2)
real,intent(in) :: arr1d(:)
real,intent(out) :: ret
real,intent(out) :: out2
integer :: ii
integer,intent(in):: jj
do ii = 1,size(arr1d)
ret = arr1d(ii)
out2 = real(jj)
if (ret > 0) then
out2 = -1d0
exit
end if
end do
end subroutine TIS2
end program TestFortran
真实程序在调试模式下确实按预期工作。然而,当处于发布模式(visual studio 2017 with intel compiler 2017)时,切换 /O3,res
值只是垃圾(比如 1.0831d-273,但是我不确定天气是否信任变量 explorer调试优化代码时)。我无法用上面的例子重现这种情况,它只是为了说明(tmp
变量在那里,而不是仅仅优化整个事情)。如果我在 真实程序 代码中添加一个 write(*,*) "res in TIS2 =",res
in 子程序 TIS2
,结果是正确的,但这是不想要的(尤其是因为速度下降)。
我已经测试了各种编译器标志组合;即以下内容:
/debug:full /O2 /Qinit:snan /Qinit:arrays /fpe:0 /Qipo /traceback /check:uninit /arch:SSE3 /real_size:64 /fp:fast=2 /Qvec-threshold:60 /recursive
有人对此有任何提示或意见吗?
我犯了一个错误(错误),其中数组未正确填充。我在调试模式下使用编译器标志发现了这一点:/Qinit:snan
和 /Qinit:arrays
。它没有出现在发布模式中。
所以总而言之,这只是我的代码中一个相当简单的错误,没有引起注意,大多数情况下(在 99% 的情况下)一切顺利,但并非总是如此。奇怪的是它并没有被释放模式捕获。