使用ifort编译的遗留代码的不稳定行为

时间:2015-11-03 20:31:42

标签: macos fortran intel-fortran intel-mkl non-deterministic

希望我有一个最低限度的工作示例!

我正在使用HSL libraries做一堆线性代数。我打开了我能想到的每一个调试标志。

在我的工作站上,我的“确定性”代码的最终结果很少有效。大多数时候,它抱怨索引错误:

在我的工作站上(Mac OS 10.7.5和ifort 12):

forrtl: severe (408): fort: (3): Subscript #1 of the array W has value 0 which is less than the lower bound of 1

Image              PC                Routine            Line        Source
libintlc.dylib     0000000103C83E04  Unknown               Unknown  Unknown
libintlc.dylib     0000000103C8259E  Unknown               Unknown  Unknown
libifcore.dylib    00000001031FBDA1  Unknown               Unknown  Unknown
libifcore.dylib    000000010316BA4E  Unknown               Unknown  Unknown
libifcore.dylib    000000010316BFB3  Unknown               Unknown  Unknown

在我的笔记本电脑上(Mac OS 10.10.5和ifort 16):

forrtl: severe (408): fort: (3): Subscript #1 of the array A has value 0 which is less than the lower bound of 1

Image              PC                Routine            Line        Source
libifcore.dylib    000000010ABDCC96  Unknown               Unknown  Unknown
Uniform2DSimplifi  00000001068851EE  _ma48bd_                 1461  ma48d.f
Uniform2DSimplifi  000000010693619C  _solve_sparse_mat         142  solve_sparse_matrix_d.f90
Uniform2DSimplifi  000000010693A7D8  _scale_and_solve_         128  scale_and_solve_sparse_matrix_d.f90
Uniform2DSimplifi  000000010685740D  _calc_simplified_         598  calc_simplified_equations_B.f90
Uniform2DSimplifi  0000000106832176  _MAIN__                   161  uniform_2D_simplified_B.f90
Uniform2DSimplifi  000000010683175E  Unknown               Unknown  Unknown

(您可能会注意到这些实际上是两个不同的错误,即使我没有更改它们之间的代码行。)

我的代码在我的笔记本电脑上使用较新版本的ifort成功运行~70%的时间,但只有约20%的时间在我的工作站上使用旧版ifort。奇怪的是,它运行的时间通常是在新的编译之后,并且在工作一次之后,它每次都会在此之后给出错误。有一次它工作,第二次没有工作,然后第三次工作。 (有时在我的笔记本电脑上,它适用于前2-3次运行,但第四次抛出错误。)

我自己的代码完全是确定性的:它正在设置解决线性代数例程。它还调用HSL例程,显然称为MKL。我认为HSL和MKL都是确定性的 - 也就是说,相同的输入产生相同的输出。 (他们不会调用RAND()或文件I / O ....)不过,我不确定。

更新

我抬头看了ma48d.f的第1461行:

     CALL MA50BD(NR,NC,NZB,JOB5,A(K+1),IRN(K+1),KEEP(IPTRD+J1),
 +               CNTL5,ICNTL5,IW(J1),IQB,NP,LA-NEWNE-KK,
 +               A(NEWNE+KK+1),IRN(NEWNE+KK+1),KEEP(IPTRL+J1),
 +               KEEP(IPTRU+J1),W,IW(M+1),INFO5,RINFO5)

在我的笔记本电脑上,它抱怨,因为k的值-1(导致错误),而它通常具有值0(导致成功)。有趣的是,我给这些例程提供了完全相同的输入,并且代码似乎是确定性的,因此它们应该执行完全相同的行...但它们不会。

我的问题:

可能导致这种不稳定行为的原因是什么?

到目前为止,我已经考虑过以下几种可能性:

  • 内部编译器错误(支持证据:较新版本的ifort似乎产生更好 - 但即使只是不同 - 结果。)
  • 与堆栈/堆相关的东西(支持证据:它第一次运行,但之后不运行。)
  • MKL(BLAS)是非确定性的(不太可能)(支持证据:追溯指向libintlc.dylib,这是一个英特尔库... 可能与MKL有关吗?)
  • HSL是非确定性的(可能是??)(支持证据:代码似乎是确定性的,尽管此代码中至少有一个错误。)
  • 关于我安装ifort或我的Mac OS X配置的事情?(支持证据:这是一台旧机器,某些地方可能出了问题?)

2 个答案:

答案 0 :(得分:3)

根据我的经验,编译器比程序员更可靠。也就是说,除非可以证明生成了错误的代码,否则我会怀疑编程错误的程序。

这种错误肯定是由于使用了未初始化的值。在使用之前,查找未特别设置为某个值的变量。

program x
integer :: i, arr(10)

do while (i < 10)
   arr (i) = 0
   i = i + 1
enddo

print *, arr
end

有时,此代码会将所有元素设置为零。其他时候它不会改变一件事。

在此逻辑中发生了直接相关但更微妙的缺少初始化错误:

program y
integer :: sum, i, arrA(10), arrB(10)
real :: ave(2)

do i = 1, 10
    arrA(i) = i * 343
    arrB(i) = i * 121
enddo

sum = 0
do i = 1, 10
    sum = sum + arrA(i)
enddo
ave(0) = sum / 10.0

do i = 1, 10
    sum = sum + arrB(i)
enddo
ave(1) = sum / 10.0

print *, 'Averages are', ave
end

如果无法重新初始化sum,则不会显示编译器警告,尽管此类错误具有可重现性和确定性。

答案 1 :(得分:1)

我无法添加评论 - 因此答案。

您还可以尝试-ftrapuv(将堆栈变量初始化为异常值)。如果您使用的是英特尔15或更高版本,则可以设置-init = snan。这会初始化“保存”变量以指示NaN。