MPI集群环境搭建

我在前面两篇博客中简要介绍了为什么要并行计算以及MPI的一些学习心得,接下来我们正式开始MPI的学习之路。我们知道MPI是分布式内存编程,所以这篇博客会详细讲解MPI集群环境的搭建过程。

一、准备工作

  1. 选择Linux版本:这里我选择的是Ubuntu14.04,其他Linux版本如CentOS、Fedora等操作类似,一些命令和配置文件路径会有一些差别。
  2. 物理服务器集群和虚拟节点选择:我是用VMware创建多个虚拟机来进行集群模拟,后期我会把环境部署到实验室的服务器集群上,基本操作应该是一样的,如果有需要注意的地方,我会在后续的博客中进行说明。
  3. 在VMware中安装Ubuntu14.04,实验模拟安装两个节点即可。建议初始设置时用户名取一样的,因为后面每个虚拟机节点之间免密登录时需要保证用户名一致,这样可以避免出现未知的问题。

二、安装MPICH

到MPICH官网下载源码包,解压、配置、编译、安装即可。
MPI集群环境搭建
上图是我VMware的一些文件夹的命名,受电脑配置限制,我创建了两个节点,如图左边所示,节点名称是node1和node2。我将mpich-3.2.tar.gz压缩包放在了mpi_install路径下,mpi_share是节点之间的共享目录,后面会说明。
首先,解压mpich-3.2.tar.gz:tar -zxvf ./mpich-3.2.tar.gz。
解压后的文件夹中有个README文件,打开后有详细的安装步骤,这里我简要说明:

  • 为避免错误,在安装MPICH之前,分别执行以下命令:sudo apt-get update(保证安装的源最新)、sudo apt-get install gcc(安装gcc编译器,用于编译C语言)、sudo apt-get install g++(安装g++编译器,用于编译C++)、sudo apt-get install gfortran(安装gfortran编译器,用于编译fortran语言)。
  • 进入源码包解压后的路径,执行如下命令:cat /etc/shells
    (1)如果显示为:/bin/sh 和 /bin/bash,则配置、编译和安装命令分别为:
    配置:
    ./configure 2>&1 | tee c.txt
    编译:
    make 2>&1 | tee m.txt
    安装:
    make install |& tee mi.txt
    配置和编译时间较长,安装路径及一些配置可以设置,不清楚的可以参考linux下软件的不同安装方式,可以参考以下博客:linux下软件安装
    (2)如果显示为:/bin/csh 和 /bin/tcsh,则配置、编译和安装命令分别为:
    配置:
    ./configure |& tee c.txt
    编译:
    make |& tee m.txt
    安装:
    make install |& tee mi.txt

安装结束后,用which mpicc和which mpiexec检查安装是否成功,如果有这两个可执行程序的路径显示,则表示安装成功。注意:如果自行选择安装路径的话,记得设置环境变量,具体README文档中有详细说明。这里希望大家注意一个问题,如果设置环境变量的话,~/.bashrc配置文件下的环境变量和切换sudo执行时的环境变量不同,sudo执行时会找不到命令。关于配置文件的介绍,可以参考下面文章:linux环境变量配置文件区别
在每个节点中安装MPICH,方法同上。建议每个节点中安装路径相同,统一命名(虽然安在不同的位置也可以,只要保证找到执行命令即可,但为了后期开发方便以及赏心悦目的原则,我们还是专业一点好)。

三、SSH免密登录

1.网络环境配置(网络搭建和ip地址设置)
分别配置两台机器的hosts文件,在此之前先通过ip addr showifconfig命令查看两台机器的IP地址,我的IP地址为:
node1:192.168.36.145
node2:192.168.36.146
然后修改hosts文件:
sudo gedit /etc/hosts
根据以上查得的IP地址,在两台机器的hosts文件中均输入以下内容并保存:
192.168.36.145 node1
192.168.36.146 node2
此时,两个节点间应该可以互相ping通(node1 ping node2)。
注意:虚拟机中每个机器的ip会自动分配发生变化,我们可以手动设置为固定ip(Ubuntu可以参考以下文章:Ubuntu固定ip)。
2.SSH免密登录
(1)在每个节点安装SSH服务(远程登录服务):sudo apt-get install ssh (有些版本Ubuntu安装过程中可能会出现问题,安装错误提示一步一步搜索即可解决问题)。
(2)各节点生成私钥和公钥
ssh-****** -t rsa // 生成的钥匙文件在 ~/.ssh/下,其他linux版本如CentOS路径会有所不同
cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys //认证(执行该步后可以保证本机免密登录,使用ssh node1进行测试)
(3)把各子节点的 id_rsa.pub 传到主节点
scp id_rsa.pub [email protected]:~/.ssh/id_rsa.pub.node2(这里我们把node1看作主节点,将node2节点的钥匙文件传到node1上)
(4)在主节点上操作
cat ~/.ssh/id_rsa.pub.node2 >> ~/.ssh/authorized_keys//认证
scp authorized_keys [email protected]:~/.ssh/authorized_keys//将认证文件传回每个子节点
(5)验证无密码登录
在node1节点上执行:ssh node2
关于SSH免密登录谈谈我的个人理解:因为MPI是分布式内存编程,在后面的开发中涉及节点间信息的传递,往往数据和程序是在一个节点上,所以需要保证执行命令时各节点之间信息的交换。设置SSH免密登录可以免去操作中密码的输入。各节点生成私钥和公钥后需要认证,此时可以保证本机免密登录。将各个子节点的公钥文件发送给主节点,然后分别加入到主节点的认证文件中,此时可以保证主节点对各个子节点的免密登录。最后将认证文件传回到每个子节点,从而保证各个子节点对其他节点之间的免密登录。

