编写健壮的“现代”Fortran代码
在一些科学环境中,由于大多数开发人员只知道习惯用法,并且有很多遗留代码和相关经验,所以经常不能没有FORTRAN。 坦率地说, 高性能编程没有太多其他的跨平台选项(C ++可以完成这个任务,但是语法,零开始数组和指针与某些人不兼容)。
因此,我们假设一个新的项目必须使用Fortran 90,但是我想用最新的编译器(Intel ifort,还包括Sun / HP / IBM编译器)来兼容最新的软件架构,
所以我正在考虑强加一些广为人知的常识,但在我的环境中还不是一个标准:
- 全局variables被禁止,没有gotos,没有跳转标签,
implicit none
,等等。 - “面向对象的编程”(具有数据types和相关子程序的模块)
- 模块化/可重用的function,有据可查的可重用的库
- 断言/先决条件/不变式(使用预处理器语句实现)
- 所有(大多数)子程序和“对象”的unit testing
- 一个强烈的“debugging模式”(
#ifdef DEBUG
)与更多的检查和所有可能的英特尔编译器检查可能(数组边界,子程序接口等) - 统一并强制执行易读的编码风格,使用代码处理工具助手。
所有的目标都是要有值得信赖,可维护和模块化的代码。 而在大量的遗留代码中,可重用性并不是一个重要的目标。
我search了关于面向对象的Fortran,合同编程(断言/前置条件/等等)的参考资料,并且find了没有大型项目参与的人员所做的丑陋和过时的文档,语法和论文以及死了的项目。
任何有关此主题的良好url,build议,参考文献/书籍?
我的5美分。
Fortran Wiki是一个很好的起点。 它有使用现代Fortran编程的不同方面的文章。 unit testing,debugging,generics编程等。另外,Fortran 2003标准的编译器支持也非常有趣。 (正如Blklight已经提到的那样,某些2003特性在编译器中是不可用的,这是比较不同编译器的好地方。)
我是一个C ++的人,但我坚持一些F90项目。
我build议阅读本课程: 现代Fortran简介 。 MSB提到着名的“Fortran 95/2003 Explained”,但这本书足够大,充满了细节。 上面提到的课程恰恰相反是一个很好的开始。 还可以看看利物浦大学的互动式Fortran 90编程课程 。
Fortran 90个可能让你惊讶的程序错误 。 这个页面标题自己说话。 =)
嗯…我也在我的书签有一些链接到PSTI研究讲座系列“科学计算与FORTRAN 95” 。 试一试。
JF Sebastian提到了F2Py并给出了教Python的build议。 我赞成他的意见。 Python不是我最喜欢的语言。 但是教它它足够有用。 除了已经提到的预处理程序(其中许多是用Python编写的)和F2Py,并没有传递SCons–现代的软件构build工具。
PS上周我在lulu.com买了一本电子书。 Drew McCormack 在Fortran的科学软件开发 。 我希望这是一个很好的阅读,但突然没有时间。 作者是Forpedo(Fortran Wiki中提到的Fortran特定预处理程序之一)的开发人员,以及有关Objective-C和Python编程的许多书籍和教程的作者。
我build议OP放弃Fortran在高性能科学计算中遭遇的一些令人讨厌的态度,并热情地投入到Fortran中。 如果OP保留那种不屑一顾的心态,那么他/她的整个Fortran编程生涯将是一场艰苦的斗争。 而且,对于Fortran来说,没有什么可以做到的,你不能用C ++来做,所以如果你真的不想这么做,那么为什么呢?
OP的子弹列表中没有任何内容,我们很多在过去的30年中一直与Fortran一起工作的人从来没有这样做(因为Fortran 90编译器的广泛使用,但是之前也有一些)。 是的,有计算科学家和懂得指针的科学软件工程师知道很多(被误导的)人从0开始计数,并且全局variables是一个有害的东西。
像@MSB一样,我推荐Metcalf 等人的书作为关于现代Fortran的function和特性的信息来源。 和@MSB一样,我对使用C或C ++来包装那些既有Fortran等价物也有更好的方法的库进行了一些研究。 2003标准与Intel Fortran中实现的C特性的互操作性使得直接调用C库变得比以往更容易。
我会采取行动的问题,模块化的代码是一个目标本身。 我认为,目标是正确的,可validation的,可validation的,可靠的,可靠的代码。 模块化是支持实现这些目标的一种方式,但这是一种策略,而不是一个终点。 如果我认为我们可以在没有模块性的情况下编写包含10 ^ 6行代码的良好(在前述的意义上)的程序,我就不会为模块化而烦恼。
好的,现在给OP提出一些具体的build议来增加OP的意愿:
- 在variables声明中使用KIND来强化你所需要的精度; 请不要将其留给编译器选项或猜测此编译器可能在该处理器上执行的操作;
- 尽可能使用数组操作而不是显式循环; 这有助于使代码更安全 – 有时会牺牲性能,但是您需要根据具体情况进行检查;
- 写PURE函数;
- 不要依赖预处理器或其他非Fortran方法来编写正确性(等等),在Fortran中编写断言和前提条件(等等); 预处理器(等)只要写得很好的Fortran程序就不能存活,并且将成为现在和将来可移植性的主要障碍;
- 如果您有权访问英特尔Fortran,则可以访问英特尔MKL(和IPP)并使用这些库,而不必编写自己的代码;
- 计划解决OpenMP和MPI的并行化,他们都非常适合Fortran; 哦,并计划尽快平行,这比串行编程更有趣。
- 这套Fortran编码标准是一个好的开始,但可能不过是这样; Code Complete的第一版有更多关于Fortran(77)编程的内容,但是其中的大部分build议都可以应用于你写的任何语言。
最后,最近,我认为Fortran程序和程序员比函数式编程的思想更好地得到了来自面向对象编程思想的信息。
Fortran 90/95/2003的devise使得人们可以编写模块化代码,如果需要的话,可以通过添加模块,私有/公共,用户定义的types等来实现。Fortran 2003引入了更多面向对象的特性。 当Fortran 90“分配”以更安全的方式直接dynamic分配Fortranarrays时,连接到C以添加malloc是没有意义的。 将程序(函数和子程序)放在模块中,然后“使用”模块将导致接口被检查。 可以使用编译器的许多debugging/检查选项,例如下标边界检查。
一本关于这些和其他function的优秀书籍:Metcalf,Reid和Cohen的“Fortran 95/2003解释”。 学习现代Fortran的最佳特性绝对是一个好主意,而不是继续编写FORTRAN 77 – 必要时编写编码标准/指南。
在过去的几年中,我和一个同事在现代Fortran中开发了一个相当庞大的计算库,并提供了许多你提到的function – 面向对象,模块化/可重用,一致的代码风格等等(我们还没有做的很好尽pipe需要进行unit testing),然后将所有这些包装在一起,以提供C ++,Python等接口。 其他人在这里指出了我所推荐的所有书籍和链接(还有更多),所以我不再重复。 我发布的原因只是说,用Fortran来做这些事情是可能的,创造一些伟大的东西,所以坚持下去。
我还要指出,在所有主要的编译器中都实现了这么多的Fortran 2003标准之后,你是多么幸运。 你会发现很多这些function(比如过程指针)非常有用。
我很急,如果我以检查点的forms作出这个答案,而不是合理的句子,请原谅我。
- 尝试遵守这个标准 (Fortran是一种标准化的语言,通过遵守标准的语言特性,并避免供应商特定的扩展,你将有一个可移植的平台之间的程序,你可以确信编译器不会有问题)。 我不知道我在哪里下载了我的副本,但是我非常肯定你可以下载最新的草稿(当心; Fortran 2008或2003的许多function在这个问题上仍然没有在currect编译器中实现,尽pipe很多function几乎都在那里现在…克雷是一个)从J3的页面
- 对于所有关于上述问题,我衷心推荐comp.lang.fortran usenet组 – 不仅它有一些非常有知识的人(例如,理查德·缅因先生…可能会愿意回答任何标准的合规性问题可能会问很详细的问题,如果问得好的话也是如此),但也有人曾经在大规模问题上工作过,而且肯定知道并愿意就你的主题给出build议
- 除了已经提到的所有内容之外(Metcalf,Reid和Cohen的书也有我的推荐,也是由Maine和其他人撰写的“Fortran 2003手册”),试着找一份Stephen J. Chapman的“Fortran 95 / 2003年为科学家和工程师“ …在某些主题上有点过于自信的立场,但总体来说还是一本很好的书,有许多”良好的编程实践“提到)
- 另外,不知道你是否遇到了这个“通过Fortran 90/95进行面向对象编程”
对你的文字有些评论:
(这可能似乎都是“明显的”现代编程假设,但在传统的Fortran世界中,其中大部分是典型的程序员工作stream程中的重大变化)
即使在现代的Fortran世界里,这些假设也有一些是值得怀疑的…记住,Fortran程序员不是程序员(我正在以简明的forms重复这个;我已经在这个论坛上多次写过),但是工程师,科学家等等。 对他们来说(我们?)代码不是一个目标,而只是一个工具…对专业程序员来说代码就是一切; 他们没有任何“超越”……因此,他们非常珍惜。 对于我们的工程师来说,这只是获得我们想要的结果的一种手段…考虑到这一点,虽然稍后好的编程实践付出,但没有必要坚持在没有明显需要的地方。
所有的目标都是要有值得信赖,可维护和模块化的代码。 而在典型的Fortran中,模块化通常不是主要目标,只有当原始开发人员非常聪明时,代码才是可信的,从那时起代码就不会改变! (我在这里有点开玩笑,但不多)
有人曾经说过,你不会相信它是多么的真实:
“没有什么比临时解决办法更具永久性了”。
任何良好的url,build议,参考文件/有关这方面的书籍?
鉴于以上几点。
另外,在写这个答案的时候,我看到了高性能。 马克贴出了一个非常好的答案,我大多同意……它进一步详细介绍了标准坚持。
此外,我的build议是肯定会在comp.lang.fortran上发布这个问题…我收集你可以得到更多的质量答案在那里,然后在这里(我相信有不到20个左右的Fortran程序员整个stackoverflow)。
有一些欧盟委员会自由发布的一套编码准则; 他们会作为这个答案的一部分非常有用,但不幸的是,我找不到他们在我的快速谷歌search,并没有时间去广泛地看。 尝试search主题…也许你会有更好的运气。
我刚刚在F2003上发现了这个由两部分组成的面向对象编程系列。 这里有很多很棒的东西:
第1部分: http : //www.pgroup.com/lit/articles/insider/v3n1a3.htm
第2部分: http : //www.pgroup.com/lit/articles/insider/v3n2a2.htm
它有很好的例子,很清楚地解释了一切。
如果您想在OO中查看大型的Fortran程序,请访问www.mohid.com。 这是GPL。 我同意写现代的Fortran面向对象是不够的,这是强制性的function编程概念。 我正在做一些研究,我相信主要缺失的function是lambda(匿名)函数。 另一方面,我认为要进行并行化,最好使用MPIpath,而不是OpenMP。