此程序在MacOSX Lion和ifort(IFORT)12.1.0 20111011
上与Illegal instruction: 4
崩溃
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。我没有看到任何问题。有任何想法吗 ?展开副本并对列执行显式循环适用于两个编译器。
请注意,使用allocatable而不是指针我没有问题。
如果语句位于模块内部,则行为相同。 我在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数据的值。
我正在比较所产生的操作码,但如果有办法看到更具交际性的中间代码形式,我很乐意欣赏它。
答案 0 :(得分:5)
你的程序是正确的(虽然如果你不需要能够重新指定它,我宁愿分配给指针)。问题是ifort默认将所有阵列临时数放在堆栈上,无论它们有多大。并且它似乎需要一个临时的数组用于您在此处执行的复制操作。要解决ifort的愚蠢默认行为,始终在编译时使用-heap-arrays标志。即。
ifort -o test test.f90 -heap-arrays 1600
-heap-arrays背后的数字是应该开始使用堆的阈值。对于低于此值的尺寸,使用堆栈。我在这里选择了一个非常低的数字 - 你可以安全地使用更高的数字。理论上,堆栈阵列更快,但差异通常完全可以忽略不计。我希望英特尔能解决这个问题。每个其他编译器都具有此设置的合理默认值。
答案 1 :(得分:1)
使用“allocatable”而不是“pointer”。
real,allocatable :: a(:,:),b(:,:)
为指针指定浮点数看起来很可疑。