使用 MPICH 构建小型私有 Beowulf 集群

作者:Stan Blank

在 2001 年春季,我的学生和我使用 MPICH 1.2.2.2(MPI 库的一种实现)和 Red Hat 6.2 在韦恩城高中计算机科学实验室构建了一个 Beowulf 集群。在此之前,我们没有人有任何严肃的 Linux 经验,最初只是心血来潮的一个项目,后来发展成为每个参与者一次认真的学习经历。我们第一次集群经验的成功成果发表在了 Beowulf Underground 上。自从我们的故事发表以来,我收到了来自世界各地的许多电子邮件,要求我详细描述我们是如何构建集群的。我的标准答案是像我们一样进行研究,但随着时间的推移,我意识到我真的应该为我们自己以及其他人的利益写下我们的方法论。

我们是伊利诺伊州南部一所小型乡村高中。即便如此,在过去的 20 年里,我们一直开设计算机科学作为一门正式课程,从最初的一台 Commodore VIC-20 发展到目前在拥有 200 名学生的学校中拥有 100 多台计算机的规模。然而,Linux 对我们来说只是另一个词,直到去年我们开始了这个项目。在事情开始步入正轨之前的几周里,经常听到诸如“root 到底是谁?”和“tar 是什么东西?”之类的短语。我们是自学成才的,不得不学习双启动、网络、X、rsh 以及任何其他似乎在最不合时宜的时候突然出现的主题的奥秘。这并非全是乐趣,但从教育的角度来看,这个过程肯定是 rewarding 的。今年秋天,我们的行政部门和学校董事会批准我们购买新的计算机硬件,这使我们来到了现在。

我们的新 Beowulf 集群由八个系统的私有网络组成,这些系统在 Windows 2000 Professional 和 Red Hat 7.1 之间双启动。每台计算机都配备了单个 AMD 1.4GHz Athlon 处理器、512MB 内存、30GB 硬盘、64MB NVIDIA 显卡和 100Mb 以太网以及交换式集线器(我说过我们的行政部门和学校董事会对我们很慷慨吗?)。我们正在使用当前版本的 MPICH (1.2.2.3) 作为我们的 MPI 库。

我们为什么选择 MPICH?当我们决定构建集群并开始研究时,我们发现了三种可能的集群系统:MPI、MOSIX 和 PVM。我们第一次尝试集群涉及 MOSIX。它的“fork and forget”理念似乎很理想(因为我们真的不知道自己在做什么),并且 MOSIX 声称可以与现有软件一起工作。我们没有意识到的是,为了使 MOSIX 正常工作,我们将不得不下载并编译一个 vanilla 内核。对于完全是业余爱好者的我们来说,这似乎是一项艰巨的任务,因此我们拒绝了 MOSIX。我们曾短暂考虑过 PVM,但我们所做的一些研究表明(正确与否)MPI 在易用性和性能方面对我们来说是更好的选择。最终,我们决定使用 MPICH 实现的 MPI,因为它的价格(免费)、易于安装(本文的主题)和可编程性(未来文章的主题?)。

使用 MPICH 1.2.2.3 分步构建集群

首先组装硬件。如果只有一台计算机可用,MPICH 允许您使用单台计算机模拟集群。本文稍后将简要讨论如何进行单计算机集群。现在,我假设您至少有两台带有可用网卡的计算机。在韦恩城,我们成功构建了由两到十六台计算机组成的集群。使用两台计算机,您可以使用简单的交叉线缆连接网卡。如果计算机超过两台,您将需要集线器或交换机来连接系统。

