将 Fortran 代码划分为子程序的缺点及其对速度的影响?



我有一个大的FEM代码。我已将其划分为子例程,以便可以进一步对其进行分区和更改。我的问题是:为什么速度变慢了。

  1. 当我将代码划分为子例程时,速度变慢了
  2. 当参数数量减少时,它变得更慢(在子例程中以极小的计算重新排列(。

有人可以帮我提供一些建议,当 fortran 程序被划分为子例程时,如何优化它。 特别是当该子例程在一个大循环中被调用时。

当一个大型单体代码被分成几个部分时,每个部分可能被调用数百万次,调用每个子例程或函数的开销成本通常是不可忽略的(无论使用哪种特定的编程语言(,除非编译器(链接器(可以自动内联这些函数。我怀疑编译器缺乏内联是您在代码中观察到的显着减速的原因。关于你的问题2,我无法理解。也许一个最小的工作示例代码会有所帮助,正如@VladimirF和@HighPerformanceMark所建议的那样。

确定原因可能很困难,识别此类问题的发生也是如此。

我怀疑代码的缓存可以提高性能,因此,如果相关的例程分布在整个内存中,则"可能"会降低性能。 识别与缓存相关的延迟很难实现。

如果这是一个解释,那么在链接时更改添加例程的顺序可能会显示一些变化。这种可能的方法的例子包括ddotp接近方程约简和daxpy接近方程反向替换可能是有效的。

实际上,此方法是在调用例程附近链接内部循环例程。在开发代码时,通常会出现这种情况。 您尚未表明您的链接顺序方法;基于这一假设,按字母顺序排列将是一种糟糕的方法。 FEM 代码最好描述为多体代码,因此此方法应该可用。我已经尝试了多个版本的高使用率实用程序例程,将它们放在代码中,例如用于特征子空间迭代或直接积分解的重复方程求解器,其中内部循环占求解时间的很大一部分。

尝试使用具有不同内存速度/带宽或缓存大小的处理器可以提供有趣的比较。 但是,将内存管理的缓存策略用于对阵列进行分区应该比尝试链接顺序更有效率。

另一个问题与编译器是否优化例程调用或是否内联一些琐碎的例程有关。您尚未指明您的编译选项或编译器来确定这是否可行。

我希望这个答案提供了一些可能的领域来进一步调查,同时没有为您的问题提供明确的解释。

最新更新