在现代时代学习FORTRAN

时间:2008-08-28 04:36:26

标签: fortran

我最近开始维护大量科学计算密集型FORTRAN代码。尽管google& go,我仍然难以掌握四十年前语言的所有细微差别。两本入门级书籍。代码充斥着“提升性能”。有没有人对 de - 优化FORTRAN到CS 101级别有任何指导或实用建议?有谁知道FORTRAN代码优化是如何运作的?是否有任何典型的FORTRAN'陷阱'可能不会发生在Java / C ++ / .NET引发的开发人员接管FORTRAN 77/90代码库?

10 个答案:

答案 0 :(得分:81)

你必须对程序员当天必须做的事情有一种“感觉”。我工作的绝大部分代码都比我年长,并且在我父母上高中时使用的机器是“新的”。

我处理的常见FORTRAN主义,可读性受损:

  • Common blocks
  • 隐含变量
  • 两个或三个带有共享CONTINUE语句的DO循环
  • GOTO代替DO循环
  • 算术IF语句
  • 计算GOTO的
  • 等效REAL / INTEGER /其他常见块

解决这些问题的策略包括:

  1. 获得Spag / plusFORT,物有所值,它自动解决了很多问题并且无错误(tm)
  2. 如果可能的话,移动到Fortran 90,如果没有移动到自由格式的Fortran 77
  3. 为每个子例程添加IMPLICIT NONE,然后修复每个编译错误,耗时但最终必要,某些程序可以自动为您执行此操作(或者您可以编写脚本)
  4. 将所有COMMON块移动到MODULEs,低悬的果实,值得它
  5. 将算术IF语句转换为IF..ELSEIF..ELSE块
  6. 将计算GOTO转换为SELECT CASE块
  7. 将所有DO循环转换为较新的F90语法

    myloop: do ii = 1, nloops
        ! do something
    enddo myloop
    
  8. 将等价的公共块成员转换为模块中分配的ALLOCATABLE内存,或者如果Hollerith存储在REAL中则转换为真正的字符例程

  9. 如果您对如何完成某些可读性任务有更具体的问题,我可以给出建议。我有一个几十万行Fortran的代码库,这个代码库是在40年的时间里写的,我在某种程度上负责,所以我可能遇到过你可能遇到的任何“问题”。

答案 1 :(得分:30)

Legacy Fortran Soapbox

我帮助维护/改进了传统的Fortran代码库已有一段时间了,并且大多数情况下认为 sixlettervariables 是有钱的。但是,这个建议往往是技术性的;锄头更加强硬,正在实施“良好做法”。

  • 建立必要的编码风格和编码指南。
  • 要求对代码库中提交的任何内容进行代码审查(不仅仅是编码器!)。 (版本控制应与此过程相关联。)
  • 开始构建和运行单元测试;同上基准或回归测试。

这些可能听起来像是显而易见的事情,但冒着过度概括的风险,我声称大多数Fortran代码商店都有一种根深蒂固的文化,一些在“软件工程”这个术语出现之前就开始了,并且随着时间的推移主宰是“现在就完成它”。 (无论如何,这并不是Fortran商店独有的。)

拥抱陷阱

但是如何处理现有的,粗糙的旧遗留代码库呢?我同意Joel Spolsky的重写,don't。但是,在我看来, sixlettervariables 确实指出了允许的例外:使用软件工具转换到更好的Fortran结构。代码分析器可以捕获/纠正很多({{ 3}})和代码重写器(FORCHECK)。如果你必须手工完成,请确保你有一个紧迫的理由。 (我希望我手边有一个关于修复软件错误所带来的软件错误数量的参考,这是令人羞愧的。我认为有一些这样的统计数据在plusFORT。)

赢得Fortran陷阱游戏的最佳进攻可能是拥有最好的防守:很好地了解语言。为了达到这个目的,我推荐......书!

Fortran死树图书馆

多年来,我作为“QA唠叨”获得了微不足道的成功,但我发现教育确实有效,有时无意中,而且最有影响力的事情之一是有人手边的参考书。我喜欢并强烈推荐

Expert C Programming ,作者:Stephen J. Chapman

这本书对Fortran 77来说甚至是好的,因为它专门识别了不应该使用的结构,并提供了更好的选择。然而,它实际上是一本教科书,当你真的想知道Fortran 95的细节时,它可能会用完,这就是我推荐的原因

