C ++与Fortran for HPC


56

在我的计算科学博士学位程序中,我们几乎只在C ++和Fortran中工作。似乎有些教授更喜欢另一种。我想知道哪个在某些情况下是“更好”的,还是一个在另一个方面要比另一个更好。


12
我认为,混合使用高级语言和低级语言比单独使用这两种语言要好。例如,我使用Python + C ++。
Faheem Mitha

2
这个问题的答案几乎是主观的,因此我不确定这个问题是否合适。
杰夫,

Answers:


61

通常,选择取决于(1)您要解决的问题,(2)您的技能以及(3)与您一起工作的人(除非这是一个单独的项目)。我暂时将(3)放在一边,因为这取决于每个人的具体情况。

问题依存关系:Fortran在数组处理方面表现出色。如果您的问题可以用简单的数据结构(特别是数组)来描述,则Fortran可以很好地适应。即使在非显而易见的情况下(例如代表图形),Fortran程序员最终还是使用数组。C ++更适合复杂和高度动态的数据结构。

技能依赖:编写良好的C ++程序比编写良好的Fortran程序需要更多的编程经验。如果您从很少的编程经验入手,而只有太多的时间来学习工作的这一方面,那么与学习C ++相比,学习Fortran可能会获得更好的投资回报。当然,假设您的问题适合于Fortran。

但是,编程不仅限于Fortran和C ++。我建议所有从事计算科学的人从动态高级语言(例如Python)开始。永远记住,您的时间比CPU时间更有价值!


17
“永远记住,您的时间比CPU时间更有价值!” 作为在HPC工作的人,我不同意这一点。其他一切都在现场。
Levi Morrison

19
“永远记住,您的时间比CPU时间更有价值!” 作为从事科学研究的人,我完全同意这一点。
Decvalts

3
“永远记住,您的时间比CPU时间更有价值!” -我想投入2美分-使用数百个节点(每个节点具有10个以上的内核)将某个程序运行几个星期,可以解释为一种最宝贵的资源的可怕浪费,如果再花费几周的时间可以仅在几天内运行的代码。这些HPC群集是稀有且昂贵的通用资源。
Dani_l 2015年

“总是记住您的时间比CPU时间更宝贵!”,编写了一周的代码,但是运行了一个月,这是很平常的先生!
fronthem

6
“永远记住,您的时间比CPU时间更有价值!”,我宁愿编写一个月的代码并在一周内运行!-编写代码后可以做更多的事情,其他人也会发现您编写的代码也更有用。
查尔斯

37

我认为C ++和Fortran都足够好并且可以很好地工作。

但是,我认为Fortran更适合数字科学计算,可以使用数组表示且不需要其他复杂数据结构的算法,因此在诸如有限差分/元素,PDE求解器,电子结构计算等领域。Fortran是特定于域的语言。特别是,我认为,由科学家(不一定是计算机科学专家)用Fortran 编写快速程序比用C ++ 编写容易。

C ++是一种通用语言,因此可以在其中表达任何算法,并且对于无法使用数组表达的算法(从HPC领域,可能是一些图形,网格生成器,符号处理等)来说,它绝对是更好的选择。

也可以用C ++编写数组算法,但是以我的经验,它需要更多的计算机科学知识,并且通常需要更多的工作(即,需要创建或重用类以进行数组操作,以及手动或使用一些内存管理方法。库,例如Trilinos的Teuchos)。非专家通常会编写相当不错的Fortran程序,但会编写糟糕的C ++程序(以我的经验为依据)。

免责声明:我个人非常喜欢Fortran,对于数字计算,我更喜欢它而不是C ++。我每天花2年以上的时间用C ++进行编程,而每天用现代Fortran进行的编程(在有限元素区域中)花费了将近一年。我也经常使用Python和Cython。


