认为这是对 Adriano 答案的扩展评论(和扩展)。
OpenMP 非常易于掌握和使用,它具有可以从同一个源代码生成串行和并行可执行文件的优点。如果您需要将现有的串行代码转换为并行代码,它还允许您采用渐进并行化路径。不过,OpenMP 有一系列缺点。首先,它只针对严重限制了其可扩展性的共享内存机器,尽管现在可以使用大型 x86 SMP 机器(例如,我们有 QPI 耦合 Xeon 系统,在我们的集群安装中共享高达 2 TiB 的共享 RAM 的 128 个 CPU 内核,专门针对大型 OpenMP 作业)。其次,它的编程模型过于简单,无法实现一些高级概念。但我会说这是该模型的优点而不是缺点,因为它使 OpenMP 保持简洁。
MPI 是事实上的现在的标准消息传递 API。它得到广泛支持并在多种并行架构上运行。它的分布式内存模型对底层硬件几乎没有限制(除了具有低延迟和高带宽的网络互连),这允许它扩展到数十万个 CPU 内核。MPI 程序在源代码级别上也非常可移植,尽管算法本身可能不具备可移植的可扩展性(例如,一个 MPI 程序可能在 Blue Gene/P 上运行得非常高效,而在 InfiniBand 集群上运行速度非常慢)。MPI 有一个严重的缺点——它的 SPMD(单程序多数据)模型需要代表程序员进行大量的精神分裂思考,并且比 OpenMP 更难掌握。将串行算法移植到 MPI 从来没有像使用 OpenMP 那样容易,有时需要完全重写才能实现高并行效率。采用渐进式并行化方法并轻松维护可以生成串行和并行可执行文件的代码库也是不可能的。MPI 有一个有趣的特性——因为它完全分离了在不同节点上运行的程序的不同部分,并为网络提供了一个抽象接口,它允许异构计算。几种 MPI 实现(例如 Open MPI)提供了异构支持,它不仅允许混合运行在不同操作系统下的节点,还允许混合具有不同“位”和字节序的 CPU。采用渐进式并行化方法并轻松维护可以生成串行和并行可执行文件的代码库也是不可能的。MPI 有一个有趣的特性——因为它完全分离了在不同节点上运行的程序的不同部分,并为网络提供了一个抽象接口,它允许异构计算。几种 MPI 实现(例如 Open MPI)提供了异构支持,它不仅允许混合运行在不同操作系统下的节点,还允许混合具有不同“位”和字节序的 CPU。采用渐进式并行化方法并轻松维护可以生成串行和并行可执行文件的代码库也是不可能的。MPI 有一个有趣的特性——因为它完全分离了在不同节点上运行的程序的不同部分,并为网络提供了一个抽象接口,它允许异构计算。几种 MPI 实现(例如 Open MPI)提供了异构支持,它不仅允许混合运行在不同操作系统下的节点,还允许混合具有不同“位”和字节序的 CPU。MPI 有一个有趣的特性——因为它完全分离了在不同节点上运行的程序的不同部分,并为网络提供了一个抽象接口,它允许异构计算。几种 MPI 实现(例如 Open MPI)提供了异构支持,它不仅允许混合运行在不同操作系统下的节点,还允许混合具有不同“位”和字节序的 CPU。MPI 有一个有趣的特性——因为它完全分离了在不同节点上运行的程序的不同部分,并为网络提供了一个抽象接口,它允许异构计算。几种 MPI 实现(例如 Open MPI)提供了异构支持,它不仅允许混合运行在不同操作系统下的节点,还允许混合具有不同“位”和字节序的 CPU。
英特尔 TBB 就像打了兴奋剂的 OpenMP。它提供了更丰富的基于内核的编程模型,使其更接近于其他并行编程范式,如 CUDA 或 OpenCL。它在适用性和可扩展性方面大量借鉴了 C++ STL 算法。它也应该是编译器中立的,原则上应该与英特尔 C++ 编译器、GNU g++ 和 MSVC 一起使用。ITBB 还使用任务“窃取”意识形态,如果不采取预防措施,可能会消除先前范式容易出现的计算失衡。
Pthreads 是最现代的类 Unix(例如 FreeBSD、Mac OS X、Linux 等)的可移植线程接口。它只是一个线程库,面向人们可以想象的最常见的用例。它几乎不提供并行结构,并且必须在其之上显式地对它们进行编程,例如,即使是简单的循环迭代分布(如 OpenMP)也必须手动编码。Pthreads 之于 Unix 就像 Win32 线程之于 Windows。
(我会跳过 Microsoft TPP,因为我真的不知道那个库)
随着单个节点逐渐获得越来越多的核心,混合这些概念显然是未来的方式。大多数算法都可以实现多级并行,可以使用 MPI 执行粗粒度并行(在多个集群节点上运行),而 OpenMP 或 ITBB 可用于执行单个节点计算的细粒度划分。共享内存编程通常可以更好地利用内存资源,因为它们都在线程之间共享,并且缓存重用之类的东西可以大大加快计算速度。MPI 也可用于对多核 SMP 或 NUMA 机器进行编程,但每个 MPI 进程都是一个单独的 OS 进程,具有自己的虚拟地址空间,这意味着可能需要复制大量(配置)数据。
我建议选择最接近你的编程背景的那个。如果您是一个狂热的 C++ 程序员并且喜欢抽象,那么选择 Intel TBB(如果您喜欢 .Net,则选择 Microsoft PPL)。OpenMP 真的很容易掌握并提供了良好的性能,但不知何故过于简单。它仍然是在 Fortran 中编写多线程代码的唯一广泛可用和使用的机制。MPI 有一个陡峭的学习曲线,但如果您的程序超出了单个计算节点所能提供的能力,那么以后总是可以使用螺栓。