通过fortran中的静态变量来表现

时间:2012-07-22 22:59:25

标签: optimization recursion fortran

在Fortran中,如果没有明确地将它们声明为recursive,则无法递归调用子例程或函数。 Fortran程序员告诉我,由于这个原因,编译器可以为所有局部变量分配静态存储,从而提高程序的速度。我对此声明感到非常惊讶,因为今天的大多数处理器都经过优化,可快速引用堆栈。我认为,从静态地址加载的局部变量可能会导致大量缓存未命中,因为静态地址不会被其他子例程用于堆栈。

静态地址的局部变量真的有加速吗?什么其他优化可能不允许递归子程序和函数?

2 个答案:

答案 0 :(得分:7)

你咨询过的Fortran程序员反过来了 - 对递归的限制产生了,因为之前(假设的)编译器只能 为任何变量分配静态存储。性能主要是一个无关紧要的考虑因素 - 虽然我想如果你根本不能做某些事情,那么你不太可能快速做到。

早期Fortran(F77和之前版本)旨在允许整个程序的内存要求由程序运行之前的fortran处理器静态确定。这适合当时的一些有限的机器架构。很难得到像递归(内存要求可能因程序输入而异)的情况,以便在一般情况下使用“必须能够通过静态分析计算总内存”限制 - 因此语言不允许它。

特定处理器如何实际实现该语言取决于它们 - 如果他们想要使用基于堆栈的stoge来处理局部变量,那么他们就可以了。在标准边界之外编写的Fortran程序员可能在历史上习惯于期望从使用静态存储获得的行为(非保存变量在调用之间记住它们的值等),但对底层实现敏感的程序不是标准符合。

(具有此限制的架构已被F90淘汰。该标准引入了程序内存需求可根据程序输入动态变化的几种方式 - 显而易见的是分配语句,但现在也允许使用自动变量。)

对于小的未保存的局部变量(标量),很可能(假设合理的硬件)相关存储更快地存在于堆栈中。

区分能够递归的程序和那些仍然具有一些实际价值的程序 - 如果局部变量很大(数组或冗长的字符),那么它可能根本不适合堆栈。为避免这种情况 - 如果过程未标记为递归且阵列具有已知大小,则fortran处理器可以使用静态存储。这避免了与动态内存分配相关的任何开销,这可能相当昂贵。如果过程标记为递归(并且局部变量未保存)或者在编译时未知数组的大小,则fortran处理器别无选择 - 它要么希望数据适合堆栈,要么使用动态内存分配

答案 1 :(得分:2)

这只是因为某些大型机cpus根本没有堆栈(例如s / 360)。编译器必须生成特殊代码来模拟它。因此,非递归的函数包含更简单/更少的代码。我不知道今天是否仍然有用。

引用特定地址而不是堆栈上的位置并不意味着更多的缓存未命中。相反,静态地址可以简化优化器的工作,因为它可以根据它们的用法将它们放在内存中。