4

我正在使用 c++ 开发一些代码,用于我在计算动力学方面的研究。我的代码解决了稀疏矩阵和密集矩阵,生成网格,并在最简单的意义上执行类似的操作。我需要并行化我的代码以减少计算时间并为此使用 OpenMP。

但是在仔细查看了商业可用的代码后,例如 ANSYS CFX,我发现该软件中使用的并行化方案是 MPICH2,它是 MPI 的一种实现。

所以你有很多并行化工具/API:

  • 开放式MP
  • MPI
  • 英特尔线程构建模块
  • 线程
  • 微软 PPL

我使用了其中一些工具,并设法在我的本地计算机上使用每个工具获得 100% 的 CPU 使用率。

我不知道在选择合适的并行化工具时应该注意哪些标准。什么样的应用需要什么样的工具?以上任何一项都可以用于研究目的吗?其中哪些主要用于商业软件?

4

2 回答 2

7

对于许多此类问题,并没有真正确定的答案。你不能说什么更好,因为答案总是“视情况而定”。关于你在做什么,关于你的代码是如何编写的,你的可移植性要求是什么等等。

按照您的清单:

  • OpenMP:非常标准,我发现它非常易于使用。即使原始代码没有考虑到并行化,这个库也使一步一步的方法非常容易。我认为这是并行计算的一个很好的切入点,因为它可以让一切变得简单,但很难调试,性能有限,而且它只是使代码并行(它缺乏并行算法、结构、原语,你不能跨越工作一个网络)。
  • 消息传递接口:在我看来,基于此标准的库最适合跨集群进行大型计算。如果您的计算机数量很少,并且想要并行计算,那么这是一个不错的选择,众所周知且稳定。这不是(在我看来)本地并行化的解决方案。如果您正在寻找用于网格计算的知名、大型使用标准,那么 MPI 适合您。
  • 英特尔线程构建模块:这是一个 C++ 库,用于统一跨不同环境(pthread 或 Windows 的线程模型)的多线程接口。如果您使用这样的库,则可能需要跨编译器和环境进行移植。此外,使用这个库不会限制你,因此它可以很好地与其他东西(例如 MPI)集成。你应该看看这个库,看看你是否喜欢它,这是一个很好的选择,设计很好,有据可查并被广泛使用。
  • Microsoft Parallel Patterns Library:这是一个非常大的库。它很新,所以我不觉得建议有人在没有经过良好测试的情况下使用它是不安全的,而且它是 Microsoft 特定的,所以你与它的编译器有关。这就是说我认为这是一个很棒的图书馆。它抽象了很多细节,设计精良,并提供了“并行任务”概念的非常高级的视图。再次使用这个库并不会阻止您使用,例如,用于集群的 MPI(但并发运行时有它自己的库)。

用什么?我没有答案,只是尝试选择你觉得更舒服的东西(也看看Boost Threads)。请注意,您可以以某种方式混合它们,例如 OpenMP+MPI、MPI+TBB 甚至 MPI+PLL)。我的偏好是 PPL,但如果您正在开发一个真实世界的应用程序,您可能需要长时间的测试来决定哪个更好。实际上我喜欢并发运行时(PPL 的基础),因为它是“水平的”,它为并行计算和许多“垂直”包(代理、PPL、TPL )提供了一个基本框架(带有结构和算法)。

也就是说,当您进行并行计算时,您可能需要提高一些 CPU 密集型例程的性能。您可以考虑使用 GPU 来完成这项任务,我认为它会为短时间的大规模并行计算提供最好的效果(当然,即使 CUDA 性能可能更高,我也更喜欢OpenCL而不是专有的CUDA)。实际上,如果您对此主题感兴趣,您甚至可以查看OpenHMPP 。

于 2012-06-05T18:13:39.173 回答
3

认为这是对 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 有一个陡峭的学习曲线,但如果您的程序超出了单个计算节点所能提供的能力,那么以后总是可以使用螺栓。

于 2012-06-05T21:25:19.290 回答