为什么边界检查会改变程序的行为?

时间:2013-02-05 21:03:09

标签: fortran intel-fortran

我有一个用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标志。

1 个答案:

答案 0 :(得分:0)

我怀疑你的数值算法比Fortran代码更多。您是否确保满足所有收敛和稳定性标准?

听起来是圆整错误导致解决方案无法收敛。如果您处于安全融合的边缘,编译器优化肯定会以某种方式提示。

我使用gfortran多于ifort,所以我不知道-unroll选项的所有细节,但是展开循环可以改变一些舍入,即使计算看起来像是应该保持不变。此外,调试肯定会改变内存和寄存器访问的确切顺序。如果数字在处理器中以某种内部表示形式存在,则写入存储器并再次读回,值可以改变。通过仔细选择kind可以在一定程度上缓解这种情况。就其本质而言,这将是处理器特定的而不是便携式的。

理论上,完全符合IEEE 754将使浮点运算可重现,但情况并非总是如此。如果调试实际上导致了这些问题,而不是代码中的其他错误,那么与处理器内部工作相关的其他神秘事物也可能导致它爆炸。

我会在代码中的各个关键点添加write语句来输出数据矩阵(或者你正在使用的任何数据结构)。一定要使用二进制输出。使用form='unformatted'access='direct'打开。