Optimization fortran中通过静态变量实现的性能

Optimization fortran中通过静态变量实现的性能,optimization,recursion,fortran,Optimization,Recursion,Fortran,在Fortran中,如果不显式地将子例程或函数声明为递归,则不能递归调用它们。一位Fortran程序员告诉我,正因为如此,编译器可以将静态存储分配给所有局部变量,从而提高程序的速度。我对这种说法感到非常惊讶,因为现在大多数处理器都是针对堆栈的快速引用而优化的。我认为,从静态地址加载的局部变量可能会导致大量缓存未命中,因为与堆栈相反,其他子例程不使用静态地址 静态地址中的局部变量真的有加速吗?还有哪些其他优化可能会禁止递归子例程和函数?这只是因为一些大型机CPU根本没有堆栈(例如s/360)。编译

在Fortran中,如果不显式地将子例程或函数声明为
递归
,则不能递归调用它们。一位Fortran程序员告诉我,正因为如此,编译器可以将静态存储分配给所有局部变量,从而提高程序的速度。我对这种说法感到非常惊讶,因为现在大多数处理器都是针对堆栈的快速引用而优化的。我认为,从静态地址加载的局部变量可能会导致大量缓存未命中,因为与堆栈相反,其他子例程不使用静态地址


静态地址中的局部变量真的有加速吗?还有哪些其他优化可能会禁止递归子例程和函数?

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


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

您咨询的Fortran程序员有相反的东西-出现了对递归的限制,因为以前(假设的)编译器只能为任何变量分配静态存储。性能主要是一个不相关的考虑因素——尽管我猜如果你根本做不到什么,那么你就不可能很快做到

早期的Fortran(F77及以前版本)设计用于允许整个程序的内存需求在程序运行之前由Fortran处理器静态确定。这适合当时一些有限的机器架构。在这种“必须能够通过静态分析计算总内存”的限制下,很难让递归(内存需求可能因程序输入而异)这样的东西在一般情况下工作,因此语言不允许这样做

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

(具有此限制的体系结构已被F90淘汰。该标准引入了多种方式,使程序内存需求可以根据程序输入动态变化——最明显的方式是allocate语句,但现在也允许使用自动变量。)

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


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

我认为您的理解是正确的。我可以想象,在FORTRAN时代,堆栈可能会变得更慢,堆栈空间也更有限。在现代系统上没有任何优势,依我看。(免责声明:我只有24岁)。我一直认为早期版本的Fortran没有堆栈,因此递归被明确禁止。有趣的是,Fortran 90标准文档中关于
RECURSIVE
的语义写得很少。快速提问。num_images()是否像一个常量表达式?由于担心内存管理不好,我不确定是否可以将real x(num_images())作为局部变量包含在大量使用的过程中。@RaulLaasner请另外问一个问题-该主题与此问题无关。