optimization - 通过 Fortran 中的静态变量实现性能

标签 optimization recursion fortran

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

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

最佳答案

您咨询的 Fortran 程序员的情况倒退了 - 出现了对递归的限制,因为以前(假设的)编译器可以 只有为任何变量分配静态存储。性能主要是一个无关紧要的考虑因素 - 尽管我想如果您根本无法做某事,那么您就不太可能快速完成。

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

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

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

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

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

关于optimization - 通过 Fortran 中的静态变量实现性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11604658/

相关文章:

java - 一种递归求解邮票问题的算法

c - 阶乘-C (Linux)

javascript - 优化 if/else 语句

list - 方案:定义一个递归谓词 u-even?获取一个列表,如果列表中的项目数为偶数,则返回#t

java - 为什么当字长超过 4 时此代码会出现计算器错误?

makefile - Fortran 90 中将函数/子例程声明与定义分开的简洁方法

python - 编译 forpy 以在 Fortran 中调用 Python 对象

ubuntu - 未找到 lgfortran

c++ - 在 C++ 函数中使用内联优化有哪些注意事项?

optimization - Oracle12c 优化器自适应特性是否消除了对索引的需求?