我有一个用Fortran编写的热工水力学代码。对于我的调试版本,我在编译时使用ifort 11.1中的-check bounds
选项。我以这种方式捕获过去的数组边界错误。不过,最近我看到解决方案很快就会爆发一个特定案例。奇特之处在于它很好地融合了代码的发布版本。果然,从我的调试makefile中删除-check bounds
标志可以解决问题。
奇怪的是,调试版本对我之前使用过的许多其他测试用例都运行良好,并且在我的代码中超出任何数组边界时没有抛出任何错误。这种行为对我来说似乎很奇怪,我不知道我的代码中是否存在某种错误或什么。什么人有任何想法可能导致这种行为?
根据要求,我用于发布和调试的标志是:
发布:-c -r8 -traceback -extend-source -override-limits -zero -unroll -O3
调试:-c -r8 -traceback -extend-source -override-limits -zero -g -O0
当然,正如我原来的问题所示,我为调试案例打开和关闭-check bounds
标志。
答案 0 :(得分:0)
我怀疑你的数值算法比Fortran代码更多。您是否确保满足所有收敛和稳定性标准?
听起来是圆整错误导致解决方案无法收敛。如果您处于安全融合的边缘,编译器优化肯定会以某种方式提示。
我使用gfortran
多于ifort
,所以我不知道-unroll选项的所有细节,但是展开循环可以改变一些舍入,即使计算看起来像是应该保持不变。此外,调试肯定会改变内存和寄存器访问的确切顺序。如果数字在处理器中以某种内部表示形式存在,则写入存储器并再次读回,值可以改变。通过仔细选择kind
可以在一定程度上缓解这种情况。就其本质而言,这将是处理器特定的而不是便携式的。
理论上,完全符合IEEE 754将使浮点运算可重现,但情况并非总是如此。如果调试实际上导致了这些问题,而不是代码中的其他错误,那么与处理器内部工作相关的其他神秘事物也可能导致它爆炸。
我会在代码中的各个关键点添加write语句来输出数据矩阵(或者你正在使用的任何数据结构)。一定要使用二进制输出。使用form='unformatted'
和access='direct'
打开。