MPI 是一个接口,它使我们能够创建多个进程以在单台机器或机器集群上运行,并支持消息传递或进程之间的简短通信。
我确信它们是其他许多规范,它们使多处理能够执行一项更大的任务。但是,多任务处理并将较大的任务分解为较小的任务也可以通过线程完成。据我了解,与进程相比,创建线程要快得多,并且它不需要任何消息传递来进行通信,因为共享内存是固有的。
当您可以使用多线程程序达到相同的效果时,为什么还要像 MPI 和其他规范一样进行多处理?
MPI 是一个接口,它使我们能够创建多个进程以在单台机器或机器集群上运行,并支持消息传递或进程之间的简短通信。
我确信它们是其他许多规范,它们使多处理能够执行一项更大的任务。但是,多任务处理并将较大的任务分解为较小的任务也可以通过线程完成。据我了解,与进程相比,创建线程要快得多,并且它不需要任何消息传递来进行通信,因为共享内存是固有的。
当您可以使用多线程程序达到相同的效果时,为什么还要像 MPI 和其他规范一样进行多处理?
有一个真实的和一个实际的原因。
首先,MPI 是在机器只有一个处理器内核并且我们想要耦合不同机器的时候开发的。今天,它用于由数万台机器组成的集群,每台机器都恰好有许多核心,但关键是它仍然是独立的机器。现在,机器 A 上的处理器内核无法访问机器 B 上的内存,因此需要有一种方法在这些进程之间传输信息——这就是消息传递接口 (MPI) 的根本作用:从一台机器传输数据给另一个。
你完全正确,严格来说,如果你只在一台机器上工作,你就不需要 MPI。这当然限制了您可以扩展程序的程度(您将能够使用几十个线程,但不是数千个,因为我们没有具有那么多内核的机器)。但更重要的是,当你使用线程时,你现在有几十个线程都在访问同一个内存。事实证明,编写高效的代码在概念上非常困难,因为从历史上看,我们被教导访问共享数据结构的方法是仅使用互斥锁来访问信息。如果您有 4 个内核访问相同的内存,那么这证明是有效的,但如果您有 192 个内核则不是:在这种情况下,计算信息所花费的时间与获取互斥锁所花费的时间的比率不再是很好了。解决这个问题需要做的是,每个线程在算法的主要阶段复制读写数据结构(这样就可以在没有互斥体的情况下访问它们),然后是归约步骤。换句话说,线程需要保持数据结构的单独副本以提高效率。但这不是我们的方式想想当我们用线程编程时,很少有实现采用这种策略。另一方面,当你使用 MPI 编程时,这就是你需要做的,因为每个进程都有自己的内存空间——所以 MPI迫使你做你应该用线程做的事情,这就是为什么使用 MPI 通常会导致非常高效和即使在可以使用线程的情况下使用,也可以扩展程序。
Wolfgang Bangerth 的回答是完全正确的,我只想补充一个实际的方面。
跨硬件的可移植性
假设您从头开始编写研究代码。你的部门有一台功能强大的多核共享内存机器可以完成这项工作。如果您从基于线程的实现开始,您可以在这台特定的机器上获得良好的性能。
只要您有一个固定的、明确定义的问题描述,那就没问题了。然而,实际上,你提出的每一个研究问题都会引出更多的问题。很快,您需要进行一项参数研究,使您的数字需求成倍增长,并且您的可访问硬件已经超出了您的需求。
如果您从一开始就使用 MPI,那么在另一个集群上扩展您的问题的问题就会更少,并且您不会局限于一个特定的架构。您可以在桌面、多核 SMD 机器和大学集群上启动您的代码!
MPI 解决了与多线程不同的问题,无论是通过pthreads
还是 OpenMP 完成:
多线程旨在利用单个大型机器,但仅限于那一台机器。如果您的服务器只有 64 个处理器内核,那就是最大值。可以运行的线程数量(如果您关心性能,那就是)。
MPI 旨在将应用程序扩展到单台机器之外。您可以使用您的钱可以购买的尽可能多的机器,将它们与一些(高性能)网络连接在一起,您可以执行一个 MPI 应用程序,一次使用您的整个价值数百万美元的超级计算机。
气候模拟、天气预报、物理模拟等经常使用 MPI 以如此大规模的并行方式运行。不是因为每个人都喜欢使用 MPI,而是因为您根本无法再在一台机器上运行高分辨率气候模型。这将花费太长时间,而且您根本无法将足够的 RAM 放入一台机器中。
这些是使用 MPI 优于 OpenMP 或的优点pthreads
:
安全性:经常被遗忘,但如果您没有可以竞争的共享数据,您就无法产生数据竞争。进程不共享数据,因此在为 MPI 编程时,您可以完全忘记抓取锁等。这使得对源代码的推理变得更加简单。所有通信都是显式的,任何接收都会阻塞,直到可以安全地继续。
请注意,现代 MPI 标准出于性能原因一直在加水:它们包括非阻塞发送/接收调用,以及用于远程内存访问的原语。这些在进程的内存隔离中公开了明显的漏洞。然而,即使有这些不太安全的通信,也很清楚哪些地方可以进行数据竞争,哪些地方不可以。所有的漏洞都非常明确,而且时间有限。这与多线程世界仍然有很大不同,在多线程世界中,您基本上需要在触摸内存对象时询问自己是否需要获取锁。
性能扩展:您不限于单台机器上的 CPU 内核数。
内存扩展:您可以将最大的 RAM 插入一台机器。使用 MPI,您可以将数据分散到许多较小的机器上。今天,这可能比性能扩展更重要!
最后,使用 MPI 并不意味着您不能在上面使用 OpenMP。这可以做到,而且已经完成:您在每台机器上启动少量进程,并且每个进程都使用 OpenMP 来利用可用的 CPU 内核。这称为混合并行化。它显着减少了需要通过 MPI 进行通信的数据量(提高了性能),但代价是使代码更加复杂。