选择并行化方案需要考虑什么?

时间:2012-06-05 17:59:28

标签: c++ parallel-processing mpi openmp tbb

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

但仔细研究了商用代码,比如ANSYS CFX,我遇到了该软件中使用的并行化方案是MPICH2,它是MPI的一种实现方式。

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

  • OpenMP的
  • MPI
  • 英特尔线程构建模块
  • P线程
  • Microsoft PPL

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

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

2 个答案:

答案 0 :(得分:7)

至于这种类型的许多问题,没有一个真正明确的答案。你不能真正说出什么更好,因为答案总是“它取决于”。关于你在做什么,你的代码是如何编写的,你的可移植性要求是什么等等。

点击列表:

  • OpenMP:非常标准,我发现真的易于使用。即使原始代码没有用并行化编写,这个库也很容易逐步实现。我认为它是并行计算的一个很好的入口点,因为它可能使一切变得简单但是很难调试,性能有限并且它只是使代码并行(它缺乏并行)算法,结构,原语,你不能跨越网络工作。)
  • Message Passing Interface:从我的角度来看,基于此标准的库最适合跨越群集进行大量计算。如果您的计算机很少并且想要并行计算,那么这是一个很好的选择,众所周知且稳定。它(我的观点再次)不是本地并行化的解决方案。如果您正在寻找一个众所周知的大型网格计算标准,那么MPI就适合您。
  • Intel Threading Building Blocks:这是一个C ++库,用于统一跨不同环境(pthreads或Windows的线程模型)的多线程接口。如果你使用这样的库,你可能需要在编译器和环境之间移植。此外,使用此库并不限制您,因此它可以与其他东西很好地集成(例如MPI)。您应该看一下库,看看您是否喜欢,这是一个非常好的选择,设计好,文档齐全,使用广泛。
  • Microsoft Parallel Patterns Library:这是一个非常大的图书馆。它是相当新的,所以我不建议有人在没有良好测试的情况下使用它,而且它是微软特定的,因此你被绑定到它的编译器。那说我认为这是一个很棒的图书馆。它抽象了很多细节,它设计得很好,它提供了“并行任务”概念的高级视图。再次使用此库并不会阻止您使用集群的MPI(但Concurrency Runtime有自己的库)。

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

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

答案 1 :(得分:3)

考虑这是对Adriano答案的扩展评论(和扩展)。

OpenMP非常容易掌握和使用,它具有很好的功能,即串行和并行可执行文件都可以从同一个源代码生成。如果您需要将现有的串行代码转换为并行代码,它还允许您采用渐进式并行化路径。然而,OpenMP有一些缺点。首先,它仅针对严重限制其可扩展性的共享内存机器,尽管现在可以使用大型x86 SMP机器(例如,我们的QPI耦合Xeon系统具有128个CPU内核,在我们的集群安装中共享最多2 TiB的共享RAM,专门针对大型OpenMP工作)。 其次,它的编程模型太简单,无法实现一些高级概念。但我会说这是模型的优势而不是缺点,因为它保持了OpenMP的简洁。

MPI是当今传递API的事实上的标准消息。它得到广泛支持,并在各种并行体系结构上运行。它的分布式内存模型对底层硬件几乎没有任何限制(除了具有低延迟和高带宽的网络互连),这使它可以扩展到数十万个CPU内核。虽然算法本身可能不具备可移植的可伸缩性(例如,一个MPI程序可能在Blue Gene / P上非常有效地运行并且在InfiniBand集群上非常慢),但MPI程序在源级别上也是非常便携的。 MPI有一个严重的缺点 - 它的SPMD(单程序多数据)模型需要代表程序员进行很多精神分裂的思考,并且比OpenMP更难掌握。将串行算法移植到MPI绝不像OpenMP那样容易,有时需要完全重写才能实现高并行效率。也不可能采用渐进式并行化方法并轻松维护可以生成串行和并行可执行文件的代码库。 MPI有一个有趣的特性 - 因为它完全分离了在不同节点上运行的程序的不同部分,并为网络提供了一个抽象接口,它允许异构计算。若干MPI实现(例如,Open MPI)提供异构支持,其允许不仅混合在不同OS下运行的节点而且混合具有不同" bitness"的CPU。和endianness。

英特尔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进程,具有自己的虚拟地址空间,这意味着可能需要复制大量(配置)数据。 MPI人员正在努力改进标准,以允许它作为线程和MPI端点运行MPI进程"可能会在即将推出的MPI标准版本3.0中结束。

我建议选择最接近您编程背景的那个。如果你是一个狂热的C ++程序员并呼吸抽象,那么选择英特尔TBB(如果你进入.Net,则选择Microsoft PPL)。 OpenMP非常容易掌握并提供良好的性能,但在某种程度上是简单的。它仍然是在Fortran中编写多线程代码的唯一广泛可用和使用的机制。 MPI有一个陡峭的学习曲线,但如果您的程序超出单个计算节点可以提供的程度,则可以随后用螺栓固定。