可以混合和匹配系统。在我们最初的集群工作中,在我们确定由 16 台 300MHz Celeron 计算机(配备 10Mbps 以太网和集线器)组成的同构实验室之前,我们有各种型号的奔腾、赛扬和移动奔腾系统协同工作。我们当前的集群保留了这种同构结构,使用 AMD Athlon 处理器和 100Mb 以太网以及交换式集线器。我还成功地将我的 Dell Inspiron 8000 笔记本电脑连接到我们的新集群,尽管与 1.4GHz AMD Athlon 相比,它的 1GHz Intel 处理器有点慢。然而,观看 Dell 笔记本电脑从另外八个 CPU 的组合功能中受益仍然很有趣。

我们使用和试验的所有计算机都是完整的独立系统,配有显示器、硬盘、键盘等。可以使用裸网络 CPU 机箱和带有显示器和键盘的单个主节点构建集群,但我们没有尝试构建这样的怪兽。此外,我们还没有机会混合和匹配其他类型的系统,例如 SGI、SPARC 或 Alpha 工作站(尽管我们很欢迎这个机会——任何想要捐赠旧设备的人都可以直接与我联系)。

接下来,在集群中的每台计算机上安装 Linux 发行版(以下,我们将它们称为节点)。我们当前集群正在使用 Red Hat 7.1,并且对其性能感到满意。

在安装过程中,为集群中的每个节点分配合理的主机名和唯一的 IP 地址。通常,一个节点被指定为主节点(您将在其中控制集群、编写和运行程序等),所有其他节点用作计算从节点。我们将我们的节点命名为 node00 到 node07 以保持简单,使用 node00 作为我们的主节点。我们的集群是私有的,因此理论上我们可以为我们的节点分配任何有效的 IP 地址,只要每个地址都具有唯一值即可。我们为主节点使用了 IP 地址 192.168.100.200,并为每个从节点添加了一个地址(192.168.100.201 等)。如果您的集群中的每个节点上都已经安装了 Linux,那么您不必更改 IP 地址或主机名,除非您想更改。可以使用您的网络配置程序(我个人偏爱 Red Hat 中的 Linuxconf)进行更改(如果需要)。最后,在每个节点上创建相同的用户帐户。在我们的例子中,我们在集群中的每个节点上创建了用户 beowulf。您可以在安装期间创建相同的用户帐户,也可以使用 root 用户的 adduser 命令。

然后在集群中的每个节点上配置 rsh。我们使用 rsh 有两个原因:首先,rsh 看起来比 ssh 更容易配置,而且由于我们拥有一个具有可信用户的私有网络,因此安全不是问题;其次,据我所知,rsh 没有加密的额外开销,因此其集群性能应该比 ssh 快一点。

作为新手用户,rsh 最初有点问题,尤其是在 Red Hat 7.1 中。每次我们尝试连接到另一个节点时,都会提示我们输入密码。最后,在互联网上搜索了很久之后,我们才找到一种似乎对我们有效的方法。从教育的角度来看,我们希望从用户和 root 用户的角度安装 MPICH,因此我们将 rsh 配置为允许用户和 root 用户访问。然而,我们的方法,即使 Linux 安全专家对此感到反感,也是如下所示

在用户和 root 目录中创建 .rhosts 文件。我们的 beowulf 用户的 .rhosts 文件如下所示

node00  beowulf
node01  beowulf
node02  beowulf
node03  beowulf
node04  beowulf
node05  beowulf
node06  beowulf
node07  beowulf

root 用户的 .rhosts 文件如下所示

node00  root
node01  root
node02  root
node03  root
node04  root
node05  root
node06  root
node07  root

接下来,我们在 /etc 目录中创建了一个 hosts 文件。下面是我们的 node00(主节点)的 hosts 文件

192.168.100.200 node00.home.net node00
127.0.0.1               localhost
192.168.100.201 node01
192.168.100.202 node02
192.168.100.203 node03
192.168.100.204 node04
192.168.100.205 node05
192.168.100.206 node06
192.168.100.207 node07

同样,我们的网络是私有的,因此我们使用了以 192.168 开头的 IP 地址,并编造了其余部分。集群中的每个节点都有一个类似的 hosts 文件,第一行进行了适当的更改以反映该节点的主机名。例如,node01 的第一行将是

