try ai
科普
编辑
分享
反馈
  • 分布式内存并行

分布式内存并行

SciencePedia玻尔百科
关键要点
  • 分布式内存并行将问题划分到多个处理器上,每个处理器都有自己的私有内存,需要通过显式消息传递(例如 MPI)进行通信。
  • 有效的并行化依赖于域分解来划分问题,并通过 halo 交换来高效地在处理器之间传递边界数据。
  • 通过使用异步消息将通信与计算重叠,并利用大问题中的表面积-体积效应,可以实现高性能。
  • 该范式是贯穿不同领域的统一原则,使得在工程、人工智能、基因组学和量子计算中进行大规模模拟成为可能。

引言

要解决我们这个时代最宏大的科学和工程挑战,所需的计算能力远非任何单台计算机所能及。想象一下,拼凑一个巨大无比的拼图,需要一个专家团队,每个人都在各自的桌子上处理自己那一部分。这就是分布式内存并行的精髓,也是现代超级计算的基础范式。它所解决的核心问题意义深远:如何协调成千上万个拥有各自私有内存的独立处理器,共同解决一个统一的问题?这需要一种经过深思熟虑的、显式的协作语言。

本文将分两部分探讨这一强大的模型。首先,在“原理与机制”一章中,我们将深入探讨核心概念,从如何使用域分解来划分问题,到通过消息传递进行通信的艺术。我们将揭示诸如 halo 交换和异步调用等能够实现巨大可扩展性的策略。随后,“应用与跨学科联系”一章将展示这些基本思想如何应用于一系列令人惊叹的领域,揭示连接星系模拟、人工智能训练和救生药物设计的共同计算基因。让我们从审视那些使这场宏大的计算交响乐成为可能的原理开始。

原理与机制

想象一下,你是一个由众多杰出专家组成的庞大团队中的一员,任务是拼凑出世界上最大、最复杂的拼图。这个拼图是一张宇宙地图,而你的工作是弄清楚它的一切是如何运作的。这个拼图巨大无比,以至于所有人不可能围在一张桌子旁。于是,拼图被切割成大块,每位专家都将一块拼图带到自己的私人办公桌前。每张桌子自成一个世界,有自己的工具和参考书。这就是​​分布式内存并行​​的精髓:每个“专家”——即一个处理器或计算节点——都有自己的私有内存,自己的地址空间,其他节点无法访问。

这种设置立刻带来了这一范式的核心挑战和决定性特征。当你的拼图块依赖于邻居拼图块的形状时,会发生什么?你不能只是探过身去看。你必须进行通信。你必须停下手中的工作,写一个清晰、明确的请求,并将其作为消息发送出去。这就是​​消息传递​​,分布式内存世界中协作的基本机制。这些消息的规则和协议集合,即专家们共同商定的“语言”,通常由一个标准来规定,比如​​消息传递接口(MPI)​​。

该模型与其他并行计算方法形成对比。例如,在用于单节点加速器(如 GPU)的隐式、基于指令的模型中,程序员的工作更像是一位给出高层指令的经理,将任务分配的细节留给硬件和编译器处理。在我们这个分布式的世界里,我们自己就是专家,负责分解和通信的每一个细节。我们用拥有任意多张“办公桌”所带来的无限可扩展性,换取了共享工作空间的便利性。

切割宇宙:域分解

在任何工作开始之前,我们必须首先决定如何“切割宇宙”——即我们的计算问题。这个关键的第一步被称为​​域分解​​。

对于具有规则结构的问题,比如在均匀网格上的模拟,最直观的方法是​​几何分解​​。我们只需沿着坐标轴切割计算域,就像切蛋糕一样。例如,在使用时域有限差分(FDTD)方法模拟电磁波传播时,我们可以将一个三维点网格划分为一叠厚板,将每个厚板分配给不同的处理器。这种几何切分的目标是创建表面积最小的紧凑子域,因为正如我们将看到的,表面是通信发生的地方。

但是,如果问题不是一个简单的蛋糕呢?想象一下,使用非结构化的三角形或四面体网格来模拟一个具有复杂、不规则部件的设备。简单的几何切割可能会直接穿过一个关键组件,造成混乱的接口和不佳的工作分配。这时,需要一种更深层次的策略:​​基于图的域分解​​。我们不再关注网格的物理坐标,而是创建一个抽象图,其中每个计算任务(如一个网格单元或一个自由度)是一个节点,如果两个节点相互依赖,则用一条边连接它们。问题就变成了对这个图进行分区,以最小化“边切割”——即被切断的连接数量。这种方法是“算子感知的”;它甚至可以加权以避免切断最重要的数学耦合,这不仅减少了通信,还可以保持模拟的数值稳定性。

