Fortran中的纯子例程 - 编译器优化

14

我最近发现Fortran中纯函数和子程序的用法。根据Fortran手册所示,似乎我的大多数子程序实际上都可以定义为纯函数(因为我总是指定所有参数的意图,并且通常在大多数子程序中没有"save"、"pause"或外部I/O)。 那么我的问题是:我应该这样做吗?我想知道编译器是否优化纯函数更好,还是根本不重要,或者会让情况变得更糟。 谢谢!

2个回答

22

与编译器协作生成良好代码,您提供的信息越多,您和编译器就可以更好地合作。

无论是使用intent(in)为您不更改的任何虚拟参数进行标记,还是对常量使用parameter,或者明确将没有任何副作用的子程序标记为pure,或者在您并不真正关心循环计算顺序时使用forall,通过更加明确地表达您想要发生的情况,您将获得以下好处:

  • 编译器现在可以在编译时检测到更多错误 - 嘿,您修改了那个您说是意图“in”的参数,或者在纯函数中修改了该模块变量。
  • 下一个来到代码并不知道它要做什么的人(这个人可能是三个月后的您)可以更清楚地理解您的代码。
  • 编译器可以更积极地进行优化(如果编译器从您那里得到保证,即什么都不会改变,它可以增强优化)。

在这三个好处中,优化可能并不是最重要的;在纯函数的情况下,聪明的编译器可能可以通过静态分析看到您的子例程没有副作用。 尽管如此,您能够提供的保证越多,它就可以更好地优化您的代码而保持正确性。


1
我只想补充一点,现在推荐使用“do concurrent”而不是“forall”。 例如,参见英特尔文档的第23页。 - max
2
你可以使用 pure 关键字作为副作用检测器。只需将编写的所有函数声明为 pure。如果函数具有副作用,编译器会发出警告。如果发生这种情况,请考虑是否可以重构它以成为无副作用的函数,否则请删除 pure。这样,您将更好地理解代码并自动编写更干净的代码。 - user26756

5
据我所知,在顺序模式下这并没有什么影响。但是,如果您激活“自动并行化”选项,则编译器有时会利用PURE声明来并行化循环(多线程),其中包含对纯子例程的调用(如果子例程不是纯的,则不能冒险)。
出于同样的原因,对于希望手动设置//指令(例如OpenMP)的程序员来说,PURE声明也非常有用,因为这样的过程出现问题的风险相当有限。通常可以并行化具有对非纯子例程的调用的循环,但这需要进行深入的验证...

3
另一方面,编译器可能不会并行化纯子程序内部的任何内容,因此要小心。 - Vladimir F Героям слава

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接