1
一个人为第一个答案保持平衡。我认为C ++和Fortran并不是当代HPC的唯一可能性。我认为在决定使用Fortran,C ++或Python(或您喜欢的任何东西)时了解优势和劣势是很好的。我已经在一个文件中看到20.000行的Fortran,数十年来有机地增长了。我个人不会将其用于隔离的重型阵列计算之外。甚至没有任何与输出有关的东西。到目前为止,有偏见。
shuhalo 2011年

6
我不能不同意这个回应。我们的有限元素代码不可能用Fortran编写。实际上,它始于15年前,它是纯C和Fortran的混合体(后者是方法的数字密集型部分),并且在几年的过程中逐渐移至纯C,然后又移至C ++。该代码一贯变得更短,更快,更容易理解,并且每次迭代后功能更强大。我同意其他人的观点,他们指出C ++可以为您提供很多帮助。选择最适合的语言。
比尔·巴特

6
Bill,您是否使用过现代的Fortran(90或更高版本)?这是非常重要的(我对此的回答应该更加明确)。当然,“ Fortran 20.000行”或f77通常并不比编写良好的C ++好。
OndřejČertík”,2011年

1
@OndřejČertík:我认为,如果您认为现代有限元程序使用“简单”数据结构,那么您最近都没有研究它们。尝试使用简单的数据结构在非结构化网格上实现自适应有限元,hp方法或多重网格。比尔是当之无愧的人,我相信我可以代表他说,使用“现代Fortran”几乎没有多大区别。
Wolfgang Bangerth 2012年

6
@WolfgangBangerth,例如,有关您提到的几乎所有内容的Fortran实现,请参见Phaml(math.nist.gov/phaml)。
昂德里杰·塞蒂克

31

我还花了两分钱,但是我只是看过这个话题,所以我觉得,为后代,有一些急切需要提出的观点。

请注意,在下文中,我将讨论C而不是C ++。为什么?好吧,否则,将成熟的动态类型化的面向对象语言与像Fortran这样的静态语言进行比较的人就成了苹果。是的,最新的Fortran标准的一些现代实现不仅可以做更多的事情,但是实际上很少有人使用它们,因此,当我们谈论Fortran时,我们会想到简单,静态和命令式语言。那也是C的所在,因此下面我将用C ++替换C。

首先,关于具有更好的编译器的Fortran / C的讨论都没有意义。专用的C / Fortran编译器已成为过去。gcc / gfortran和icc / ifc只是同一后端的不同前端,即,您的程序将由前端转换为抽象描述,然后由后端进行优化和组装。如果以语义方式用Fortran或C语言编写相同的代码,则在两种情况下,编译器都将产生相同的程序集,其运行速度将相同。

现在这引出我的第二点:为什么我们仍然看到差异?问题在于,大多数比较都是由Fortran程序员尝试使用C进行的,反之亦然。是否曾经注意到大多数作者或诗人更喜欢用母语写作?您是否想用一种不完全自信或不自在的语言写诗?当然不是。我自己认为C是我的“本机”编程语言。但是,我确实也花了三年的时间在一个仅使用Fortran的小组中工作,在该小组中我达到了一定的流利程度。但是,我永远不会在Fortran中自己写任何东西,因为我对C更加满意,因此无论您将其定义为什么,结果代码都会更好