一旦我们决定了如何分区,就必须决定如何分配这些分块。对于某些问题,比如在计算天体物理学中求解大型稠密方程组,简单的分块划分会导致负载不均,因为一些处理器会提前完成工作而处于空闲状态。一种巧妙的折衷方案是​​二维块循环分布​​,即将矩阵切成小块,然后像发牌一样以轮循方式将这些块分发给一个二维处理器网格。这确保了每个处理器都拥有一个分散在整个域内的多样化工作组合,从而在复杂的算法(如 LU 分解)中实现出色的负载均衡和持续的性能。

跨越虚空的低语:消息传递的艺术

域分解完成后,模拟开始。每个处理器处理其子域的内部。但它不可避免地会到达边界,需要来自邻居的数据。如何高效地管理这一切?

答案是 ​​halo 交换​​。处理器不是逐点请求数据(这是一个效率极低的过程),而是与其邻居进行一次协调好的交换。每个处理器将其自身边界层单元发送给邻居,邻居接收后将其存储在一个“幽灵单元”的缓冲区中,这个缓冲区也称为 ​​halo​​。这个 halo 提供了处理器完成其边界计算所需的所有数据。对于麦克斯韦方程组的模拟,更新两个子域之间界面上的电场和磁场需要交换切向场分量,然后将这些分量存储在这些 halo 区域中以计算离散旋度算子。这个 halo 的厚度由计算模板的“作用范围”决定;如果你的计算依赖于两格远的邻居,那么你的 halo 必须至少有两格厚。

这些消息传递调用的性质至关重要。

  • ​​同步通信​​:这是最简单的形式。处理器调用一个阻塞式的 Send 或 Receive,并一直等待操作完成。这就像寄一封挂号信,并在门口等待投递确认。虽然简单,但这可能导致大量的空闲时间。更糟糕的是,如果每个处理器都决定在检查邮件之前先发信,整个系统可能会陷入​​死锁​​——每个人都在等待,而没有人接收!
  • ​​异步通信​​:一种远为优雅的解决方案是使用非阻塞调用。处理器提交一个发送或接收数据的请求,然后立即继续其他工作。它可以计算其子域的内部,这部分不依赖于通信。只有当它必须获得 halo 数据来计算其边界时,它才会暂停以检查消息是否到达。这种巧妙的技术,即​​将通信与计算重叠​​,隐藏了网络延迟,是在现代超级计算机上实现高性能的关键。

我们这个专家议会的执行模型通常是​​单程序多数据(SPMD)​​。每个处理器运行相同的可执行代码,但它们可以根据自己唯一的标识符,即它们的进程号 (rank),采取不同的路径。进程号为 0 的处理器可能负责汇总结果,而所有其他进程则执行计算。这允许灵活和独立的控制流,与 GPU 的​​单指令多线程(SIMT)​​模型形成鲜明对比,在后者中,成千上万的线程以严格的步调一致执行,任何控制流的偏差都可能导致性能下降。

规模的宏伟交响乐

为什么这种分配内存和传递消息的整个努力对于巨大的科学问题如此有效?答案在于一个优美的几何原理。

考虑一个分配给某个处理器的立方体数据块。计算工作量与块内点的数量成正比——即其​​体积​​。所需的通信量与边界上点的数量成正比——即其​​表面积​​。当我们通过解决更大的问题来增大该数据块时,其体积(L3L^3L3)的增长速度快于其表面积(L2L^2L2)。这就是著名的​​表面积-体积效应​​。对于足够大的问题,有效计算量会远远超过通信开销。这一原理是并行[算法可扩展性](@entry_id:636611)的秘诀,从地震波模拟到宇宙学模型皆是如此。

另一个关键原理是​​摊销​​。发送一条消息会产生一个固定的成本,即​​延迟​​(LLL),无论其大小如何——可以把它想象成邮政服务对任何包裹收取的基本费用。发送一百万个小包裹远比发送一个大包裹昂贵得多。因此,在有许多小更新的情况下,将这些更新在本地累积起来,并在一个更大的批次中一次性发送,效率要高得多。通过这样做,我们将固定的延迟成本摊销到多次更新上。性能建模显示,通常存在一个最佳的批次大小,这是一个在等待批次填满的时间与通信开销之间达到完美平衡的“甜蜜点”。