四、建立和挂载NFS共享目录

前面几步我们安装了MPICH和实现了SSH免密登录,如果要执行程序的话,需要保证每个节点的相同目录中都生成可执行文件,该操作方式比较繁琐,为解决该问题,我们可以采用建立共享目录的方案。
(1)在所有节点中建立相同路径下的相同目录:mkdir /home/mpi_share
(2)安装NFS,不同的Linux安装和启动NFS的命令可能不同,在ubuntu14.04中,命令为:sudo apt-get install nfs-kernel-server,另外还需要安装sudo apt-get install portmapsudo apt-get install rpcbind(这里安装如果出现问题的话,根据提示搜索可以解决问题)。
(3)设置NFS服务器,选取一个节点作为服务器,即编写程序的虚拟机,当在此台虚拟机的共享目录编写程序并编译后会将共享目录中的所有文件同步到其它虚拟机中(NFS客户端):sudo vi /etc/exportssudo gedit /etc/exports,打开文件后,在文件的最后附件上所有同步的客户端的虚拟机的ip和权限,如下:
/home/mpi_share 192.168.36.145 (rw,sync,no_root_squash,no_subtree_check)
/home/mpi_share 192.168.36.146 (rw,sync,no_root_squash,no_subtree_check)
其中/home/mpi_share是共享目录,ip地址是所有的客户端(其它节点)的地址,包括本机的,后面括号中的是权限,具体含义可上网查阅(rw即读写权限)。
(4)重启NFS,sudo /etc/init.d/nfs-kernel-server restart,此时,NFS服务器虚拟机配置完毕。
(5)接下来需要配置其它NFS客户端虚拟机,使其能共享NFS服务器的共享目录:在其他节点中运行sudo mount -t nfs 192.168.36.145:/home/mpi_share /home/mpi_share,其中ip为NFS服务器的地址,:后面跟的是服务器的共享目录,在后面跟的是本机(客户端)的共享同步目录。此时,所有的共享目录便配置完毕了(每次节点启动时都需重新执行挂载命令,如果想开机自动挂载:把上述指令sudo mount -t nfs 192.168.36.145:/home/mpi_share /home/mpi_share 写到 /etc/rc.local 文件中)。
(6)测试:在NFS服务器端的共享目录建立一个文件gedit test.c并保存,几秒钟后检查其他节点中是否在共享目录中产生了该文件,若产生则配置成功。
建立和挂载NFS共享目录的目的是保证主节点生成的可执行文件和需要的数据其他节点可以访问,这样就可以保证多个节点之间的并行(如果不执行这一步的话,需要将执行文件和需要的数据复制到每个节点的相同位置)。

五、集群环境执行MPI程序

(1)新建配置文件:
在home根目录(也可以是其他目录)下新建一个文件:mpi_config_file。mpi_config_file是在运行MPI程序时参考的配置文件,它显式注明每台机器各有几个CPU核。
编辑mpi_config_file(这个文件在后面执行程序时会作为参数包括在命令中):
sudo gedit mpi_config_file
因为我主机是8核且每台虚拟机分配了四核,所以在mpi_config_file中输入以下内容并保存:
node1:4
node2:4
(2)编写MPI程序:
这里我们选取案例程序进行测试,在我们之前解压的mpich-3.2文件夹下的examples目录下就有现成的可执行程序cpi,我们运行它即可。
(3)运行可执行程序:
将可执行文件cpi复制到共享目录/home/mpi_share/中,保证每个节点都可以访问该可执行文件(如果不安装NFS服务的话,需要将可执行文件放到每台机器的相同目录下)。
切换到共享目录:cd /home/mpi_share/
执行指令:mpiexec -n 8 -f /home/mpi_config_file ./cpi(mpiexec 表示执行该mpi程序,-n 8表示开8个进程,参数-f /home/mpi_config_file 表示运行过程参考配置文件mpi_config_file,./cpi是当前目录下的执行文件名)。执行成功后结果如下:
[email protected]:/home/mpi_share$ mpiexec -n 8 -f /home/mpi_config_file ./cpi
Process 2 of 8 is on node2
Process 5 of 8 is on node1
Process 7 of 8 is on node2
Process 4 of 8 is on node1
Process 3 of 8 is on node2
Process 1 of 8 is on node1
Process 6 of 8 is on node2
Process 0 of 8 is on node1

接下来我会持续更新该系列博客,并结合自己MPI程序实例分析MPI中的通信函数和并行设计策略。以下是我的邮箱:[email protected],如有问题,欢迎讨论。