所以主要的区别在于程序员,而不是语言。所以没有区别吗?好吧,不完全是。这里有一些例子:

  • SIMD:无论是SSE,SSE3还是AltiVec,如果您想在Fortran中使用它们,您最好希望并祈祷编译器准确地猜测出您想要的东西并这样做。祝好运。在C语言中,您通常具有每种体系结构的固有功能,或者最近具有gcc中的常规SIMD矢量类型。大多数Fortran编译器仅使用SIMD指令展开循环,但是如果您有一个以非显而易见的方式处理短数据向量的内核,则编译器很可能看不到它。

  • 不同的硬件体系结构:整个CUDA体系结构都是基于C内核构建的。是的,波特兰集团现在也具有支持CUDA的fortran编译器,但它是商业化的,而且最重要的是,它不是来自NVIDIA。OpenCL也是如此,我能找到的最好的是最近的项目,该项目仅支持一些基本调用。

  • 并行编程:是的,MPI和OpenMP在C和Fortran上都可以正常工作。但是,如果您想真正地控制线程,即如果您具有完全动态的共享内存计算,那么Fortran会让您感到烦恼。在C语言中,您拥有标准的pthread,尽管这些线程并不温暖且模糊,但仍然可以帮助您度过难关。通常,大多数依赖操作系统访问的计算(例如线程,进程,文件系统等)最好与C配合使用。哦,不要尝试使用Fortran进行自己的联网。

  • 易于使用:Fortran比C更接近Matlab。一旦掌握了所有不同的关键字以及如何声明变量,其余的代码就类似于Matlab,从而使编程经验有限的用户可以更容易地访问它。

  • 互操作性:在C语言中创建结构时,实际数据的布局是直接且确定的。在Fortran中,如果使用指针数组或结构化数据,则数据的实际布局在很大程度上取决于编译器,而不是直截了当的,并且通常是完全未记录的。您可以从Fortran调用C,反之亦然,但不要开始认为将静态数组从一个数组传递到另一个数组再传递回来可能并不那么容易。

这些都是令人讨厌的低级内容,但这是我们正在谈论的高性能计算,对吗?如果您对如何最好地利用底层硬件范例不感兴趣,即实现和/或开发最适合共享/分布式内存,线程,SIMD矢量化,使用SIMT的GPU等的算法,那么您就是只是在计算机上做数学。

这已经比我所想的要长得多,所以这里是一个摘要-一系列带回家的消息:

  • 你会写出最好的代码,你在其中的语言可以,你知道最好的。
  • 使用相同后端的两个编译器产生的代码质量没有差异-是我们用一种或另一种语言编写错误代码。
  • 尽管感觉比较低级,但是Fortran还是一个高级抽象,不会让您直接访问某些硬件/操作系统功能,例如SIMD,线程,网络等。

5
反应良好。我认为您的最终评论不一定正确。我本人是C程序员,但是您可以通过良好的编程习惯来访问Fortran中的低级内容。利用SIMD ops之类的东西的理想方法是编写强烈建议使用它的代码(例如,阻塞循环),然后让编译器为您完成。对于线程,只需使用openMP(pthreads还可用于一些额外的工作)。Fortran具有您提到的所有功能,而对于它的典型用户而言,它只是一个重要的级别:数字。
Reid.Atcheson,2012年

@ Reid.Atcheson:好吧,如果您阻塞所有内容以使编译器可以捕获它,那么它将在C和Fortran中自动运行。但问题是,您想信任编译器多远?当您完全知道自己想做什么时,为什么还要信任它呢?OpenMP可以进行线程化,是的,但可以逐块执行。您可以欺骗它,让不同的线程池执行不同的操作,但这只是滥用OpenMP。Fortran的Pthread只是C函数的包装。不过,我同意,如果您不了解详细信息,那么Fortran会更容易。
2012年

1
当然,依靠编译器不会达到成熟的99%峰值效率,但是您可以很轻松地接近它。除此之外,您还必须使用内部函数或内联ASM。您必须在某些地方做出让步,以提高整体程序员的效率,这就是为什么首先存在编程语言的原因。在您实际上非常疯狂地了解内在函数或ASM的阶段(我已经去过几次),Fortran并不是拐杖。无论如何,您将知道如何链接到已汇编的手动优化代码中。
Reid.Atcheson,2012年

@ Reid.Atcheson:好吧,我认为对于并行HPC应用,您可能最终会远远低于99%的峰值效率...而且gcc向量类型使使用内在函数成为非问题:)
Pedro

1
@Pedro,精彩的帖子。绝对辉煌​​。非常感谢您的发布。只是在随机浏览有趣的线程时发现了它。
Inquest 2012年

16

