1

我多么希望我有一个最小的工作示例!

我正在使用HSL 库做一堆线性代数。我已经打开了我能想到的所有调试标志。

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

在我的工作站(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

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

我的代码在我的笔记本电脑上使用较新版本的大约 70% 的时间成功运行,但在我的工作站上ifort使用旧版本的只有大约 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 的配置?(支持证据:这是一台旧机器,可能某处出了问题?)
4

2 回答 2

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尽管这种错误是可重现且具有确定性的,但不会因未能重新初始化而出现编译器警告。

于 2015-11-03T20:36:06.577 回答
1

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

您也可以尝试 -ftrapuv(将堆栈变量初始化为不寻常的值)。如果您使用的是 Intel 15 或更高版本,您可以设置 -init=snan。这会初始化“已保存”的变量以发出 NaN 信号。

于 2015-11-03T21:44:32.810 回答