并行科学计算软件开发语言?

计算科学 Python 高性能计算 C++ 正则 模拟
2021-12-20 21:55:00

我想从头开始开发一个并行的科学计算软件。我想要一些关于从哪种语言开始的想法。该程序涉及读取/写入数据到 txt 文件和并行执行大量计算,具有许多 LU 分解和使用稀疏线性求解器。我正在考虑的候选解决方案是带有 OpenMP 或 co-array 的 Fortran 2003/2008、带有 openmp cilk+ 或 TBB 的 C++、python。欢迎任何其他记录在案的建议!我非常了解 C、Fortran 和 Java(按此顺序)。我已经在 python 中编写了一些脚本,但是基本的东西。

我知道 fortran 非常快,但是很难维护和并行化。据说 C++ 很慢,除非您使用我喜欢的外部库等 Python,但是在上面编写完整的工业级软件是否现实?

该软件需要能够处理大量数据并有效地进行科学计算。表演才是重点。

作为背景,我已经有一个用 Fortran 编写的工作软件。许多人参与了多年的开发,代码真的很脏。维护和并行化代码已被证明是一场噩梦,我正在考虑替代方案。

4个回答

让我尝试分解您的要求:

  • 可维护性
  • 读/写文本数据
  • LU分解的强大接口/能力
  • 稀疏线性求解器
  • 大数据的性能和可扩展性

从这个列表中,我会考虑以下语言:

C、C++、Fortran、Python、MATLAB、Java

Julia 是一种很有前途的新语言,但社区仍在围绕它形成,并且尚未在任何主要的新代码中部署。

读/写文本数据

这在任何编程语言中都很容易做到。确保您适当地缓冲和合并您的 I/O 访问,并且您将从您应该考虑的任何语言中获得良好的性能。避免使用 C++ 中的流对象,除非您知道如何高效地使用它们。

LU分解的强大接口/能力

如果您正在执行密集的 LU 分解,您将需要使用 LAPACK 或 ScaLAPACK/Elemental 来实现并行功能。LAPACK 和 ScaLAPACK 是用 Fortran 编写的,Elemental 是用 C++ 编写的。这三个库都是高性能的,并且得到了很好的支持和记录。您可以从您应该考虑的任何语言与它们交互。

稀疏线性求解器

首屈一指的免费稀疏线性求解器几乎都可以通过PETSc获得,用 C 语言编写,有详细的文档和支持。您可以从您应该考虑的任何语言与 PETSc 交互。

大数据的性能和可扩展性

您提到的唯一并行编程范例是基于共享内存的,这意味着您没有考虑基于 MPI(消息传递)的分布式内存计算方法。根据我的经验,使用分布式内存解决方案编写可扩展到十几个内核之外的代码要容易得多。如今,几乎所有的大学“集群”都是基于 MPI 的,大型共享内存机器价格昂贵,而且相应地很少见。您应该为您的方法考虑 MPI,但无论您选择哪种编程范式,我的建议都将适用。

关于节点性能,如果您自己编写数值例程,最容易在 Fortran 中获得良好的串行性能。如果您在 C、C++ 或 Python 方面有一点经验,您可以获得非常可比的性能(C 和 C++ 是死的,即使使用 Fortran,Python 和 MATLAB 只需花费大约 25% 的时间开销,而无需付出太多努力)。MATLAB 通过 JIT 编译器和非常好的线性代数表达能力来做到这一点。您可能需要使用 Cython、numpy、numexpr 或嵌入数值内核来从 Python 获得声称的性能。我无法评论 Java 的性能,因为我不太了解该语言,但我怀疑如果由专家编写,它与 Python 的性能相差不远。

关于接口的说明

我希望我已经说服你,你将能够用你正在考虑的任何编程语言做任何你想做的事情。如果您使用的是 Java,那么 C 接口将有点挑战性。Python 通过 ctypes、Cython 和 f2py 具有出色的 C 和 Fortran 接口支持。LAPACK 已经打包并通过 scipy 提供。MATLAB 在其本机库中具有您需要的所有功能,但不易扩展或特别容易在集群上运行。Java 可以通过JNI支持 C 和 Fortran 接口,但在集群和用于科学计算的并行软件中并不常见。

可维护性

很多这将归结为个人喜好,但关于可维护性的普遍共识是,您希望最大限度地减少软件中的代码行数,编写具有明确定义的接口的模块化代码,对于计算软件,提供验证实现的正确性和功能性的测试。

推荐

个人对 Python 很幸运,我推荐它用于许多计算项目。我认为您应该为您的项目强烈考虑它。Python 和 MATLAB 可能是可用于科学计算的最具表现力的语言。您可以轻松地将 Python 连接到任何其他编程语言,您可以使用 f2py 来包装您当前的 Fortran 实现,并在验证您是否正在维护功能的同时,在 Python 中逐段重写您希望使用的任何部分。此时,我会推荐将官方 Python 2.7 实现scipy结合使用。您可以从免费提供的 Enthought Python Distribution轻松开始使用此堆栈。

