FORTRAN中PURE关键字的正确使用方法

26

我目前在学习Fortran,遇到了 pure 关键字,该关键字指定了没有副作用的函数/子程序。

我有一本书,作者是S Chapman,名为《Fortran 90/95》,介绍了 pure 关键字,但奇怪的是没有提供好的编码实践用例。

我在想,在过程中应该自由地使用这个关键字吗?仅在需要完全保证无副作用的程序中使用?还是在计划稍后转换为 elemental 程序的程序中使用?(因为 elemental 程序必须先是 pure。)


4
我尽可能经常使用“纯”的例程,这迫使我编写清晰的代码。然而,实际上只有少数例程可以是“纯”的...但我从未看到过任何关于速度等方面的差异。 - Alexander Vogt
3
不是Fortran 90/95,但请注意“elemental”过程可能是“impure”。 - francescalus
“只有少数”?在我看来,当编写正确时,大多数函数/子程序都将是“纯”的。据我从书中了解到,只有修改指定为“intent(in)”的变量或具有I/O组件的过程才不是“纯”的。对我来说,这似乎是少数而不是多数。 - River
很遗憾,一旦涉及到I/O操作,这就不再可能了。指针?不纯。C绑定?有些内在函数是纯的,有些则不是。甚至有些编译器版本下,某些内在函数也是不纯的...一旦一个例程不纯,所有调用它的例程也都不纯了 :( - Alexander Vogt
然而,许多小的程序可以很容易地避免指针或I/O的使用,当然这取决于写的是什么类型的程序。 您是说应该尽可能使用pure关键字吗?根据我查看的Fortran代码,这似乎不是标准使用方法。 - River
2个回答

18
在某些情况下需要使用PURE,例如,在规范表达式内部调用的过程或从FORALLDO CONCURRENT结构中调用的过程。在这些情况下需要使用PURE,以便为Fortran处理器提供过程调用顺序的灵活性,同时仍然能够从特定代码段得出相当确定的结果。
除了这些必需的情况外,是否使用PURE基本上是一个风格问题,这在某种程度上是主观的。
使用PURE也有一些代价(无法在过程内进行IO操作,不能调用不是PURE的过程)和好处(今天编写的纯过程可以在明天编写的需要纯过程的上下文中调用,因为PURE过程没有副作用,这样调用的含义可能更清晰),两者之间的权衡取决于具体情况。
标准可能给予Fortran处理器在评估表达式和函数引用内部的方法上相当大的自由度。它确实在某些方面限制了程序的功能,例如函数执行的副作用和函数参数的修改。对纯函数的要求与该自由度和这些约束一致,因此有些人采用大多数函数都是纯的风格。同样,这仍然可能取决于具体情况,在与外部API交互或C互操作性方面可能需要例外。

其他答案提供了关于使用pure的其他有用信息,应该查看更多关于如何让编译器通过乱序并行化进行优化的内容。 - River
@IanH 如果我定义了一个纯函数 f 并在表达式 x=f(a*b)+f(a*b) 中使用它,那么 f 总是被调用一次吗?似乎无法测试是否为真,因为这需要将某种副作用放入函数中。 - Raul Laasner
1
@RaulLaasner 不是的。f 可能被调用零次、一次或两次,这与 f 是否为纯函数无关。 - IanH
你可以通过创建一个长时间运行的纯函数来测试这个。根据仅有的一次这样的测试,很显然Intel Fortran不会将f(arg)+f(arg)优化为2*f(arg),无论是否有pure声明。 - agentp

11
正如chw21所建议的那样,PURE 的主要动机是让编译器更好地进行优化。特别地,对于未被声明为PURE的函数将阻止由于未知副作用而进行的并行处理。请注意,PURE子程序(与函数不同)可能具有INTENT(INOUT)参数,但仍然存在副作用限制(并且PURE过程只能调用其他PURE过程)。
在Fortran 2003之前,ELEMENTAL过程隐含为PURE。Fortran 2008添加了一个IMPURE前缀,可用于与ELEMENTAL过程一起使用以禁用该方面。

1
你有任何可用的基准测试来证明“pure”语句实际上会通过编译器进行更好的优化吗?我只是好奇,我以前尝试过在gfortranifort中使用它,但没有看到任何好处。 - Alexander Vogt
如果我在一个非纯例程上放置“PURE”关键字,编译器将会抛出一个错误。显然,编译器可以自行确定这一点,因此人们可能会期望它这样做,并因此优化相同的代码。 - agentp
这些答案帮助我更好地理解pure关键字的好处,但我仍然想了解它通常如何使用。它应该尽可能使用吗?还是更类似于位操作、多线程和其他只有在速度非常重要的情况下才普遍存在的东西? - River
1
@agentp 这假设编译器在编译对过程的引用时可以“看到”标记为PURE的过程的主体。这并不总是成立的-考虑外部或单独模块过程的分离编译的可能性。 - IanH

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