在现代,我们可以集两者之长。一台超级计算机是一个由节点组成的集群,而每个节点本身就是一台拥有多个共享内存的处理器核心的并行机器。这催生了​​混合并行​​方法。我们使用 MPI 来管理节点之间的粗粒度通信,并使用像 OpenMP 这样的共享内存模型来并行化每个节点内部的工作。这种“MPI+X”模型不仅优雅,而且实用,因为它可以通过消除在同一台机器上运行的 MPI 进程之间复制 halo 缓冲区的需要,从而显著减少节点上的总内存占用。

最后,宇宙不是静态的,我们的模拟也不是。在​​自适应网格加密(AMR)​​中,计算网格会动态地在“有趣的”区域增加分辨率,比如流体动力学模拟中激波周围的区域。这意味着我们精心平衡的工作负载可能很快变得不平衡。解决方案是​​动态负载均衡​​:周期性地暂停模拟,评估每个处理器上的新工作负载,并在它们之间迁移单元以恢复平衡。这是一个微妙的成本效益分析。迁移的成本必须与在模拟剩余时间内工作负载平衡所带来的性能增益相权衡。一个好的策略只有在不平衡显著且预测的未来收益超过当前开销时才会触发重新分区。

从分离内存的基本决策,到异步通信和动态重新平衡的复杂舞蹈,分布式内存并行是一个内容丰富且功能强大的范式。正是这个引擎,让我们能够构建像宇宙本身一样广阔和复杂的计算拼图,并一次一个分布式地解决它们。

应用与跨学科联系

现在我们已经可以说是深入了解了分布式内存并行的内部工作原理——如何划分问题以及如何组织通信——我们可能会倾向于认为这些只是计算机科学中枯燥、抽象的规则。事实远非如此。这些原理不仅仅是抽象的规则;它们是现代计算科学的基本语法。同样的一些思想,同样的通信和计算模式,一次又一次地出现,统一了那些表面上看起来毫无关联的领域。

这是一件了不起的事情。无论我们是在设计下一代飞机、模拟蛋白质的折叠、训练一个改变世界的人工智能,还是试图理解宇宙的诞生,我们都会发现自己面临着同样的基本挑战:我们如何分配工作?我们如何最小化处理器之间的交流?当问题本身在我们脚下不断变化时,我们如何平衡负载?让我们踏上一段旅程,探索其中一些引人入胜的应用。这趟旅程不仅将揭示并行计算的力量,还将揭示其内在的美和统一性。

数字工坊:模拟物理与工程

自计算诞生之初,我们就梦想着在投入昂贵的物理原型之前,先在数字世界中进行构建和测试。这个梦想现在已成为现实,很大程度上要归功于分布式内存并行,它使我们能够处理规模和复杂性巨大的问题。

考虑一下有限元法(FEM),这是现代工程学的支柱。如果你想知道一座桥是否会屹立不倒,或者一个飞机机翼是否能承受住压力,你就会使用 FEM。该方法涉及将物体分解为大量小的、简单的部分,或称“单元”。对于每个微小的单元,我们可以写出简单的方程,但要理解整个物体的行为,我们必须将这些方程“组装”成一个庞大的方程组,由一个全局的“刚度矩阵”表示。

在并行环境中,这种组装是“scatter-add”模式的一个优美例证。每个处理器处理自己那片区域的单元,计算它们的局部刚度矩阵。然后它将这些贡献发送出去,以加到最终的全局矩阵中。全局矩阵中一个对应于不同处理器上单元共享的点的条目,将接收到所有这些处理器的贡献。系统必须被设计成累加这些贡献,而不仅仅是覆盖它们。这正是一个并行的 scatter-add 操作,一个多名工人将其各自的成果贡献给一个共享蓝图的协作过程,确保每一份贡献都得到正确累积。这就像一个组织良好的建筑队,每个小组负责建筑的一部分,然后将其部分精确地集成到主体结构中。

