本节试图概述使用 Linux 的集群并行处理。集群目前是最流行且种类最多的方法,范围从传统的工作站网络 (NOW) 到本质上是定制的并行计算机,只是恰好使用 Linux PC 作为处理器节点。使用 Linux 机器集群进行并行处理也有相当多的软件支持。
集群并行处理提供了几个重要的优势
好的,集群是免费或便宜的,而且可以非常大且高度可用……为什么不是每个人都使用集群呢?嗯,也存在一些问题
ps
命令仅报告一个 Linux 系统上运行的进程,而不是跨 Linux 系统集群运行的所有进程。
因此,基本情况是集群提供了巨大的潜力,但对于大多数应用程序来说,实现这种潜力可能非常困难。好消息是有相当多的软件支持可以帮助您为非常适合这种环境的程序实现良好的性能,并且还有专门设计的网络来扩大可以实现良好性能的程序范围。
计算机网络是一个蓬勃发展的领域……但您已经知道了。越来越多的网络技术和产品正在开发中,大多数都可以应用于将一组机器(即每台都运行 Linux 的 PC)构建成并行处理集群。
不幸的是,没有一种网络技术能够最佳地解决所有问题;事实上,方法、成本和性能的范围最初令人难以置信。例如,使用标准的商用硬件,每台联网机器的成本从不到 5 美元到超过 4,000 美元不等。交付的带宽和延迟也各有四个数量级的变化。
在尝试了解特定网络之前,重要的是要认识到这些东西变化无常(请参阅 http://www.linux.org.uk/NetNews.html 以获取 Linux 网络新闻),并且很难获得关于某些网络的准确数据。
在我特别不确定的地方,我放置了一个?。我花了很多时间研究这个主题,但我确信我的总结充满了错误,并且遗漏了很多重要的东西。如果您有任何更正或补充,请发送电子邮件至 hankd@engr.uky.edu。
像 http://web.syr.edu/~jmwobus/comfaqs/lan-technology.html 上的 LAN 技术记分卡之类的摘要给出许多不同类型的网络和 LAN 标准的一些特性。但是,本 HOWTO 中的摘要侧重于与构建 Linux 集群最相关的网络属性。讨论每个网络的部分以简短的特征列表开始。以下定义了这些条目的含义。
如果答案是否,则含义非常明确。其他答案试图描述用于访问网络的基本程序接口。大多数网络硬件通过内核驱动程序进行接口,通常支持 TCP/UDP 通信。一些其他网络使用更直接的(例如,库)接口来通过绕过内核来减少延迟。
多年前,通过 OS 调用访问浮点单元被认为是完全可以接受的,但现在显然是荒谬的;在我看来,并行程序执行的处理器之间的每次通信都需要 OS 调用也是同样尴尬的。问题是计算机尚未集成这些通信机制,因此非内核方法往往存在可移植性问题。在不久的将来,您将听到更多关于这方面的信息,主要以新的 虚拟接口 (VI) 架构 http://www.viarch.org/ 的形式出现,这是一种标准化的方法,用于大多数网络接口操作绕过通常的 OS 调用层。VI 标准得到 Compaq、Intel 和 Microsoft 的支持,并且肯定会在未来几年对 SAN(系统区域网络)设计产生重大影响。
这是每个人都关心的数字。我通常使用理论上的最佳情况数字;您的里程将会有所不同。
在我看来,这是每个人都应该比带宽更关心的数字。同样,我使用了不切实际的最佳情况数字,但至少这些数字确实包括所有延迟来源,包括硬件和软件。在大多数情况下,网络延迟仅为几微秒;更大的数字反映了低效的硬件和软件接口层。
简而言之,这描述了您如何获得这种类型的网络硬件。商品化的东西可以从许多供应商处广泛获得,价格是主要的区别因素。多供应商的东西可以从多个竞争供应商处获得,但存在显着差异和潜在的互操作性问题。单供应商网络让您受制于该供应商(无论它多么仁慈)。公共领域设计意味着即使您找不到人向您出售,您或任何其他人都可以购买零件并制造一个。研究原型就是这样;它们通常既不适合外部用户,也不对他们开放。
如何连接这个网络?性能最高且现在最常见的是 PCI 总线接口卡。还有 EISA、VESA 局部总线(VL 总线)和 ISA 总线卡。ISA 最先出现,并且仍然常用于低性能卡。EISA 仍然作为许多 PCI 机器中的第二条总线存在,因此有一些卡。如今,您看不到太多 VL 的东西(尽管 http://www.vesa.org/ 会乞求不同意)。
当然,任何无需打开 PC 机箱即可使用的接口都具有一定的吸引力。IrDA 和 USB 接口的出现频率越来越高。标准并行端口 (SPP) 曾经是打印机插入的地方,但最近它作为 ISA 总线的外部扩展得到了大量使用;IEEE 1284 标准增强了这种新功能,该标准指定了 EPP 和 ECP 改进。还有旧的、可靠的、缓慢的 RS232 串口。我不知道有人使用 VGA 视频连接器、键盘、鼠标或游戏端口连接机器……差不多就是这样了。
总线是一根电线、一组电线或光纤。集线器是一个小盒子,它知道如何连接插入其中的不同电线/光纤;交换式集线器允许同时主动传输数据的多个连接。
以下是如何使用这些数字。假设不计算网络连接,购买一台 PC 用作集群中的节点需要花费 2,000 美元。添加快速以太网使每个节点的成本约为 2,400 美元;添加 Myrinet 则使成本约为 3,800 美元。如果您有大约 20,000 美元可供花费,这意味着您可以拥有 8 台通过快速以太网连接的机器,或者 5 台通过 Myrinet 连接的机器。拥有多个网络也非常合理;例如,20,000 美元可以购买 8 台通过快速以太网和 TTL_PAPERS 连接的机器。选择最有可能产生运行您的应用程序最快的集群的网络或网络集。
当您阅读到这里时,这些数字将是错误的……哎,它们可能已经错了。也可能有数量折扣、特殊优惠等。尽管如此,这里引用的价格不太可能错到导致您做出完全不合适的选择。不需要博士学位(虽然我确实有一个 ;-) 就能看出,昂贵的网络只有在您的应用程序需要其特殊属性或集群的 PC 相对昂贵时才有意义。
既然您已经了解了免责声明,那就继续展示吧……
ARCNET 是一种局域网,主要用于嵌入式实时控制系统。与以太网类似,该网络在物理上组织为总线上的抽头或一个或多个集线器,但是,与以太网不同,它使用基于令牌的协议在逻辑上将网络构建为环。数据包标头很小(3 或 4 个字节),消息可以携带少至单个字节的数据。因此,ARCNET 比以太网产生更一致的性能,具有有界延迟等。不幸的是,它比以太网慢且不太流行,因此价格更贵。更多信息可从 ARCNET 贸易协会 http://www.arcnet.com/ 获得。
除非您在过去几年里一直处于昏迷状态,否则您可能已经听说了很多关于 ATM(异步传输模式)是未来的信息……好吧,有点像。ATM 比 HiPPI 便宜,比快速以太网更快,并且可以用于电话公司关心的非常远的距离。ATM 网络协议还旨在提供更低开销的软件接口,并更有效地管理小型消息和实时通信(例如,数字音频和视频)。它也是 Linux 当前支持的最高带宽网络之一。坏消息是 ATM 并不便宜,并且供应商之间仍然存在一些兼容性问题。Linux ATM 开发的概述可在 http://lrcwww.epfl.ch/linux-atm/ 获得。
CAPERS(并行执行和快速同步的电缆适配器)是 PAPERS 项目 http://garage.ecn.purdue.edu/~papers/ 的衍生项目,该项目位于普渡大学电气与计算机工程学院。本质上,它定义了一个软件协议,用于使用普通的“LapLink”SPP 到 SPP 电缆为两台 Linux PC 实现 PAPERS 库。这个想法不可扩展,但您无法击败价格。与 TTL_PAPERS 一样,为了提高系统安全性,建议但不强制使用次要内核补丁:http://garage.ecn.purdue.edu/~papers/giveioperm.html。
多年来,10 Mb/s 以太网一直是标准网络技术。好的以太网接口卡可以以远低于 50 美元的价格购买,并且现在相当多的 PC 主板上都内置了以太网控制器。对于轻度使用的网络,以太网连接可以组织为没有集线器的多抽头总线;这种配置可以服务多达 200 台机器,成本极低,但不适用于并行处理。添加非交换式集线器实际上无助于提高性能。但是,可以为同步连接提供全带宽的交换式集线器每个端口仅需约 100 美元。Linux 支持各种各样的以太网接口,但重要的是要记住,接口硬件的变化可能会导致显着的性能差异。有关支持哪些以及它们的工作效果如何的评论,请参阅硬件兼容性 HOWTO;另请参阅 http://cesdis1.gsfc.nasa.gov/linux/drivers/。
NASA CESDIS 的 Beowulf 项目 http://cesdis.gsfc.nasa.gov/linux/beowulf/beowulf.html 中完成的 16 机 Linux 集群工作提供了一种有趣的性能改进方法。在那里,许多以太网卡驱动程序的作者 Donald Becker 开发了对跨多个相互镜像的以太网网络(即,共享相同的网络地址)进行负载共享的支持。这种负载共享内置于标准 Linux 发行版中,并在套接字操作级别以下不可见地完成。由于集线器成本很高,因此让每台机器连接到两个或多个无集线器或非交换式集线器以太网网络可能是提高性能的一种非常经济有效的方法。事实上,在网络性能瓶颈是一台机器的情况下,使用镜像网络进行负载共享比使用单个交换式集线器网络效果更好。
虽然实际上有相当多的不同技术自称为“快速以太网”,但该术语最常指的是基于集线器的 100 Mb/s 以太网,它在某种程度上与较旧的“10 BaseT”10 Mb/s 设备和电缆兼容。正如可能预期的那样,任何称为以太网的东西通常都以批量市场定价,并且这些接口通常只是 155 Mb/s ATM 卡价格的一小部分。问题在于,让一堆机器共享单个 100 Mb/s“总线”的带宽(使用非交换式集线器)所产生的性能平均而言甚至可能不如使用具有交换式集线器的 10 Mb/s 以太网好,后者可以为每台机器的连接提供完整的 10 Mb/s。
可以同时为每台机器提供 100 Mb/s 的交换式集线器价格昂贵,但价格每天都在下降,并且这些交换机确实比非交换式集线器产生更高的总网络带宽。使 ATM 交换机如此昂贵的原因是它们必须为每个(相对较短的)ATM 信元进行交换;一些快速以太网交换机利用预期的较低交换频率,使用可能通过交换机具有低延迟的技术,但需要几毫秒才能更改交换路径……如果您的路由模式频繁更改,请避免使用这些交换机。有关各种卡和驱动程序的信息,请参阅 http://cesdis1.gsfc.nasa.gov/linux/drivers/。
另请注意,如以太网所述,NASA 的 Beowulf 项目 http://cesdis.gsfc.nasa.gov/linux/beowulf/beowulf.html 一直在开发通过跨多个快速以太网进行负载共享来提供改进性能的支持。
我不确定千兆以太网 http://www.gigabit-ethernet.org/ 是否有充分的技术理由被称为以太网……但这个名称确实准确地反映了这样一个事实,即这旨在成为一种廉价、大众市场、计算机网络技术,并具有对 IP 的原生支持。但是,当前定价反映了这样一个事实,即 Gb/s 硬件仍然是一件棘手的事情。
与其他以太网技术不同,千兆以太网提供了一定程度的流量控制,这应该使其成为更可靠的网络。FDR 或全双工中继器只是复用线路,使用缓冲和本地化流量控制来提高性能。大多数交换式集线器都作为现有千兆位交换矩阵的新接口模块构建。至少 http://www.acacianet.com/、http://www.baynetworks.com/、http://www.cabletron.com/、http://www.networks.digital.com/、http://www.extremenetworks.com/、http://www.foundrynet.com/、http://www.gigalabs.com/、http://www.packetengines.com/、http://www.plaintree.com/、http://www.prominet.com/、http://www.sun.com/ 和 http://www.xlnt.com/ 等公司已经发货或宣布了交换机/FDR 产品。
Packet Engines “Yellowfin”G-NIC http://www.packetengines.com/ 有一个 Linux 驱动程序 http://cesdis.gsfc.nasa.gov/linux/drivers/yellowfin.html。Linux 下的早期测试实现了比最好的 100 Mb/s 快速以太网高约 2.5 倍的带宽;对于千兆位网络,仔细调整 PCI 总线的使用是关键因素。毫无疑问,驱动程序改进以及其他 NIC 的 Linux 驱动程序将会随之而来。
FC(光纤通道)的目标是提供高性能块 I/O(一个 FC 帧携带 2,048 字节的数据负载),特别是用于共享可以直接连接到 FC 而不是通过计算机连接的磁盘和其他存储设备。从带宽方面来看,FC 被指定为相对较快,运行速度在 133 到 1,062 Mb/s 之间。如果 FC 作为高端 SCSI 替代品而流行起来,它可能会很快成为一种廉价技术;就目前而言,它并不便宜,并且 Linux 不支持它。光纤通道协会维护了 FC 参考资料的良好集合,网址为 http://www.amdahl.com/ext/CARP/FCA/FCA.html
FireWire http://www.firewire.org/,IEEE 1394-1995 标准,注定将成为消费电子产品的低成本高速数字网络。展示的应用是将 DV 数字摄像机连接到计算机,但 FireWire 旨在用于从作为 SCSI 替代品到互连家庭影院组件的各种应用。它允许使用总线和桥接器以任何拓扑结构连接多达 64K 个设备,而不会创建环路,并在添加或删除组件时自动检测配置。支持短(四字节“四字”)低延迟消息以及类似 ATM 的等时传输(用于保持多媒体消息同步)。Adaptec 拥有 FireWire 产品,允许将多达 63 个设备连接到单个 PCI 接口卡,并且还在 http://www.adaptec.com/serialio/ 提供了良好的通用 FireWire 信息。
虽然 FireWire 不会是可用的最高带宽网络,但消费级市场(应该会降低价格)和低延迟支持可能会使其在未来一年左右成为最佳的 Linux PC 集群消息传递网络技术之一。
HiPPI(高性能并行接口)最初旨在为超级计算机和另一台机器(超级计算机、帧缓冲区、磁盘阵列等)之间传输海量数据集提供非常高的带宽,并且已成为超级计算机的主导标准。虽然这是一个矛盾修辞,但 串行 HiPPI 也越来越流行,通常使用光纤电缆代替 32 位宽标准(并行)HiPPI 电缆。在过去几年中,HiPPI 交叉开关变得很常见,价格也大幅下降;不幸的是,串行 HiPPI 仍然很昂贵,而这通常是 PCI 总线接口卡支持的。更糟糕的是,Linux 尚不支持 HiPPI。CERN 在 http://www.cern.ch/HSI/hippi/ 维护了 HiPPI 的良好概述;他们还在 http://www.cern.ch/HSI/hippi/procintf/manufact.htm 维护了相当长的 HiPPI 供应商列表。
IrDA(红外数据协会,http://www.irda.org/)是很多笔记本电脑侧面的那个小红外设备。使用此接口本质上很难连接两台以上的机器,因此不太可能用于集群。Don Becker 曾对 IrDA 做了一些初步工作。
Myrinet http://www.myri.com/ 是一种局域网 (LAN),旨在也充当“系统区域网络”(SAN),即,连接为并行系统的机器柜内的网络。LAN 和 SAN 版本使用不同的物理介质,并且具有略有不同的特性;通常,SAN 版本将在集群内使用。
Myrinet 结构相当传统,但以实施得特别好而闻名。据说 Linux 的驱动程序性能非常好,尽管据报道,对于主机计算机的不同 PCI 总线实现,性能变化惊人地大。
目前,Myrinet 显然是不太受“预算挑战”的集群组最喜欢的网络。如果您的 Linux PC 概念是高端奔腾 Pro 或奔腾 II,至少具有 256 MB RAM 和 SCSI RAID,那么 Myrinet 的成本是相当合理的。但是,使用更普通的 PC 配置,您可能会发现您的选择是在 Myrinet 连接的 N 台机器或多个快速以太网和 TTL_PAPERS 连接的 2N 台机器之间。这实际上取决于您的预算以及您最关心的计算类型。
卡尔斯鲁厄大学信息学系的 ParaStation 项目 http://wwwipd.ira.uka.de/parastation 正在构建与 PVM 兼容的自定义低延迟网络。他们首先使用自定义 EISA 卡接口和运行 BSD UNIX 的 PC 构建了一个双处理器 ParaPC 原型,然后使用 DEC Alpha 构建了更大的集群。自 1997 年 1 月以来,ParaStation 已可用于 Linux。PCI 卡正在与一家名为 Hitex 的公司合作制造(请参阅 http://www.hitex.com:80/parastation/)。Parastation 硬件实现了快速、可靠的消息传输和简单的屏障同步。
仅需一根“LapLink”电缆的成本,PLIP(并行线路接口协议)允许两台 Linux 机器通过标准并行端口使用标准基于套接字的软件进行通信。就带宽、延迟和可扩展性而言,这不是一种非常严肃的网络技术;但是,近乎零成本和软件兼容性非常有用。该驱动程序是标准 Linux 内核发行版的一部分。
SCI(可扩展一致性互连,ANSI/IEEE 1596-1992)的目标本质上是提供一种高性能机制,可以支持跨大量机器的一致性共享内存访问,以及各种类型的块消息传输。可以肯定地说,与大多数其他网络技术相比,SCI 的设计带宽和延迟都“非常棒”。问题在于 SCI 作为廉价的生产单元并未广泛可用,并且没有任何 Linux 支持。
SCI 主要用于各种专有设计中,用于逻辑共享的物理分布式内存机器,例如 HP/Convex Exemplar SPP 和 Sequent NUMA-Q 2000(请参阅 http://www.sequent.com/)。但是,SCI 可以作为 PCI 接口卡和 4 路交换机(通过级联四个 4 路交换机最多可以连接 16 台机器)从 Dolphin http://www.dolphinics.com/ 获得,作为他们的 CluStar 产品线。CERN 在 http://www.cern.ch/HSI/sci/sci.html 维护了一组概述 SCI 的良好链接。
SCSI(小型计算机系统互连)本质上是一种用于磁盘驱动器、CD ROM、图像扫描仪等的 I/O 总线。有三个独立的标准 SCSI-1、SCSI-2 和 SCSI-3;快速和超快速;以及 8、16 或 32 位的数据路径宽度(SCSI-3 中也提到了 FireWire 兼容性)。这一切都非常令人困惑,但我们都知道,好的 SCSI 比 EIDE 稍快,并且可以更有效地处理更多设备。
许多人没有意识到的是,两台计算机共享单个 SCSI 总线非常简单。这种类型的配置对于在机器之间共享磁盘驱动器和实现 故障转移 非常有用 - 当另一台机器发生故障时,由一台机器接管数据库请求。目前,这是 Microsoft 的 PC 集群产品 WolfPack 支持的唯一机制。但是,无法扩展到更大的系统使得共享 SCSI 对于一般的并行处理来说毫无意义。
ServerNet 是 Tandem 公司的高性能网络硬件,http://www.tandem.com。尤其在在线事务处理 (OLTP) 领域,Tandem 以其高可靠性系统而闻名,因此他们的网络声称不仅具有高性能,而且还具有“高数据完整性和可靠性”也就不足为奇了。ServerNet 另一个有趣的方面是,它声称能够将数据从任何设备直接传输到任何设备;不仅在处理器之间,而且还在磁盘驱动器等设备之间,采用类似于第 3.5 节中描述的 MPI 远程内存访问机制所建议的单边方式。关于 ServerNet 的最后一点评论:虽然只有一个供应商,但该供应商实力强大,有可能将 ServerNet 确立为主要标准... Tandem 已被康柏公司收购。
SHRIMP 项目,http://www.CS.Princeton.EDU/shrimp/,在普林斯顿大学计算机科学系正在构建一台使用运行 Linux 的 PC 作为处理单元的并行计算机。第一个 SHRIMP(可扩展、高性能、真正廉价的多处理器)是一个简单的双处理器原型,在定制的 EISA 卡接口上使用双端口 RAM。现在有一个原型,它将扩展到更大的配置,使用定制的接口卡连接到“hub”,该“hub”本质上与 Intel Paragon 中使用的网状路由网络相同(参见 http://www.ssd.intel.com/paragon.html)。已经投入了大量精力来开发低开销的“虚拟内存映射通信”硬件和支持软件。
虽然 SLIP(串行线路接口协议)牢牢地位于性能频谱的低端,但 SLIP(或 CSLIP 或 PPP)允许两台机器通过普通的 RS232 串行端口执行套接字通信。RS232 端口可以使用空调制解调器 RS232 串行电缆连接,甚至可以通过调制解调器拨号连接。无论如何,延迟很高,带宽很低,因此只有在没有其他替代方案时才应使用 SLIP。然而,值得注意的是,大多数 PC 都有两个 RS232 端口,因此可以通过简单地将机器连接成线性阵列或环形来联网一组机器。甚至还有名为 EQL 的负载共享软件。
PAPERS(普渡大学并行执行和快速同步适配器)项目,http://garage.ecn.purdue.edu/~papers/,在普渡大学电气与计算机工程学院正在构建可扩展、低延迟、聚合函数通信硬件和软件,这些硬件和软件允许使用未经修改的 PC/工作站作为节点来构建并行超级计算机。
已经构建了十几种不同类型的 PAPERS 硬件,这些硬件通过 SPP(标准并行端口)连接到 PC/工作站,大致遵循两条开发路线。名为“PAPERS”的版本针对更高的性能,使用任何适当的技术;目前的工作使用 FPGA,并且高带宽 PCI 总线接口设计也在开发中。相比之下,名为“TTL_PAPERS”的版本旨在易于在普渡大学以外复制,并且是非常简单的公共领域设计,可以使用普通的 TTL 逻辑构建。其中一种设计已商业化生产,http://chelsea.ios.com:80/~hgdietz/sbm4.html。
与来自其他大学的定制硬件设计不同,TTL_PAPERS 集群已在美国到韩国的许多大学组装。带宽受到 SPP 连接的严重限制,但 PAPERS 实现了极低延迟的聚合函数通信;即使是最快的面向消息的系统也无法在这些聚合函数上提供可比的性能。因此,PAPERS 特别适合同步视频墙的显示(将在即将推出的视频墙 HOWTO 中进一步讨论)、调度对高带宽网络的访问、评估遗传搜索中的全局适应度等。虽然 PAPERS 集群已使用 IBM PowerPC AIX、DEC Alpha OSF/1 和 HP PA-RISC HP-UX 机器构建,但基于 Linux 的 PC 是最佳支持的平台。
使用 TTL_PAPERS AFAPI 的用户程序直接访问 Linux 下的 SPP 硬件端口寄存器,而无需为每次访问调用 OS。为此,AFAPI 首先使用 iopl()
或 ioperm()
获取端口权限。这些调用的问题在于,两者都要求用户程序具有特权,从而产生潜在的安全漏洞。解决方案是一个可选的内核补丁,http://garage.ecn.purdue.edu/~papers/giveioperm.html,允许特权进程控制任何进程的端口权限。
USB(通用串行总线,http://www.usb.org/)是一个热插拔的、传统以太网速度的总线,最多可连接 127 个外围设备,范围从键盘到视频会议摄像头。尚不清楚多台计算机如何使用 USB 相互连接。无论如何,USB 端口正迅速成为 PC 主板上的标准配置,就像 RS232 和 SPP 一样,因此如果下一台您购买的 PC 背面潜伏着一两个 USB 端口,请不要感到惊讶。Linux 驱动程序的开发在 http://peloncho.fis.ucm.es/~inaky/USB.html 中讨论。
在某些方面,USB 几乎是您今天可以购买的低性能、零成本版本的 FireWire。
WAPERS(并行执行和快速同步的线与适配器)是 PAPERS 项目的衍生项目,http://garage.ecn.purdue.edu/~papers/,在普渡大学电气与计算机工程学院。如果正确实现,SPP 具有四个集电极开路输出位,这些位可以在机器之间连接在一起以实现 4 位宽的线与。这种线与在电气上很敏感,并且可以以这种方式连接的最大机器数量关键取决于端口的模拟特性(最大吸电流和上拉电阻值);通常,最多可以通过 WAPERS 连接 7 或 8 台机器。虽然成本和延迟非常低,但带宽也很低;WAPERS 更适合作为聚合操作的辅助网络,而不是集群中唯一的网络。与 TTL_PAPERS 一样,为了提高系统安全性,建议但不强制使用一个小的内核补丁:http://garage.ecn.purdue.edu/~papers/giveioperm.html。
在继续讨论并行应用程序的软件支持之前,首先简要介绍一下网络硬件的底层软件接口的基础知识非常有用。实际上只有三种基本选择:套接字、设备驱动程序和用户级库。
到目前为止,最常见的底层网络接口是套接字接口。套接字已经成为 unix 的一部分十多年了,大多数标准网络硬件都设计为至少支持两种类型的套接字协议:UDP 和 TCP。这两种类型的套接字都允许您将任意大小的数据块从一台机器发送到另一台机器,但它们之间存在几个重要的差异。通常,两者都会产生大约 1,000 微秒的最小延迟,尽管性能可能会因网络流量而变得更差。
这些套接字类型是大多数可移植的、更高级别的并行处理软件的基本网络软件接口;例如,PVM 使用 UDP 和 TCP 的组合,因此了解差异将有助于您调整性能。为了获得更好的性能,您还可以直接在程序中使用这些机制。以下只是 UDP 和 TCP 的简单概述;有关详细信息,请参阅手册页和优秀的网络编程书籍。
UDP 是用户数据报协议,但您可以更轻松地记住 UDP 的属性,即不可靠数据报处理。换句话说,UDP 允许将每个块作为单独的消息发送,但消息可能会在传输中丢失。实际上,根据网络流量,UDP 消息可能会丢失、多次到达或以与发送顺序不同的顺序到达。UDP 消息的发送者不会自动收到确认,因此检测和补偿这些问题取决于用户编写的代码。幸运的是,UDP 确实确保如果消息到达,则消息内容是完整的(即,您永远不会只收到 UDP 消息的一部分)。
UDP 的优点是它往往是最快的套接字协议。此外,UDP 是“无连接”的,这意味着每条消息本质上都独立于所有其他消息。一个很好的类比是,每条消息都像一封要邮寄的信;您可能会向同一个地址发送多封信,但每封信都独立于其他信件,并且您可以向多少人发送信件没有限制。
与 UDP 不同,TCP 是一种可靠的、基于连接的协议。发送的每个块不被视为消息,而是被视为通过发送者和接收者之间连接传输的字节连续流中的数据块。这与 UDP 消息传递非常不同,因为每个块只是字节流的一部分,并且由用户代码来弄清楚如何从字节流中提取每个块;没有标记分隔消息。此外,连接在网络问题方面更加脆弱,并且每个进程可以同时存在的连接数量有限。由于 TCP 是可靠的,因此通常意味着比 UDP 显着更多的开销。
然而,关于 TCP 也有一些令人惊喜的事情。其中之一是,如果通过连接发送多条消息,TCP 能够将它们打包到缓冲区中,以更好地匹配网络硬件数据包大小,从而可能为短消息或大小不规则的消息组产生比 UDP 更好的性能。另一个好处是,使用机器之间可靠的直接物理链路构建的网络可以轻松有效地模拟 TCP 连接。例如,ParaStation 的“Socket Library”接口软件就是这样做的,它使用用户级调用提供 TCP 语义,这些用户级调用与标准 TCP OS 调用的不同之处仅在于每个函数名称添加了前缀 PSS
。
当实际将数据推送到网络或从网络拉取数据时,标准的 unix 软件接口是 unix 内核的一部分,称为设备驱动程序。UDP 和 TCP 不仅传输数据,它们还意味着相当多的套接字管理开销。例如,有些东西必须管理多个 TCP 连接可以共享单个物理网络接口的事实。相比之下,专用网络接口的设备驱动程序只需要实现几个简单的数据传输功能。然后,用户程序可以使用 open()
来标识正确的设备,然后使用诸如 read()
和 write()
之类的系统调用对打开的“文件”进行操作来调用这些设备驱动程序功能。因此,每个这样的操作都可以传输一个数据块,其开销仅比系统调用的开销稍多,系统调用可能快至几十微秒。
编写用于 Linux 的设备驱动程序并不难......如果您精确地知道设备硬件的工作原理。如果您不确定它是如何工作的,请不要猜测。调试设备驱动程序并不有趣,错误可能会烧毁硬件。但是,如果这没有吓退您,那么可能可以编写一个设备驱动程序,例如,使用专用的以太网卡作为哑但快速的机器到机器的直接连接,而没有通常的以太网协议开销。事实上,这在很大程度上是早期英特尔超级计算机所做的……有关更多信息,请查看设备驱动程序 HOWTO。
如果您参加过操作系统课程,那么用户级访问硬件设备寄存器正是您被教导永远不要做的事情,因为操作系统的主要目的之一是控制设备访问。但是,操作系统调用至少有几十微秒的开销。对于像 TTL_PAPERS 这样的定制网络硬件,它可以在短短 3 微秒内执行基本网络操作,这种操作系统调用开销是无法容忍的。避免这种开销的唯一方法是让用户级代码(用户级库)直接访问硬件设备寄存器。因此,问题变成用户级库如何直接访问硬件,又不损害操作系统对设备访问权限的控制。
在典型的系统中,用户级库直接访问硬件设备寄存器的唯一方法是
mmap()
调用(在第 2.6 节中首次提到)来映射表示 I/O 设备物理内存页地址的特殊文件。或者,编写设备驱动程序来执行此功能相对简单。此外,此设备驱动程序可以通过仅映射包含所需特定设备寄存器的页面来控制访问,从而维护操作系统访问控制。*((char *) 0x1234) = 5;
会将字节值 5 存储到内存位置 1234(十六进制)。幸运的是,事实证明,用于 Intel 386(和兼容处理器)的 Linux 提供了更好的解决方案
ioperm()
操作系统调用,获取访问与设备寄存器对应的精确 I/O 端口地址的权限。或者,可以使用独立的特权用户进程(即“元操作系统”)使用 giveioperm() 操作系统调用 补丁来管理权限。
第二种解决方案更可取,因为常见的情况是多个 I/O 设备的寄存器位于单个页面内,在这种情况下,第一种技术将无法防止访问碰巧与预期寄存器位于同一页面中的其他设备寄存器。当然,缺点是 386 端口 I/O 指令不能用 C 语言编写 - 相反,您需要使用一些汇编代码。用于字节值端口输入的 GCC 包装(可在 C 程序中使用)内联汇编代码函数是
extern inline unsigned char inb(unsigned short port) { unsigned char _v; __asm__ __volatile__ ("inb %w1,%b0" :"=a" (_v) :"d" (port), "0" (0)); return _v; }
同样,用于字节端口输出的 GCC 包装代码是
extern inline void outb(unsigned char value, unsigned short port) { __asm__ __volatile__ ("outb %b0,%w1" :/* no outputs */ :"a" (value), "d" (port)); }
PVM(并行虚拟机)是一个免费提供的、可移植的消息传递库,通常在套接字之上实现。它已明确确立为消息传递集群并行计算的事实标准。
PVM 支持单处理器和 SMP Linux 机器,以及由支持套接字的联网(例如,SLIP、PLIP、以太网、ATM)连接的 Linux 机器集群。事实上,PVM 甚至可以在不同类型的处理器、配置和物理网络被使用的机器组之间工作 - 异构集群 - 甚至可以达到将互联网连接的机器视为并行集群的规模。PVM 还提供跨集群的并行作业控制设施。最重要的是,PVM 长期以来都是免费提供的(目前来自 http://www.epm.ornl.gov/pvm/pvm_home.html),这导致许多编程语言编译器、应用程序库、编程和调试工具等都将其用作其“可移植消息传递目标库”。还有一个网络新闻组,comp.parallel.pvm。
然而,重要的是要注意,PVM 消息传递调用通常会为标准套接字操作增加显着的开销,而标准套接字操作已经具有高延迟。此外,消息处理调用本身并不构成特别“友好”的编程模型。
使用在第 1.3 节中首次描述的相同 Pi 计算示例,使用 C 语言和 PVM 库调用的版本是
#include <stdlib.h> #include <stdio.h> #include <pvm3.h> #define NPROC 4 main(int argc, char **argv) { register double lsum, width; double sum; register int intervals, i; int mytid, iproc, msgtag = 4; int tids[NPROC]; /* array of task ids */ /* enroll in pvm */ mytid = pvm_mytid(); /* Join a group and, if I am the first instance, iproc=0, spawn more copies of myself */ iproc = pvm_joingroup("pi"); if (iproc == 0) { tids[0] = pvm_mytid(); pvm_spawn("pvm_pi", &argv[1], 0, NULL, NPROC-1, &tids[1]); } /* make sure all processes are here */ pvm_barrier("pi", NPROC); /* get the number of intervals */ intervals = atoi(argv[1]); width = 1.0 / intervals; lsum = 0.0; for (i = iproc; i<intervals; i+=NPROC) { register double x = (i + 0.5) * width; lsum += 4.0 / (1.0 + x * x); } /* sum across the local results & scale by width */ sum = lsum * width; pvm_reduce(PvmSum, &sum, 1, PVM_DOUBLE, msgtag, "pi", 0); /* have only the console PE print the result */ if (iproc == 0) { printf("Estimation of pi is %f\n", sum); } /* Check program finished, leave group, exit pvm */ pvm_barrier("pi", NPROC); pvm_lvgroup("pi"); pvm_exit(); return(0); }
虽然 PVM 是事实上的标准消息传递库,但 MPI(消息传递接口)是相对较新的官方标准。MPI 标准的主页是 http://www.mcs.anl.gov:80/mpi/,新闻组是 comp.parallel.mpi。
然而,在讨论 MPI 之前,我觉得有必要稍微谈谈过去几年一直在进行的 PVM 与 MPI 的宗教战争。我实际上不站在任何一边。以下是我对差异的相对公正的总结尝试
简而言之,PVM 有一个,而 MPI 没有指定如何/是否实现一个。因此,启动 PVM 程序执行之类的操作在任何地方都是相同的,而对于 MPI,则取决于正在使用的实现。
PVM 在工作站周期回收利用的世界中成长起来,因此直接管理机器和操作系统的异构混合。相比之下,MPI 在很大程度上假设目标是 MPP(大规模并行处理器)或几乎相同的专用工作站集群。
PVM 证明了 MPI 2.0 所不具备的统一目标。新的 MPI 2.0 标准包含许多超出基本消息传递模型的功能 - 诸如 RMA(远程内存访问)和并行文件 I/O 之类的东西。这些东西有用吗?当然有用……但学习 MPI 2.0 很像学习一种全新的编程语言。
MPI 是在 PVM 之后设计的,显然从中吸取了教训。MPI 提供了更简单、更高效的缓冲区处理和更高级别的抽象,允许在消息中传输用户定义的数据结构。
据我统计,仍然有明显更多设计为使用 PVM 的东西,而不是使用 MPI 的东西;但是,将它们移植到 MPI 很容易,并且 MPI 以广泛支持的正式标准为后盾的事实意味着,对于许多机构而言,使用 MPI 是政策问题。
结论?好吧,至少有三个独立开发的、免费提供的 MPI 版本可以在 Linux 系统集群上运行(我写了一个)
无论使用这些(或其他)MPI 实现中的哪一个,执行最常见的通信类型都相当简单。
然而,MPI 2.0 包含了几种通信范例,这些范例在根本上差异足够大,以至于使用其中一种范例的程序员甚至可能无法将其他编码风格识别为 MPI。因此,与其给出一个示例程序,不如给出 MPI 支持的每种根本不同的通信范例的示例。所有三个程序都实现了相同的基本算法(来自第 1.3 节),该算法在整个 HOWTO 中用于计算 Pi 的值。
第一个 MPI 程序使用基本的 MPI 消息传递调用,以便每个处理器将其部分和发送到处理器 0,处理器 0 对结果求和并打印
#include <stdlib.h> #include <stdio.h> #include <mpi.h> main(int argc, char **argv) { register double width; double sum, lsum; register int intervals, i; int nproc, iproc; MPI_Status status; if (MPI_Init(&argc, &argv) != MPI_SUCCESS) exit(1); MPI_Comm_size(MPI_COMM_WORLD, &nproc); MPI_Comm_rank(MPI_COMM_WORLD, &iproc); intervals = atoi(argv[1]); width = 1.0 / intervals; lsum = 0; for (i=iproc; i<intervals; i+=nproc) { register double x = (i + 0.5) * width; lsum += 4.0 / (1.0 + x * x); } lsum *= width; if (iproc != 0) { MPI_Send(&lbuf, 1, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD); } else { sum = lsum; for (i=1; i<nproc; ++i) { MPI_Recv(&lbuf, 1, MPI_DOUBLE, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &status); sum += lsum; } printf("Estimation of pi is %f\n", sum); } MPI_Finalize(); return(0); }
第二个 MPI 版本使用集体通信(对于这个特定的应用程序,这显然是最合适的)
#include <stdlib.h> #include <stdio.h> #include <mpi.h> main(int argc, char **argv) { register double width; double sum, lsum; register int intervals, i; int nproc, iproc; if (MPI_Init(&argc, &argv) != MPI_SUCCESS) exit(1); MPI_Comm_size(MPI_COMM_WORLD, &nproc); MPI_Comm_rank(MPI_COMM_WORLD, &iproc); intervals = atoi(argv[1]); width = 1.0 / intervals; lsum = 0; for (i=iproc; i<intervals; i+=nproc) { register double x = (i + 0.5) * width; lsum += 4.0 / (1.0 + x * x); } lsum *= width; MPI_Reduce(&lsum, &sum, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD); if (iproc == 0) { printf("Estimation of pi is %f\n", sum); } MPI_Finalize(); return(0); }
第三个 MPI 版本使用 MPI 2.0 RMA 机制,以便每个处理器将其本地 lsum
添加到处理器 0 上的 sum
中
#include <stdlib.h> #include <stdio.h> #include <mpi.h> main(int argc, char **argv) { register double width; double sum = 0, lsum; register int intervals, i; int nproc, iproc; MPI_Win sum_win; if (MPI_Init(&argc, &argv) != MPI_SUCCESS) exit(1); MPI_Comm_size(MPI_COMM_WORLD, &nproc); MPI_Comm_rank(MPI_COMM_WORLD, &iproc); MPI_Win_create(&sum, sizeof(sum), sizeof(sum), 0, MPI_COMM_WORLD, &sum_win); MPI_Win_fence(0, sum_win); intervals = atoi(argv[1]); width = 1.0 / intervals; lsum = 0; for (i=iproc; i<intervals; i+=nproc) { register double x = (i + 0.5) * width; lsum += 4.0 / (1.0 + x * x); } lsum *= width; MPI_Accumulate(&lsum, 1, MPI_DOUBLE, 0, 0, 1, MPI_DOUBLE, MPI_SUM, sum_win); MPI_Win_fence(0, sum_win); if (iproc == 0) { printf("Estimation of pi is %f\n", sum); } MPI_Finalize(); return(0); }
值得注意的是,MPI 2.0 RMA 机制非常巧妙地克服了各种处理器上相应数据结构位于不同内存位置的任何潜在问题。这是通过引用一个“窗口”来完成的,该“窗口”暗示了基地址、防止越界访问,甚至地址缩放。RMA 处理可能会延迟到下一个 MPI_Win_fence
,这有助于高效实现。总之,RMA 机制可能是分布式共享内存和消息传递之间的一种奇怪的混合体,但它是一个非常干净的接口,有可能产生非常高效的通信。
与 PVM、MPI 等不同,AFAPI(聚合函数应用程序编程接口)的诞生并非试图构建一个分层在现有网络硬件和软件之上的可移植抽象接口。相反,AFAPI 最初是 PAPERS(普渡大学并行执行和快速同步适配器;参见 http://garage.ecn.purdue.edu/~papers/)的非常特定于硬件的底层支持库。
PAPERS 在第 3.2 节中简要讨论过;它是一个公共领域设计的定制聚合函数网络,可提供低至几微秒的延迟。然而,关于 PAPERS 的重要之处在于,它的开发是为了构建一台超级计算机,该超级计算机将比现有超级计算机更适合编译器技术。这与大多数 Linux 集群工作和 PVM/MPI 在质量上不同,后者通常侧重于尝试将标准网络用于相对较少的足够粗粒度的并行应用程序。Linux PC 被用作 PAPERS 系统的组件仅仅是以最具成本效益的方式实现原型的产物。
在十几种不同的原型实现中需要一个通用的底层软件接口,这使得 PAPERS 库标准化为 AFAPI。然而,AFAPI 使用的模型本质上更简单,更适合并行编译器编译的代码或为 SIMD 架构编写的代码的更细粒度的交互。该模型的简单性不仅使 PAPERS 硬件易于构建,而且还为各种其他硬件系统(例如 SMP)产生了出奇高效的 AFAPI 端口。
AFAPI 目前在连接使用 TTL_PAPERS、CAPERS 或 WAPERS 的 Linux 集群上运行。它还使用名为 SHMAPERS 的 System V 共享内存库在 SMP 系统上运行(无需 OS 调用,甚至无需总线锁定指令,请参阅第 2.2 节)。一个在传统网络(例如,以太网)上使用 UDP 广播跨 Linux 集群运行的版本正在开发中。所有发布的版本都可以从 http://garage.ecn.purdue.edu/~papers/ 获得。所有版本的 AFAPI 都设计为从 C 或 C++ 调用。
以下示例程序是第 1.3 节中描述的 Pi 计算的 AFAPI 版本。
#include <stdlib.h> #include <stdio.h> #include "afapi.h" main(int argc, char **argv) { register double width, sum; register int intervals, i; if (p_init()) exit(1); intervals = atoi(argv[1]); width = 1.0 / intervals; sum = 0; for (i=IPROC; i<intervals; i+=NPROC) { register double x = (i + 0.5) * width; sum += 4.0 / (1.0 + x * x); } sum = p_reduceAdd64f(sum) * width; if (IPROC == CPROC) { printf("Estimation of pi is %f\n", sum); } p_exit(); return(0); }
除了 PVM、MPI 和 AFAPI 之外,以下库还提供了一些功能,这些功能可能在使用 Linux 系统集群进行并行计算时很有用。本文档对这些系统进行了较轻的处理,仅仅是因为与 PVM、MPI 和 AFAPI 不同,我在 Linux 集群上使用这些系统几乎没有或根本没有直接经验。如果您发现这些或其他库特别有用,请发送电子邮件至 hankd@engr.uky.edu 描述您的发现,我将考虑添加关于该库的扩展部分。
Condor 是一个分布式资源管理系统,可以管理大型异构工作站集群。其设计受到希望利用此类集群的未利用容量来执行长时间运行、计算密集型作业的用户的需求驱动。Condor 在执行机器上保留了很大程度上源机器的环境,即使源机器和执行机器不共享公共文件系统和/或密码机制。由单个进程组成的 Condor 作业会自动进行检查点操作,并在工作站之间迁移,以确保最终完成。
Condor 可在 http://www.cs.wisc.edu/condor/ 获得。存在 Linux 端口;更多信息可在 http://www.cs.wisc.edu/condor/linux/linux.html 获得。有关详细信息,请联系 condor-admin@cs.wisc.edu。
DFN-RPC(德国研究网络远程过程调用)工具的开发是为了在工作站和计算服务器或集群之间分发和并行化科学技术应用程序。该接口针对用 fortran 编写的应用程序进行了优化,但 DFN-RPC 也可在 C 环境中使用。它已被移植到 Linux。更多信息请访问 ftp://ftp.uni-stuttgart.de/pub/rus/dfn_rpc/README_dfnrpc.html。
DQS 3.0(分布式排队系统)不是一个库,而是一个作业排队系统,它已在 Linux 下开发和测试。它旨在允许将异构集群的使用和管理作为一个单一实体。它可从 http://www.scri.fsu.edu/~pasko/dqs.html 获得。
还有一个名为 CODINE 4.1.1(分布式网络环境中的计算)的商业版本。有关它的信息可从 http://www.genias.de/genias_welcome.html 获得。
由于集群可以以如此多种不同的方式构建和使用,因此有很多团队做出了有趣的贡献。以下是各种与集群相关的项目的参考资料,这些项目可能具有普遍意义。这包括 Linux 特定的和通用集群参考资料的混合。列表按字母顺序排列。
Beowulf 项目,http://cesdis1.gsfc.nasa.gov/beowulf/,专注于生产用于使用基于商用 PC 级硬件、高带宽集群内部网络和 Linux 操作系统构建的现成集群工作站的软件。
Thomas Sterling 一直是 Beowulf 背后的驱动力,并且继续成为 Linux 集群在科学计算领域普遍应用的雄辩而直言不讳的倡导者。事实上,许多团队现在将其集群称为“Beowulf 类”系统 - 即使该集群实际上与官方 Beowulf 设计并没有那么相似。
Don Becker 在支持 Beowulf 项目的工作中,生产了 Linux 通用使用的许多网络驱动程序。这些驱动程序中的许多甚至已被改编用于 BSD。Don 还负责许多这些 Linux 网络驱动程序,这些驱动程序允许跨多个并行连接进行负载共享,以在没有昂贵的交换式集线器的情况下实现更高的带宽。这种类型的负载共享是 Beowulf 集群最初的显着特征。
Linux/AP+ 项目,http://cap.anu.edu.au/cap/projects/linux/,并非完全关于 Linux 集群,而是专注于将 Linux 移植到 Fujitsu AP1000+ 并添加适当的并行处理增强功能。AP1000+ 是一种商用 SPARC 架构的并行机器,它使用具有环形拓扑结构、25 MB/s 带宽和 10 微秒延迟的定制网络……简而言之,它看起来很像 SPARC Linux 集群。
Locust 项目,http://www.ecsl.cs.sunysb.edu/~manish/locust/,正在构建一个分布式虚拟共享内存系统,该系统使用编译时信息来隐藏消息延迟并减少运行时网络流量。Pupa 是 Locust 的底层通信子系统,并使用以太网在 FreeBSD 下连接 486 PC。Linux?
Midway,http://www.cs.cmu.edu/afs/cs.cmu.edu/project/midway/WWW/HomePage.html,是一个基于软件的 DSM(分布式共享内存)系统,与 TreadMarks 类似。好消息是它使用编译时辅助而不是相对缓慢的页面错误机制,并且它是免费的。坏消息是它不在 Linux 集群上运行。
MOSIX 修改了 BSDI BSD/OS,以在联网的 PC 组之间提供动态负载平衡和抢占式进程迁移。这对于并行处理以及通常将集群用作可扩展 SMP 来说都是好东西。会有 Linux 版本吗?有关更多信息,请访问 http://www.cs.huji.ac.il/mosix/。
伯克利 NOW(工作站网络)项目,http://now.cs.berkeley.edu/,引领了使用工作站网络进行并行计算的潮流。这里正在进行大量工作,所有工作都旨在“在未来几年内演示一个实用的 100 处理器系统”。可惜的是,他们不使用 Linux。
使用 Linux WWW 站点进行并行处理,http://aggregate.org/LDP/,是本 HOWTO 和许多相关文档的主页,包括为期一整天教程的在线幻灯片。除了 PAPERS 项目的工作之外,普渡大学电气与计算机工程学院通常一直是并行处理领域的领导者;建立此站点的目的是帮助其他人将 Linux PC 应用于并行处理。
自从普渡大学的第一个 Linux PC 集群于 1994 年 2 月组装完成以来,普渡大学已经组装了许多 Linux PC 集群,包括几个带有视频墙的集群。虽然这些集群使用了 386、486 和奔腾系统(没有奔腾 Pro 系统),但英特尔最近向普渡大学捐赠了一笔款项,这将使其能够构建多个大型奔腾 II 系统集群(计划单个集群最多可达 165 台机器)。虽然这些集群都拥有/将拥有 PAPERS 网络,但大多数集群也拥有传统的网络。
1997 年 4 月 10 日至 11 日,AMES 实验室在爱荷华州得梅因市举办了奔腾 Pro 集群研讨会。本次研讨会的 WWW 站点,http://www.scl.ameslab.gov/workshops/PPCworkshop.html,包含了从所有与会者那里收集的大量 PC 集群信息。
DSM(分布式共享内存)是一种技术,通过该技术,消息传递系统可以表现得像 SMP 一样。有很多这样的系统,其中大多数系统使用操作系统页面错误机制来触发消息传输。TreadMarks,http://www.cs.rice.edu/~willy/TreadMarks/overview.html,是其中效率较高的系统之一,并且可以在 Linux 集群上运行。坏消息是“TreadMarks 以少量成本分发给大学和非营利机构。” 有关该软件的更多信息,请联系 treadmarks@ece.rice.edu。
康奈尔大学的 U-Net(用户级网络接口架构)项目,http://www2.cs.cornell.edu/U-Net/Default.html,试图通过虚拟化网络接口来提供低延迟和高带宽,以便应用程序可以在没有操作系统干预的情况下发送和接收消息,从而使用商品网络硬件。U-Net 在 Linux PC 上运行,使用基于 DECchip DC21140 的快速以太网卡或 Fore Systems PCA-200(不是 PCA-200E)ATM 卡。
威斯康星州确实有很多与集群相关的工作。WWT(威斯康星风洞)项目,http://www.cs.wisc.edu/~wwt/,正在努力开发编译器和底层并行硬件之间的“标准”接口。还有威斯康星 COW(工作站集群)、协同共享内存和 Tempest、Paradyn 并行性能工具等。不幸的是,关于 Linux 的内容不多。