您也可以在 C、C++ 或 Fortran 中完成大部分操作。对于具有丰富经验的专业开发人员来说,C 和 C++ 是非常有吸引力的语言,但经常会绊倒新开发人员,从这个意义上说,对于更具学术性的代码来说,这可能不是一个好主意。Fortran 和 MATLAB 在学术计算中很流行,但在 Python 提供的高级数据结构和表达能力方面很弱(例如,想想 Python dict 对象)。

相关问题:

除了 Aron 非常全面的答案之外,我还要看看 scicomp.stackexchange 上的各种线程,这些线程处理了采用哪种编程语言的问题——包括程序的速度以及简单或困难的问题就是用这些语言编写和维护软件。

也就是说,除了那里写的内容之外,让我提出一些意见:

(i) 您在列表中包含 co-array Fortran。据我所知,实际支持它的编译器数量非常少——事实上,我的数量为零。最广泛使用的 Fortran 编译器是 GNU gfortran,虽然当前的开发源解析协数组的一个子集,但我相信它实际上并不支持其中任何一个(即,它接受语法但不实现任何语义) . 这当然是对较新的 Fortran 标准的一般观察:编译器实际支持新标准的滞后是几年来衡量的——编译器在过去几年中仅完全实现了 Fortran 2003,并且仅部分支持 Fortran 2008。如果您有一个恰好支持您使用的编译器,这不应该阻止您使用其中的任何一个,

(ii) C++/Cilk+ 也是如此:是的,英特尔正在 GCC 的一个分支上开发它,但它在任何 GCC 版本中都不可用,而且很可能暂时不会。您可以预计至少需要 2-3 年才能找到 Cilk+ 以及安装在典型 linux 机器上的 GCC 版本。

(iii) C++/TBB 是一个不同的故事:TBB 已经存在了一段时间,具有非常稳定的界面,并且可以与过去几年存在的大多数 C++ 编译器(在 Linux 和 Windows 上)进行编译. 我们已经在deal.II中使用了几年,效果很好。还有一本非常好的书。

(iv) 我对 OpenMP 有自己的看法,即它是寻找问题的解决方案。它适用于并行化内部循环,如果您有非常规则的数据结构,这可能会引起您的兴趣。但是,如果您需要并行化某些东西,这很少是您想要做的——因为您真正想要做的是并行化外部循环。为此,诸如 TBB 之类的解决方案是更好的解决方案,因为它们使用编程语言的机制,而不是试图描述语言之外发生的事情(通过#pragmas),并且您无法访问线程句柄,结果状态指示器等,来自您的程序。

(v) 如果您是实验性的,您还可以看看为并行编程而设计的新编程语言,特别是针对您所描述的那些任务。基本上有两个我要看看: X10Chapel我在 Chapel 上看过很好的教程,它看起来设计得很好,尽管今天两者当然也是孤立的解决方案。

一般来说,如果你真的对这个软件项目很认真,我会建议用你自己觉得最舒服的任何语言完全重写。听起来您将独自完成工作,因此您将使用您最熟悉的语言获得最佳结果。

不过,更具体地说,关于并行性,我鼓励您尝试跳出框框思考。OpenMP 有其优势,但仍停留在采用顺序代码和随处添加并行性的思维方式中。本质上,英特尔的 TBB 也是如此。

Cilk绝对是朝着正确方向迈出的一步,即它迫使您在固有的并行设置中重新考虑您的问题/解决方案。不过,我不喜欢它的地方在于它是另一种语言此外,由于它只能粗略地推断并行任务之间的关系,调度程序可能非常保守,可能无法很好地解决某些问题。

不过,好消息是,如果你对你的实现很认真,你可以做 Cilk 所做的事情,例如将你的问题重新编写为一组相互依赖的任务,并将它们分布在多个处理器上/核心,全部由您自己使用pthreads或滥用 OpenMP 来生成进程。PLASMA库中使用的QUARK调度程序就是一个很好的例子。这里给出了它的性能与 Cilk 的一个很好的比较

在上述评论中几乎没有讨论 coarray fortran。目前,据我所知,编译器中的 coarray 支持大致如下:

  • Cray 有一个编译器,它至少支持基本的 coarray 特性。我用它来编写旨在“教育”的代码,但我想说你可以用 coarray fortran 编写真正的代码。语法和概念大多比 MPI 简单得多,但与往常一样,存在很多陷阱,并且陷阱与 MPI 不同。
  • 英特尔 fortran 在其 MPI 库之上构建了 coarray 支持。据说这限制了他们的理论峰值性能,但我还没有看到任何指标。
  • Gfortran 支持 coarrays,但仅适用于单个图像(或 MPI 中的单个等级)。因此,在 gfortran 4.8 或 4.9 发布之前,没有真正的并行化可用。

一般来说,如果启动基于 coarray 的代码,我会小心。语法比带有 MPI 的 Fortran/C/C++ 更简单,更方便,但是,它的功能并不全面。例如,MPI 支持很多归约操作等,这对您来说可能非常方便。这真的取决于你是否需要大量的沟通。如果您想要一个示例,请告诉我,如果我可以挖掘文件,我可以为您提供一些示例。