一旦矩阵构建完成,我们就必须求解方程。这通常是要求最高的部分。一些算法,比如用于求解扩散问题(想象热量在金属板中扩散)的优雅的交替方向隐式(ADI)方法,提出了一些有趣的并行难题。ADI 巧妙地将一个困难的二维问题转化为一系列更简单的一维问题。如果我们将二维网格划分为水平条带,每个处理器一个,那么在 xxx 方向上的求解是完全局部且并行的。但是,当我们切换到 yyy 方向时,我们会发现每个一维问题都是一列,它贯穿了每一个处理器的域!

我们如何解决这个问题?没有唯一的答案,这正是其有趣之处。我们可以进行一次大规模的数据转置——一次数字化的 all-to-all 置换,其中每个处理器都与所有其他处理器交换数据——以将数据重新排列成垂直条带,使得 yyy 方向的求解变为局部。或者,我们可以使用更复杂的并行算法来求解分布式三对角系统,而无需移动数据。每种策略在网络延迟(启动消息的成本)和带宽(发送数据本身的成本)之间都有自己的权衡。选择取决于机器和问题的具体情况,这展示了算法与架构之间深刻的相互作用。

模拟自然,从分子到地震

宇宙是一个大规模并行的系统,所以用大规模并行计算机来模拟它也就不足为奇了。

让我们放大到分子的尺度。在分子动力学(MD)中,我们模拟数百万个原子的运动,以了解蛋白质如何折叠、药物如何与细胞相互作用,或材料如何表现。MD 模拟是一个包含两个阶段的故事。首先是力计算:对于每个原子,我们必须计算其邻居对它施加的力。这是一个复杂的相互作用网络,是*任务并行*的完美候选,其中每个成对力的计算都是一个独立的任务。然而,当多个任务试图同时将其计算出的力加到同一个原子上时,它们可能会相互干扰,产生“竞争条件”。这需要仔细的同步,使用像原子操作这样的工具来确保正确性。

第二个阶段是状态更新:一旦所有的力都已知,我们就更新每个原子的位置和速度。这一步非常简单。一个原子的更新完全独立于所有其他原子。这是一个经典的*数据并行*问题,非常适合现代处理器的 SIMD(单指令,多数据)能力。像 MD 这样的现实世界应用很少是纯粹的一种并行类型;它们是丰富的混合体。这就是为什么现代并行程序通常使用混合方法:用 MPI 在节点间分配域,用像 OpenMP 这样的共享内存模型来管理每个节点内复杂的、任务并行的力计算。

现在,让我们把视野放大到行星尺度。想象一下模拟一次地震。活动集中在破裂前沿,而周围广阔的岩石区域相对平静。在所有地方都使用高分辨率网格将是对计算资源的浪费。这就是自适应网格加密(AMR)发挥作用的地方。模拟会动态地在需要的地方增加更多细节(加密网格),在不需要的地方移除细节。

这种动态性给简单的并行方案带来了噩梦。工作负载变得不规则,并在每个时间步都在变化。一个处理器可能突然比它的邻居有更多的工作。一个刚性的数据并行循环会导致严重的负载不平衡,许多处理器处于空闲状态。解决方案是一个更灵活的、基于任务的范式。我们将整个工作流程——更新一个片区、与邻居交换数据、决定是否加密——分解成一个具有明确依赖关系的任务图。然后,一个智能的运行时调度器执行这个图,动态地将就绪的任务分配给空闲的处理器。它甚至可以在等待来自其他节点的消息时调度有用的计算,从而有效地隐藏通信延迟。这种范式将一个混乱、不规则的问题转变为一个管理精美、高效的并行计算。

新前沿:人工智能、基因组学和量子世界

分布式计算的原理不仅用于模拟物理世界;它们也是探索信息前沿本身不可或缺的工具。

如今,人工智能(AI)正成为头条新闻。训练驱动这些系统的大型语言模型是有史以来最大的计算任务之一。这是一个典型的分布式数据并行问题。庞大的训练数据集被分割到数千个 GPU 上。每个 GPU 根据其数据切片计算“梯度”——即调整模型数万亿参数的方向。但在任何 GPU 更新其模型之前,所有这些局部计算出的梯度必须被平均在一起。系统的每个部分都需要知道整体的集体智慧。

这种全局共识是通过一个精心编排的集体操作,即 all-reduce 来实现的。在一种常见的实现方式 环形 all-reduce 中,处理器被排成一个逻辑环。它们将自己的梯度数据块在环上传递,边传边累加总和,然后将最终结果在环上循环分发。这是一场规模庞大的数字方块舞。这场舞所花费的时间是一个关键瓶颈,是模型大小、处理器数量以及网络延迟和带宽的函数。通过对这种通信进行建模,我们可以理解和预测训练这些庞大模型的成本。