在我15年的科学软件思考中:如果您的代码运行速度提高了25%(因为您是用Fortran编写的),但是编写它所需的时间却是它的4倍(没有STL,难以实现复杂的数据结构等),那么Fortran仅当您花费大量时间摇动拇指并等待计算完成时才赢。鉴于对我们所有人来说,最宝贵的时间就是我们自己的时间,其结论是:使用允许您以最快的速度开发,调试和测试代码的语言,在某种程度上忽略了它可能比可能慢的原因。您是用Fortran编写的。


13

我的方法是对计算内核以外的所有事物都使用C ++,这通常最好用汇编语言编写。这可以为您带来传统HPC方法的所有性能,但可以简化接口,例如,将SGEMM / DGEMM / CGEMM / ZGEMM之类的计算内核重载到单个例程中,例如Gemm。显然,可以通过避免使用原始指针并切换到不透明类来提高抽象级别,但这是一个不错的第一步。

我发现C ++最大的缺点是编译时间的增加,但是以我的经验,节省的开发时间远远不能弥补。另一个缺点是,与C和Fortran编译器相比,C ++编译器往往具有更多的错误。在过去的一年中,我认为我在C ++编译器中遇到了将近十个错误。

综上所述,我认为撤销以低级语言(和Fortran)编写的科学软件包的做法是不愿公开用于复杂数据结构的便捷接口:大多数人都对Fortran BLAS接口感到满意,因为它只需要用来描述矩阵的指针和前导维,但是很少有人会争辩说,通常的40整数Fortran稀疏直接求解器接口几乎很方便(参见UHM,SuperLU,PETSc和Trilinos)。

总而言之,我主张对低级计算内核使用汇编语言,而对其他所有语言使用高级语言,尤其是对非平凡的数据结构进行操作时。

y:=αx+y


2
您为什么不信任启用了适当优化的标准C编译器来编译小型内核?在那种代码大小和复杂度的水平上,编译器可以退出的差异尚不清楚。
彼得·布鲁恩

1
我曾与一些人交谈,他们告诉我,即使使用适当的限制用法,对于某些操作(例如显式矩阵转置),他们的Fortran仍然比其C和/或C ++代码更快。我并不是说不可能使C或C ++代码变得如此快,但是Fortran编译器往往会做得更好。
杰克·普尔森

我对“ restrict”关键字有相同的体验(我简单的Fortran代码总是快一些)。但是我的专长是有限的,而且我根本没有时间去了解gcc生成的程序集。所以我只是使用Fortran,它既简单又快速。
2011年

@JackPoulson:我从Fortran社区中听到了很多关于编译器参数的信息。不幸的是,大多数编译器(例如gcc或ifc / icc)对同一后端使用不同的语言前端。进行优化和代码生成的机制是相同的,因此结果的差异很可能是由于程序员对基础语言的熟悉程度不同所致……
Pedro

1
只是为了对经常重复但很少得到验证的关于Fortran在数字内核上更快的说法提供一些观点:前一阵子,我们注意到Trilinos的Epetra程序包中的稀疏矩阵矢量乘积比其中的慢30%。交易 前者是用Fortran 77直接编写的,后者是用C直接编写的,没有使用“限制”。两者都有大约10-15行代码。如今,Trilinos使用了源自deal.II的代码段。我敢肯定,在很多情况下F77的速度都比C快。关键是,今天这种情况并不普遍。
Wolfgang Bangerth 2012年

8

因为我是新来的,所以我一直在浏览旧问题并找到了这个问题。希望回答旧问题不是禁忌!

既然没有人提到这件事,我想。大多数主要的编译器(intel,ibm,cray,NAG,PCG)几乎都完全支持 Fortran 2003 ,甚至还有即将推出的最新版本4.7的gcc。Fortran 2003(和2008)是一种面向对象的语言,尽管比C ++更为冗长。我认为Fortran的优点之一是,标准委员会将科学计算视为其主要受众(我感谢Damian Rouson前几天向我指出了这一点)。

