6

该程序Illegal instruction: 4在 MacOSX Lion 和 ifort (IFORT) 12.1.0 20111011 上崩溃

program foo
      real, pointer :: a(:,:), b(:,:)
      allocate(a(5400, 5400))
      allocate(b(5400, 3600))
      a=1.0
      b(:, 1:3600) = a(:, 1:3600)

      print *, a
      print *, b

      deallocate(a)
      deallocate(b)

end program 

相同的程序适用于 gfortran。我看不出有什么问题。有任何想法吗 ?展开副本并在列上执行显式循环在两个编译器中都有效。

请注意,使用可分配而不是指针我没有问题。

如果语句在模块内或不在模块内,行为是相同的。我在 ifort (IFORT) 12.1.3 20120130 上确认了相同的行为。

显然,Linux 和 ifort 12.1.5 没有问题

我尝试使用以下链接选项增加堆栈大小

ifort -Wl,-stack_size,0x40000000,-stack_addr,0xf0000000 test.f90

但我仍然得到同样的错误。增加 ulimit -s 来解决同样的问题。

编辑2:我做了更多的调试,显然问题发生在数组拼接操作时

      b(:, 1:3600) = a(:, 1:3600)

涉及可疑接近 16 M 数据的值。

我正在比较生成的操作码,但如果有一种方法可以查看更具交流性的中间代码形式,我将不胜感激。

4

2 回答 2

6

您的程序是正确的(尽管如果您不需要能够重新指向它,我更愿意分配给指针)。问题是 ifort 默认情况下将所有临时数组放在堆栈上,无论它们有多大。您在这里执行的复制操作似乎需要一个临时数组。要解决 ifort 愚蠢的默认行为,请在编译时始终使用 -heap-arrays 标志。IE

ifort -o test test.f90 -heap-arrays 1600

-heap-arrays 后面的数字是它应该开始使用堆的阈值。对于低于此的大小,使用堆栈。我在这里选择了一个相当低的数字——你可能可以安全地使用更高的数字。理论上堆栈数组更快,但差异通常完全可以忽略不计。我希望英特尔能解决这种行为。每个其他编译器对此设置都有合理的默认值。

于 2012-10-29T01:39:04.483 回答
1

使用“可分配”而不是“指针”。

真实的,可分配的 :: a(:,:), b(:,:)

将浮点数分配给指针对我来说看起来很可疑。

于 2012-10-28T23:50:29.697 回答