192.168.100.201    node01.home.net  node01

第三行包含 node00 的 IP 和主机名。所有其他节点都以相同的方式配置。不要删除 127.0.0.1 localhost 行(正如我们通过惨痛教训发现的那样)。通过在每个节点上的 hosts.allow 文件中添加 ALL+ 作为文件中的唯一行来修改这些文件。这允许任何节点上的任何人连接到我们私有集群中的任何其他节点。为了允许 root 用户使用 rsh,我们必须将以下行添加到 /etc/securetty 文件中

rsh, rlogin, rexec, pts/0, pts/1

。此外,我们修改了 /etc/pam.d/rsh 文件

#%PAM-1.0
# For root login to succeed here with pam_securetty, "rsh" must be
# listed in /etc/securetty.
auth       sufficient   /lib/security/pam_nologin.so
auth       optional     /lib/security/pam_securetty.so
auth       sufficient   /lib/security/pam_env.so
auth       sufficient   /lib/security/pam_rhosts_auth.so
account    sufficient   /lib/security/pam_stack.so service=system-auth
session    sufficient   /lib/security/pam_stack.so service=system-auth

最后,经过大量研究,我们发现 rsh、rlogin、Telnet 和 rexec 在 Red Hat 7.1 中默认禁用。要更改此设置,我们导航到 /etc/xinetd.d 目录并修改每个命令文件(rsh、rlogin、telnet 和 rexec),将 disabled = yes 行更改为 disabled = no

对每个文件进行更改(并保存)后,我们关闭编辑器并发出以下命令:xinetd -restart 以启用 rsh、rlogin 等。然后我们就可以正常使用了,不再出现 rsh 密码提示。

接下来,从 www-unix.mcs.anl.gov/mpi/mpich/download.html 将最新版本的 MPICH(UNIX 所有版本)下载到主节点(我们集群中的 node00)。该文件大约为 9.5MB,您可能应该在下载时获取安装说明和其他文档。您永远不知道安装指南何时可能有用。

在公共用户目录(您为我们集群上的所有节点“beowulf”建立的相同用户)或 root 目录中解压该文件(如果您想以 root 用户身份运行集群)。发出命令:tar zxfv mpich.tar.gz(或您的 MPICH 版本的 tar 文件名),将创建 mpich-1.2.2.3 目录,其中包含所有子目录。如果您使用的 MPICH 版本比我们更新,则最后一个数字可能与我们的不同。

切换到新创建的 mpich-1.2.2.3 目录。务必阅读 README 文件(如果存在),但在我们的经验中,configure 和 make 脚本无需修改即可工作。键入 ./configure,当配置完成并且您有命令提示符时,键入 make

make 可能需要几分钟时间,具体取决于您的主计算机的速度。make 完成后,将 mpich-1.2.2.3/bin 和 mpich-1.2.2.3/util 目录添加到 .bash_profile 中的 PATH 中,或者以您设置路径环境变量语句的任何方式添加。我们主节点上 MPICH bin 和 util 目录的完整 root 路径是 /root/mpich-1.2.2.3/util 和 /root/mpich-1.2.2.3/bin。对于我们集群上的 beowulf 用户,路径语句中的 /root 替换为 /home/beowulf。注销然后登录以启用包含 MPICH 目录的修改后的 PATH。

在 mpich-1.2.2.3 目录中,转到 util/machines/ 目录并找到 machines.LINUX 文件。此文件将包含集群中所有节点的主机名。当您首次查看该文件时,您会注意到您正在使用的计算机的主机名的五个副本将位于该文件中。对于我们集群上的 node00,machines.LINUX 文件中将有五个 node00 的副本。如果您只有一台计算机可用,请保持此文件不变,您将能够在单台计算机上运行 MPI/MPICH 程序。否则,删除这五行,并为您集群中的每个节点添加一行主机名,但您正在使用的节点除外。对于我们的集群,从 node00(主节点)查看的 machines.LINUX 文件如下所示