我并不是为了使C ++程序员成为Fortran程序员,而是为了让Fortran的人们知道他们现在除了切换到C ++或在Fortran 90/95中模拟面向对象的概念外,还有更多选择。

我要补充的一个警告是,处于编译器实现的最前沿的代价是代价。如果您现在在Fortran 2003中进行一个大型项目,您会偶然发现bug,并不断需要更新编译器(特别是如果您使用gcc),尽管在过去几个月中,这种情况已经大大改善了!


7

C ++的问题在于,您有很多机会破坏性能,例如盲目地使用STL,异常,类(虚拟开销和对齐问题),运算符重载(冗余的新/删除)或模板(无休止的编译和错误)看起来不错,但是您可以这样浪费时间)。

但是,更多的人可以更好地访问通用库,并且可以更好地查看代码(尽管这在很大程度上取决于字段,并且您仍然拥有纯C语言)。您仍然可以通过将其代码包装在脚本语言(例如R,Lush,Matlab / Scilab甚至Python,Ruby或Lua)中来弥补Fortran的灵活性不足。


1
在高级语言中应用低级技术通常是一个坏主意。例如,STL被设计为在非常抽象的级别上运行。必须知道该接口是为什么设计的,将其用于此任务,然后摆脱编译器的方式。
shuhalo 2011年

2
我认为mbq和Martin的观点都不公平。是的,如果您尝试使用std :: list <double>为线性代数目的实现数字矢量,则有多种方法可以使自己陷入困境。但这是一个愚蠢的说法:至少C ++ 具有可使用的链表类,而Fortran却没有。这就像在说:“汽车的行驶速度如此之快,以至于您可能撞到墙壁并受伤;您应该使用马拉的马车。” 废弃也支持具有高级功能的低级内容(例如C ++)的高级语言只是一个愚蠢的想法。
Wolfgang Bangerth 2012年

@WolfgangBangerth不,现在您在伤害Fortran,它就像细菌比人类“进化得少”一样“低级”。如果您想用汽车做个比喻,它应该更像是“您可以同时使用吉普车和雷克萨斯来穿越沼泽路,但使用第一个汽车所受的伤害较小”。
mbq 2012年

1
感谢您的意见,但我
坚信

7

三个事实:

  • C语言中的F77样式n维数组:使用CnD没问题(诚​​然,一个无耻的插件)

  • F90的模块系统设计欠佳,对构建环境不利。(例如,模块的名称不必与文件名匹配)

  • Fortran无法很好地支持重构。从函数中提取一些功能需要您触摸四个位置:实际代码,变量声明,参数声明和参数列表。C碰触到两个地方。这加剧了无法很好地管理数据的影响(如下所述):由于小规模的模块化非常痛苦,因此几乎每个人都编写了巨大的子例程。

个人印象:

  • Fortran不适用于管理数据。尝试在F77或F90中返回指向用户不透明数据结构的指针。(transfer(),我们来了)

嗨,安德里亚斯!CnD很有趣,我不知道。啊,你写的。:)(f90还支持切片,可分配给数组,最重要的是-用于乘法,加法等的数组语法。)我将CMake与Fortran一起使用,并且它与模块非常兼容。什么是“参数列表”?我不认为我使用了这些,因此只需修改3个位置。在C语言中,通常需要修改实际的代码,参数和头文件,因此它也是3个位置(最肯定是在C ++中)。是的,transfer()并不是很好,但是通常在实践中不需要它。
2011年

3
使用适当的IDE重构现代fortran并不容易,例如Eclipse中的Photran。

2
“一个模块的名称不必与它的文件名相匹配,例如”。其中一些仅跨越几行。如果您不必为每个文件创建文件,则它们创建起来会容易得多。
Vladimir F

1
只是想补充一下@ user389所说的内容,尽管Photran很棒,并且是唯一允许重构的Fortran IDE,但其解析器始终会失败。另一方面,无需评论Eclipse需要大量内存的事实。
astrojuanlu

