在我的计算科学博士项目中,我们几乎只使用 C++ 和 Fortran。似乎有些教授更喜欢其中之一。我想知道哪个“更好”,或者在某种情况下是否比另一个更好。
用于 HPC 的 C++ 与 Fortran
通常,选择取决于(1)您要解决的问题,(2)您拥有的技能,以及(3)与您一起工作的人(除非它是一个单独的项目)。我暂时将(3)放在一边,因为这取决于每个人的个人情况。
问题依赖性:Fortran 擅长数组处理。如果您的问题可以用简单的数据结构,特别是数组来描述,那么 Fortran 非常适合。Fortran 程序员最终会使用数组,即使在不明显的情况下(例如用于表示图形)。C++ 更适合复杂和高度动态的数据结构。
技能依赖:编写好的 C++ 程序比编写好的 Fortran 程序需要更多的编程经验。如果您从很少的编程经验开始并且只有这么多时间来学习您工作的这方面,那么您可能会从学习 Fortran 获得比学习 C++ 更好的投资回报。当然,假设您的问题适合 Fortran。
然而,编程不仅仅是 Fortran 和 C++。我建议任何进入计算科学的人从 Python 等动态高级语言开始。永远记住,你的时间比 CPU 时间更宝贵!
我认为 C++ 和 Fortran 都足够好并且运行良好。
但是我认为 Fortran 更适合数值科学计算,适用于可以使用数组表示且不需要其他复杂数据结构的算法,因此在有限差分/元素、PDE 求解器、电子结构计算等领域。Fortran 是一种特定领域的语言。特别是,我认为科学家(不一定是计算机科学专家)用 Fortran编写快速程序比用 C++ 更容易。
C++ 是一种通用语言,因此可以用它来表达任何算法,对于无法使用数组表达的算法,它肯定更好,从 HPC 领域可能是一些图形、网格生成器、符号操作等。
也可以用 C++ 编写数组算法,但根据我的经验,它需要更多的计算机科学知识和更多的工作(即需要创建或重用用于数组操作的类,并手动处理内存管理或使用一些像 Trilinos 的 Teuchos 这样的库)。非专家倾向于编写相当不错的 Fortran 程序,但 C++ 程序却很糟糕(根据我自己的经验)。
免责声明:我个人非常喜欢 Fortran,我更喜欢它而不是 C++ 用于数值计算。我每天用 C++ 编程超过 2 年,每天用现代 Fortran 编程近一年(在有限元领域)。我也经常使用 Python 和 Cython。
我也有点晚了,但我只是看到了这个线程,我觉得对于后代来说,有几点迫切需要提出。
请注意,下面我将讨论 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 语言中,您有标准的 pthreads,虽然不温暖和模糊,但仍然可以帮助您度过难关。一般来说,大多数依赖于访问操作系统的计算,例如线程、进程、文件系统等......最好用 C 来处理。哦,不要试图用 Fortran 做你自己的网络。
易用性:Fortran 比 C 更接近于 Matlab。一旦你了解了所有不同的关键字以及如何声明变量,剩下的代码看起来就像 Matlab,让编程经验有限的用户更容易使用它。
互操作性:当您在 C 中创建结构时,实际数据的布局是直接且确定的。在 Fortran 中,如果您使用指针数组或结构化数据,则数据的实际布局强烈依赖于编译器,不是直截了当的,而且通常完全没有文档记录。您可以从 Fortran 调用 C,反之亦然,但不要开始认为将静态数组以外的任何东西从一个到另一个传递并返回可能很容易。
这都是一些令人讨厌的低级东西,但这是我们正在谈论的高性能计算,对吗?如果您对如何最好地利用底层硬件范例不感兴趣,即实现和/或开发最适合共享/分布式内存、线程、SIMD 矢量化、使用 SIMT 的 GPU 等的算法,那么您就是只是在电脑上做数学。
这比我想要的要长得多,所以这里有一个摘要——一组带回家的信息:
- 你会用你最熟悉的语言编写最好的代码。
- 使用相同后端的两个编译器生成的代码质量没有区别——是我们用一种或另一种语言编写了糟糕的代码。
- 尽管感觉更底层,Fortran 是一个相当高级的抽象,不会让您直接访问某些硬件/操作系统功能,例如 SIMD、线程、网络等......
从我对科学软件的 15 年思考中:如果你的代码运行速度提高了 25%,因为你用 Fortran 编写它,但编写它的时间是你的 4 倍(没有 STL,难以实现复杂的数据结构等),那么 Fortran只有当你一天中的大部分时间都在摆弄拇指并等待你的计算完成时,你才会获胜。鉴于几乎对我们所有人来说最有价值的东西是我们自己的时间,因此结论是:使用允许您以最快的速度开发、调试和测试代码的语言,在合理的范围内忽略它可能比可能的慢你用 Fortran 写的。