node01
node02
node03
node04
node05
node06
node07

然后制作所有示例文件和 MPE 图形文件。首先,导航到 mpich-1.2.2.3/examples/basic 目录并键入 make 以制作所有基本示例文件。当此过程完成后,您不妨更改为 mpich-1.2.2.3/mpe/contrib 目录并制作一些额外的 MPE 示例文件,特别是如果您想查看图形。在 mpe/contrib 目录中,您应该看到几个子目录。我们(目前——您可以自行探索其他目录)感兴趣的是 mandel 目录。更改为 mandel 目录,然后键入 make 以创建 pmandel exec 文件。您现在可以测试您的集群了。

运行测试程序

我将描述如何运行两个测试程序作为开始。您可以从那时起自行探索。我们将运行的第一个程序是 cpilog。在 mpich-1.2.2.3/examples/basic 目录中,将 cpilog exec 文件(如果此文件不存在,请尝试再次键入 make)复制到您的顶层目录。在我们的集群上,这要么是 /root(如果我们以 root 用户身份登录),要么是 /home/beowulf(如果我们以 beowulf 用户身份登录)(我们在这两个位置都安装了 MPICH)。然后,从您的顶层目录,使用 rcp 将 cpilog 文件复制到集群中的每个节点,将该文件放置在每个节点上的相应目录中。例如,如果我以 beowulf 用户身份登录到主节点,我将发出 rcp cpilog node01:/home/beowulf 以将 cpilog 复制到 node01 上的 beowulf 目录。我对每个节点都执行相同的操作(我确信脚本可以简化此操作)。如果我想以 root 用户身份运行程序,那么我会将 cpilog 文件复制到集群中所有节点的 root 目录。

文件复制完成后,我将从我的主节点的顶层目录键入以下内容来测试我的集群

mpirun -np 1 cpilog

这将运行主节点上的 cpilog 程序,以查看程序是否正常工作。某些 MPI 程序至少需要两个处理器 (-np 2),但 cpilog 仅使用一个处理器即可工作。输出如下所示

pi is approximately 3.1415926535899406,
Error is 0.0000000000001474
Process 0 is running on node00.home.net
wall clock time = 0.360909

现在尝试所有八个节点(或您想尝试的任意数量的节点),方法是键入:mpirun -np 8 cpilog,您将看到

pi is approximately 3.1415926535899406,
Error is 0.0000000000001474
Process 0 is running on node00.home.net
Process 1 is running on node01.home.net
Process 2 is running on node02.home.net
Process 3 is running on node03.home.net
Process 4 is running on node04.home.net
Process 5 is running on node05.home.net
Process 6 is running on node06.home.net
Process 7 is running on node07.home.net
wall clock time = 0.0611228

或类似的内容。根据您的 machines.LINUX 文件和节点之间的网络通信速度,“Process x is running on nodexx”行可能不是按数字顺序排列的。但是,您应该能够注意到的是,随着根据挂钟时间添加节点,执行速度会提高。如果您只有一台计算机可用,您可以使用相同的方式使用 mpirun,但每个进程将仅在主节点上运行。-np 参数后面的数字对应于您想在运行程序中使用的处理器(节点)的数量。此数字可能不超过 machines.LINUX 文件中列出的计算机数量加一(主节点未在 machines.LINUX 文件中列出)。

要查看一些图形,我们必须运行 pmandel 程序。将 pmandel exec 文件(从 mpich-1.2.2.3/mpe/contrib/mandel 目录)复制到您的顶层目录,然后复制到每个节点(就像您对 cpilog 所做的那样)。然后,如果 X 尚未运行,请发出 startx 命令。从命令控制台,键入 xhost + 以允许任何节点使用您的 X 显示,然后按如下方式设置您的 DISPLAY 变量:DISPLAY=node00:0(请务必将 node00 替换为您的主节点的主机名)。设置 DISPLAY 变量会将所有图形输出定向到您的主节点。通过键入以下内容运行 pmandel:mpirun -np 2 pmandel