5

Fortran已针对数组/矩阵计算进行了优化,并且对于任何类型的文本解析都非常麻烦。C和C ++在数值计算上可能无法与Fortran匹配(接近),但是我发现使用C / C ++处理文本和组织数据(即自定义数据结构)要容易得多。

正如其他人所提到的,不要指望动态解释语言(Python等)。它们可能无法提供Fortan的正面融化速度,但是它们使您可以将精力更多地放在解决计算问题上,而不是实现的所有细节。通常,您可以使用Python实现解决方案,如果性能不可接受,请进行一些性能分析,确定问题区域,然后使用Cython优化该代码或以编译语言重新实现整个程序。一旦解决问题的逻辑充实了,剩下的只是实现,并且在对计算基础有所了解的情况下,应该可以很容易地以任何一种编程语言来表示。


那就对了。对于文本解析,我还使用Python。
2011年

您还可以实现一个Python脚本的一部分编译语言如C ++,并把它挂在如升压Python中,痛饮等。
Faheem米撒

4

我目前在国家实验室之一工作。我周围的大多数人都是机械工程师。与HPC小组中的一些人聊天时,他们主要是Linux和C ++。我目前所在的组主要用于桌面应用程序,我们以降序使用Windows:C#,FORTRAN,Python,VBA和VB(6,而不是.NET)。我们使用的一些仿真引擎是在FORTRAN的其他国家实验室编写的。


4

不好意思,我想挖一个旧线程,但即使在2015年,Fortran仍被大量使用。

我只是碰到了这个(替代链接)列表,该列表基本上是由美国能源部的OCLF设施批准的,在300 petaFLOPS Summit机器上运行的13个代码的清单,该机器将于2018年提供给研究人员。我试图找到使用的主要语言代码(基于谷歌快速搜索),这是我发现的内容:

XGC Fortran

SPECFEM Fortran

ACME Fortran (Bunch of climate codes)

DIRAC Fortran (Mostly)

FLASH Fortran

GTC Fortran

HACC C/C++

LS-DALTON Fortran (some C)

NAMD C/C++

NUCCOR Fortran

NWCHEM Fortran

QMCPACK C++

RAPTOR Fortran

因此,在13个代码中,至少有10个(根据我的快速搜索)似乎是用Fortran编写的。对于50岁的语言来说还不错。

注意:我很清楚,语言比较是没有用的,但是考虑到Fortran不好的人(特别是C ++用户)的数量,我认为值得一提。


3
我不同意,因为我在国家实验室的经验恰恰相反。我在劳伦斯·利弗莫尔(Lawrence Livermore)看到的大多数新项目都是用C ++编写的,并且ODE求解器,FEM离散化和通用科学计算库中的大多数新的(或积极维护的)最新的开源库似乎是在C或C ++中。Fortran似乎主要用于使用现有/旧版库的项目中。我没有看到很多使用Fortran的大型新项目,而与我对语言的看法无关。
Geoff Oxberry 2015年

一些用Fortran编写的密度泛函理论代码包括VASPCASTEP,尽管正如@GeoffOxberry指出的那样,项目的确可能倾向于C ++。
dr.blochwave

@blochwave如您在链接中所读,这些项目是针对一台新机器(带有加速器等)的,该机器将于2018年上线。因此,它不像需要25年的代码并进行编译,而是希望以良好的性能运行性能。我可以肯定上面列表中的大部分代码已经或已经被重写,就像新代码一样。Fortran中也有许多“新的”气候法规,许多国家的许多机构都在使用。
stali 2015年

0

杰克·P·我想说的是,您应该混搭。精心设计了一个好的软件。不同的层可以更自然或更有效地映射到不同的语言。您应该为每个图层选择最合适的语言。您还应该了解语言如何进行互操作,这可能会影响您为哪一层选择的语言。

一个更好的问题是,有哪些优秀设计的软件实例值得研究,以学习如何设计分层软件。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.