提问人:Kristian HM 提问时间:10/16/2023 最后编辑:Ian BushKristian HM 更新时间:10/17/2023 访问量:104
带有优化标志的 gfortran 如何解释嵌套的隐含 do 循环?
How does gfortran with optimization flags interpret nested implied do loops?
问:
我对 gfortran 有一个问题,我试图在一般层面上理解它,以避免将来再次遇到它。具体来说,我试图了解嵌套隐含的 do 循环在读取数据时的行为,以及 gfortran 优化标志如何影响它。
作为我正在修改的更大程序的一部分,我正在尝试读取一些数据并将它们存储在一个矩阵中,在我的特定情况下,这是一个给定分配时使用的变量维度的向量。下面给出了显示该问题的最小工作示例。sttheight
问题与从输入文件读取变量时使用的嵌套隐含 do 循环构造有关。当使用 编译程序并运行它时,它会生成所需的输出,即打印 8 个浮点变量:gfortran Read_fct.f90 -o Read
Input.txt
0.00000000 14370.0117 14370.0117 14370.0117 14370.0117 14370.0117 14370.0117 14370.0117
我正在使用:“GNU Fortran (GCC) 12.2.0 20220819 (HPE)”
但是,如果我用 编译它,输出是“0.00000000”打印 8 次。使用或更高优化标志(-O3 到 -O5)可以获得相同的结果。该程序不会引发任何错误或警告,这意味着该问题很容易被忽略。通过揭示错误的来源进行进一步调试:gfortran -O2 Read_fct.f90 -o Read
-O1
gfortran -O2 -g -fcheck=bounds Read_fct.f90 -o Read
At line 18 of file Read_fct.f90
Fortran runtime error: Index '0' of dimension 1 of array 'noheight' below lower bound of 1
也就是说,程序似乎在将值分配给 之前尝试初始化 。因此,对于这种特定情况,我可以轻松解决问题,但这会使我的代码不那么通用,可能会引入其他问题。此外,在花了几个小时试图找到问题之后,我想了解潜在的问题,以减少再次遇到此问题的机会。noheight(jpuff)
jpuff
使用 -O3 编译时同时包含:“Cray Fortran:版本 16.0.1”和“ifort (IFORT) 2021.7.1 20221019”会导致打印正确浮点值的预期行为。
简而言之:1)我的代码有问题吗,2)这是gfortran优化标志的预期行为还是3)这是gfortran中的错误吗?后者在我看来不太可能,但我想没有什么是不可能的。
我希望有人能够在这里为我指出正确的方向。
MWE:
Read_fct.f90:
program Read_fct
implicit none
integer :: ntraj, mpuff
integer :: jheight, jt, jpuff
real,allocatable :: sttheight(:,:,:)
integer, dimension(:), allocatable :: noheight
open(1, file='Input.txt')
ntraj = 8
mpuff = 1
allocate(noheight(mpuff))
noheight(1) = 1
allocate(sttheight(noheight(1), ntraj, mpuff))
read (1,*) (((sttheight(jheight,jt,jpuff),jheight=1,noheight(jpuff)),jt=1,ntraj),jpuff=1,mpuff)
write(*,*) sttheight
close(1)
end program
文件“Input.txt”只有一行包含我试图读取的数据:
0.00000000,14370.01149861,14370.01149861,14370.01149861,14370.01149861,14370.01149861,14370.01149861,14370.01149861 ! sttheight
编辑:包含并相应删除implicit none
答:
程序可以大大简化,这是我想出的MRE
program implied_do_bug
implicit none
integer :: i,j,k
real :: arr(1,1,1)
integer :: ni(1)
ni(1) = 1
arr = 1
write(*,*) (((arr(i,j,k), i=1,ni(k)), j=1,1), k=1,1)
end program
我已将其作为可能的编译器错误提交到 GCC Bugzilla 中,该错误是作为错误111837的回归。
根据回复,解决方法是通过 禁用前端优化。-fno-frontend-optimize
评论
implicit none
noheight