在生物信息学中,从数十亿个短 DNA 测序读段中组装一个基因组是另一个巨大挑战。这通常是一个多阶段的流水线,不同阶段需要不同的并行策略。第一阶段,计算所有短 DNA 子序列(k-mers)的出现次数,是一个大规模的数据重排问题。K-mers 在所有节点上生成,然后根据哈希值重新分配,这样给定 k-mer 的所有实例都会落到同一个处理器上进行计数。这是数据并行。下一阶段涉及从这些 k-mers 构建一个复杂的“德布鲁因图”,并遍历该图来重建基因组。这种图遍历是不规则和不可预测的,使其非常适合基于任务的并行。因此,一个单一的科学工作流程可以成为并行计算世界的一个缩影,需要一个包含不同技术的工具箱才能高效运作。

也许最令人费解的应用是使用经典并行计算机来模拟量子计算机。一个 NNN 量子比特系统的状态由一个包含 2N2^N2N 个复数的向量来描述。这种指数级增长是惊人的;仅仅模拟 50 个量子比特就需要存储一个超过一千万亿个元素的向量,远远超出了任何单台机器的内存。在这里,分布式内存不仅仅是一种优化;它是一种绝对的必需。状态向量被划分到数千个节点上。当模拟一个量子门操作时,它会耦合这些数字中的两个或多个。如果这些数字恰好位于不同的节点上,就必须发送一条消息。因此,经典模拟的通信模式直接反映了被模拟的量子电路的逻辑结构。从非常真实的意义上说,我们正在用今天的并行技术来描绘明天的并行技术。

算法与架构的和谐

我们已经看到,最佳的并行策略通常取决于问题的结构。但事情比这更微妙。最佳策略还关键地取决于你运行它的机器。这就是性能工程的艺术:实现算法与架构之间的和谐统一。

多级快速多极子算法(MLFMA)为这一原则提供了大师级的课程。MLFMA 是一种革命性的算法,它极大地加速了电磁学等领域问题的求解。它有几个截然不同的计算阶段。如果你有一个足够小的问题,可以放入单个大型多核服务器的内存中,那么最好的方法是使用线程的纯共享内存模型。不需要消息传递的开销。但是,如果你有一个需要多节点集群的庞大问题,每个核心一个进程的纯消息传递方法可能会因通信延迟而陷入困境。更优越的策略是混合策略:使用 MPI 在节点之间进行通信,但在每个节点内部,使用线程来协作处理本地工作负载。这减少了通信进程的数量,并允许更好的消息聚合,从而带来更高的效率。范式的选择不是绝对的;它是基于规模和硬件的务实决策。

这种与硬件的亲密关系延伸到最细微的细节,尤其是在图形处理单元(GPU)等加速器兴起的情况下。一个典型的基于 GPU 的分布式模拟面临一个关键瓶颈:将数据从一个节点上的 GPU 发送到另一个节点上的 GPU。传统的路径很繁琐:数据必须从 GPU 复制到主机 CPU 的内存,由 CPU 通过网络发送,由目标 CPU 接收,最后复制到目标 GPU。像 GPUDirect RDMA 这样的现代技术创建了一条高速“快车道”,允许 GPU 将数据直接发送到网卡,完全绕过 CPU。

即使有了这条快车道,基本的权衡依然存在。是向邻居发送许多小的 halo 交换消息更好,还是花时间将它们打包成一个大消息?许多小消息准备起来很快,但每个消息都会受到网络延迟开销的影响。一个大消息只支付一次延迟成本,但会产生打包和解包数据的开销。分析这些模型揭示了最佳的聚合策略,这是在延迟和带宽之间取得的微妙平衡,需要根据机器的具体性能特征进行定制。

一个统一的主题

从建造桥梁到组装基因组,从模拟地震到训练人工智能,一个统一的主题浮现出来。挑战是多样的,但其基本原理是相同的。我们分解问题,分配数据,并组织处理器之间的对话。我们与延迟和带宽作斗争,我们寻求平衡负载,我们努力将计算与通信重叠。分布式内存并行不仅仅是一种技术;它是现代计算发现的共同语言,使我们能够提出——并回答——那些曾经遥不可及的问题。