Fortran 暗示做不起作用

Tha*_*les 5 fortran

我正在使用 Fortran90,但我对它不太熟悉。

在代码的某些地方,我想在 t0 和 tf 之间创建一个由 n 个线性等距点组成的数组,所以我尝试了这个:

t = t0+(/(i,i=0,n-1)/)*(tf-t0)/(n-1)
Run Code Online (Sandbox Code Playgroud)

这与以下内容相同:

do while(i<=n)
    t(i) = i-1
    i=i+1
end do

t = t*(tf-t0)/(n-1)+t0
Run Code Online (Sandbox Code Playgroud)

但是,如果 n 太大(n=2000001 或更大),则第一个选项不起作用。我收到错误:

forrtl: 严重 (170): 程序异常 - 堆栈溢出

这是为什么?我该怎么做才能使隐含的 do 循环适用于 n 大?

Ian*_*anH 5

一些 Fortran 处理器使用硬件堆栈来存储在表达式求值期间创建的临时值。当表达式涉及大型对象时——例如大型数组——临时对象所需的存储空间可能会超过硬件堆栈可用的总存储空间,并且堆栈溢出。

在第一种情况下,您的 Fortran 处理器可能正在创建一个大的临时文件来保存数组构造函数的结果。

不同的处理器在无需临时变量的情况下评估表达式的能力不同 - 例如,您可能会发现某些处理器在您的第二个示例中也存在堆栈溢出问题 - 分配给的变量 t 也在右侧表达式中引用对于某些 Fortran 处理器来说,可能需要对整个右侧进行临时评估。

您的选择是(也许组合):

  • 使用操作系统或编译器开关为硬件堆栈留出更多存储空间。

  • 使用编译器开关或类似的东西来指导处理器在堆上而不是堆栈上创建临时文件。

  • 以不同的方式重述整个操作,以便编译器不再创建临时文件(正如您已经探索过的)。这可能包括在 do 循环中将操作重新转换为逐个元素的操作,而不是直接在数组上使用操作。

这些方法是特定于平台的。根据错误消息,我猜您在 Windows 上使用 Intel Fortran(或祖先) - 如果是这样,请参阅/heap-arrays编译器选项和 Windows 链接器选项/stack。如果您使用的是 linux,请查看该ulimit命令。