迈克尔·梅特卡夫(Michael Metcalf)饰演的 Fortran 90/95 for Scientists and Engineers 约翰·K·里德

作为Fortran 95的首选参考资料。请注意,这不是最清晰的写作,但当您真正想要充分利用新的Fortran 95功能时,面纱将会升级。

关注从Fortran 77到Fortran 90的问题,我很喜欢

Jim Kerrigan

Fortran 90/95 Explained

但这本书已经绝版了。 (我只是不明白O'Reilly对Migrating to Fortran 90的使用,为什么不是每本绝版书都可用?)

最后,关于精彩,精彩经典的继承人Safari,我提名

Software Tools ,作者:Michael Kupferschmid

本书不仅展示了“仅”Fortran 77可以做些什么,而且还讨论了一些更微妙的问题(例如,应该或不应该使用EXTERNAL声明)。这本书并不完全覆盖与“软件工具”相同的空间,但它们是我将标记为“有趣”的三本Fortran编程书籍中的两本....(Classical FORTRAN)。

其他适用于几乎每个Fortran编译器的建议

  • 有一个编译器选项可以强制执行IMPLICIT NONE行为,您可以使用它来识别问题例程,而无需先使用IMPLICIT NONE声明对其进行修改。在第一次构建炸弹之后,由于插入到遗留例程中的IMPLICIT NONE命令,这条建议似乎没有意义。 (什么?你的代码审查没有抓到这个?; - )
  • 有一个用于数组边界检查的编译器选项,在调试Fortran 77代码时非常有用。
  • Fortran 90编译器应该能够编译几乎所有Fortran 77代码甚至更旧的Fortran代码。打开Fortran 90编译器上的报告选项,通过它运行遗留代码,您将在语法检查方面有一个不错的开端。一些商业Fortran 77编译器实际上是以Fortran 77模式运行的Fortran 90编译器,因此对于您拥有的任何构建脚本而言,这可能是相对简单的选项。

答案 2 :(得分:21)

原始问题中有一些我会提醒的。你说代码充斥着“性能提升”。由于Fortran问题通常具有科学性和数学性,因此不要假设这些性能技巧可以改进编译。这可能与语言无关。在Fortran中,解决方案很少涉及代码本身的效率,而是解决最终问题的基础数学。这些技巧可能会使编译速度变慢,甚至可能使逻辑变得混乱,但目的是使解决方案更快。除非你确切知道它在做什么以及为什么这样做,否则不管它。

即使是简单的重构,比如改变看似愚蠢的变量名也可能是一个很大的陷阱。从Maxwell时代开始,在给定的科学领域中,历史上标准的数学方程式将使用特定的简写。因此,在电磁学中看到一个名为B(:)的数组,可以告诉所有Emag工程师究竟要解决的问题。改变你的危险。道德,在重命名之前,先了解科学的标准命名法。

答案 3 :(得分:7)

作为一名有FORTRAN经验的人(虽然我认真使用它已经有一段时间了,虽然它已经有一段时间了)和C / C ++,需要注意的项目是数组。 FORTRAN数组的索引为1而不是0,就像在C / C ++ / Java中一样。而且,存储器布置是相反的。因此,递增第一个索引可以为您提供顺序的内存位置。

我的妻子仍然定期使用FORTRAN并且有一些她需要使用的C ++代码,因为我即将开始帮助她。当她转换过程中出现问题时,我会试着指出它们。也许他们会帮忙。

答案 4 :(得分:5)

您能否解释一下维护代码时需要做些什么?你真的要修改代码吗?如果您可以通过仅修改该代码的接口而不是代码本身来逃避,那将是最好的。

处理大型科学代码(不仅仅是FORTRAN)时的固有问题是基础数学和实施都很复杂。几乎默认情况下,实现必须包含代码优化,以便在合理的时间范围内运行。这个领域的许多代码都是由他们所在领域的专家而不是软件开发专家的科学家/工程师创建的。让我们说“易于理解”不是他们的首要任务(我是其中之一,仍然学习成为更好的软件开发人员)。

由于问题的性质,我不认为一般的问题和答案足以提供帮助。我建议你发布一系列附带代码片段的具体问题。也许从让你最头痛的那个开始?

答案 5 :(得分:5)

我从1967年以来的'66版本开始使用Fortran(在具有32k字内存的IBM 7090上)。然后我使用PL / 1一段时间,但后来又回到了Fortran 95,因为它非常适合我们的矩阵/复数问题。我想补充一点考虑因素,旧代码的大部分复杂结构仅仅是由于可用内存量很小,这就像通过计算或分配GOTO重用几行代码一样。另一个问题是通过为每个重复的子表达式定义辅助变量来进行优化 - 编译器根本没有为此进行优化。另外,不允许写DO i=1,n+1;你必须写n1=n+1; DO i=1,n1。结果,旧代码被多余的变量所淹没。当我在Fortran 95中重写代码时,只有10%的变量存活了下来。如果你想让代码更清晰,我强烈建议你寻找易于消除的变量。

我可能会提到的另一件事是,多年来复杂的算术和多维数组的效率非常低。这就是为什么你经常发现重写代码只使用实数变量进行复杂计算,以及用单个线性索引处理的矩阵。

答案 6 :(得分:4)

嗯,从某种意义上说,你很幸运,因为Fortran对微妙的控制流构造或继承等方面没有多少帮助。另一方面,它有一些真正令人惊奇的陷阱,比如算术计算的分支到数字标签的东西,隐式类型的变量,不需要声明,缺少真正的关键字。

我不知道“提升绩效”。我猜他们中的大多数都可能是无效的,因为几十年的编译器技术已经使大多数暗示变得不必要了。不幸的是,除非你打算进行大规模的重写,否则你可能不得不按原样保留事物。

无论如何,核心科学计算代码应该是相当可读的。使用中缀算法的任何编程语言都可以很好地准备读取Fortran的算术和赋值代码。

答案 7 :(得分:3)

我喜欢FORTRAN,我曾经教过它并编写代码。只想把它丢进去。多年来都没碰过它 我从COBOL开始,当我搬到FORTRAN时,我觉得我被释放了。一切都是相对的,是吗? 我是第二个上面所说的 - 认识到这是一种程序性的语言 - 没有子语言 - 所以请按照你的看法进行操作。
可能会让你开始感到沮丧。

答案 8 :(得分:3)

我开始使用穿孔卡上的Fortran IV(WATFIV),我早期的工作年份是VS FORTRAN v1(IBM,Fortran 77级别)。这个帖子中有很多好建议。

我想补充一点,你必须区分为了让野兽完全运行所做的事情,而不是“优化”代码的事情,而不是更易读和可维护的事情。我记得在尝试让DOE仿真代码在具有虚拟内存的IBM上运行时处理VAX覆盖(必须将它们删除,整个事物变成一个地址空间)。

我一定会首先仔细地将FORTRAN IV控制结构重组为至少FORTRAN 77级别,并进行适当的缩进和评论。尝试摆脱原始控制结构,如ASSIGN和COMPUTED GOTO以及算术IF,当然,尽可能多的GOTO(使用IF-THEN-ELSE-ENDIF)。绝对在每个例程中都使用IMPLICIT NONE,强制你正确声明所有变量(你不会相信我在其他人的代码中捕获了多少错误 - 变量名称中的拼写错误)。注意“过早优化”,你最好让编译器单独处理。

如果此代码要继续生存并且可维护,那么您应该为自己和您的继任者付出代价,使其易于理解。 当你改变代码时,确定你在做什么! FORTRAN有许多特殊的结构,可以轻易地绊倒来自编程世界的C方面的人。请记住,FORTRAN可以追溯到50年代中后期,当时没有语言和编译器设计的科学,只是 ad hoc 一起黑客攻击(对不起,B博士!)

答案 9 :(得分:1)

这是另一个不时咬我的人。当您使用FORTRAN代码时,请确保跳过所有六个初始列。每隔一段时间,我只会得到代码缩进五个空格,没有任何作用。乍一看,一切似乎都没问题,然后我终于意识到所有的线都是从第6列开始而不是第7列。

对于不熟悉FORTRAN的人来说,前5列用于行号(=标签),第6列用于延续字符,以防你有超过80个字符的行(只需在这里放一些东西,编译器就知道了这一行实际上是前一行的一部分,而代码总是从第7列开始。