pmandel 程序至少需要两个处理器才能正确运行。您应该在主节点上看到呈现的 Mandelbrot 集。

Using MPICH to Build a Small Private Beowulf Cluster

图 1. 在主节点上呈现的 Mandelbrot 集

您可以使用鼠标绘制一个框并放大到集合中(如果您愿意)。添加更多处理器 (mpirun -np 8 pmandel) 应该会显着提高渲染速度。mandelbrot 集图形已被划分为小矩形,以便由各个节点进行渲染。您实际上可以看到节点正在工作,因为矩形正在填充。如果一个节点有点慢,那么来自该节点的矩形将是最后一个填充的。观看它非常有趣。我们还没有找到优雅地退出此程序的方法,只能按 Ctrl-C 或单击窗口中的关闭框。您可能需要多次执行此操作才能杀死所有节点。pmandel 的一个选项是将 cool.points 文件从原始 mandel 目录复制到与 pmandel 相同的顶层目录(在主节点上),并运行 mpirun -np 8 pmandel -i cool.points

-i 选项将 cool.points 作为脚本运行,并呈现一个不错的 mandelbrot 幻灯片。如果您愿意,可以使用 cool.points 文件作为模型来创建您自己的显示序列。

您可以使用 make 在 mpich-1.2.2.3/mpe/contrib 子目录中创建其他示例图形和测试文件。将 exec 文件放置在所有节点的顶层目录中,并像使用 cpilog 和 pmandel 程序一样使用 mpirun。

g_Life 程序的执行方式与 pmandel 程序略有不同。您能解释一下为什么增加节点数量实际上可能会降低其性能吗?

我们注意到的一个有趣的情况(并且无法解释)是,当我们以 root 用户身份登录时,集群运行速度大约快 10%。如果原始性能是一个问题,那么集群速度的这种提高可能很重要。

最后,当我在完成本文时,我正在全力以赴地运行集群,并发现当我的学生在每个节点上进行 OpenGL/GLUT 项目时,我可以使用所有八个节点(主节点加七个从节点)。我没有注意到集群性能下降,学生们也不知道我正在从他们的各自机器上窃取计算机时间。MPICH 在集群环境中可以很好地进行多任务处理。

故障排除

我们遇到的最常见错误是硬件问题。确保所有线缆都已插入,并且每个节点都可以通过 rsh(或 ssh,如果您愿意)与所有其他节点“对话”。另一个常见错误是未能将所有集群节点包含在 machines.LINUX 文件中。最后,确保每个节点都包含当前 exec 文件(您尝试运行的程序)的副本,该副本位于顶层用户目录中。如果所有其他方法都失败了,请阅读文档。有许多很棒的用户组和网站致力于集群。使用您喜欢的搜索引擎,键入“beowulf cluster”并开始搜索!

结论

本文的目的是给出我们用于构建最新 Beowulf 集群的分步方法。它并非旨在作为 MPICH 或 MPI 的入门指南。您应该准备好阅读文档和 MPICH 目录中的所有 README 文件,以获取有关如何从 MPICH 和您的集群中获得最大收益的提示和说明。我们觉得我们从集群冒险中学到了很多东西。我毫不怀疑我的学生已经准备好迎接更雄心勃勃的项目,包括编写我们自己的基于 MPI 的程序,并最终实现分布式图形。学习不应该这么有趣!

资源

Beowulf 项目Beowulf UndergroundMPICH

Stan Blank,博士,在韦恩城高中教授化学、物理和计算机科学。问题和意见可以发送至 sblank@accessus.net

电子邮件:sblank@accessus.net

加载 Disqus 评论