博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Linux多节点下MPI集群环境搭建
阅读量:5814 次
发布时间:2019-06-18

本文共 7504 字,大约阅读时间需要 25 分钟。

  hot3.png

一、MPI

1.  关于MPI

        MPI(Message Passing Interface)是一个信息传递应用程序接口,可以用于并行计算。MPI有多种实现版本,如MPICH, CHIMP以及OpenMPI。其中最常见的的是MPICH和OpenMPI,本文使用的是MPICH。

        MPICH官网:

        OpenMPI官网:

2.  软硬件准备

机器准备:

        3个节点(dellnode1、dellnode2、dellnode3)

操作系统:

        Centos 6.5 64位

依赖软件:

        该安装过程需要c、c++等编译器,否则安装过程中会出现如下错误:

        若出现该错误,只需按照提示信息安装对应的编译器即可

3.  系统环境配置

        为减小配置对整个系统的影响,我们在 root 用户下新建一个名为“mpiuser”的用户,然后将要安装的的软件都安装在该用户目录下。

sudo useradd -m mpiusersudo passwd mpiusersudo adduser mpiuser sudo

        之后注销当前用户,返回登陆界面。在登陆界面中选择刚创建的 mpiuser 用户进行登陆。

4.  下载并安装MPI

        进入MPICH官网(),点击“Download MPICH”

        选择对应的版本,点击Download下的http即可下载。

3.2版可直接点击如下链接进行下载:

        接下来将下载的压缩包拷贝到Linux系统下,在mpiuser目录下新建一个mpich目录

cd /home/mpiusermkdir mpich

        切换到压缩包目录,使用如下命令进行安装: 

tar -xzvf mpich-3.2.1.tar.gz -C /home/mpiuser/mpich/cd /home/mpiuser/mpich/mpich-3.2.1/./configure --prefix=/home/mpiuser/mpich  #运行后出现"Configuration completed."即配置成功#可能会提示你需要安装各种编译器#gcc编译器:sudo yum install gcc#g++编译器:sudo yum install gcc-c++#gfortran编译器:sudu yum install gcc-gfortranmake && make install    #若出现问题,请使用root权限安装

        安装后加入环境变量

vim /home/mpiuser/.bashrc

        添加如下内容(注意要与自己实际的安装目录相对应,不然后面会无法识别mpi的相关命令) 

PATH=$PATH:/home/mpiuser/mpich/binexport PATH

         执行source命令

source /home/mpiuser/.bashrc

 

二、单节点测试

        切换到example目录下

cd ~/mpich/mpich3.2.1/examples/

        执行

mpirun -n 5 ./cpi

     若输出结果如下,则单节点已经配置成功(注意在可执行文件cpi前面加上 ./ ,不然会报 “HYDU_create_process (./utils/launch/launch.c:75): execvp error on file cpi (No such file or directory)” 的错误)

211544_cUxO_2812815.png

如果出现以下报错,只需要修改/etc/hosts文件,添加一行“127.0.0.1   hostname”(hostname为你自己的主机名)

13c1f51b0bd2e5290727d4f3e3fde86a0e5.jpg

三、多节点配置

1、host配置(所有节点)

vim /etc/hosts

154714_zdJZ_2812815.png

source /etc/hosts

        可以互ping来测试主机名修改是否成功(如使用 “ping dellnode2” )

2、集群机器上面需要配置ssh登录权限

        生成公钥,并发送给dellnode2节点

cd ~/.ssh/                     # 若没有该目录,请先执行一次ssh localhostssh-keygen -t rsa              # 会有提示,接着连按3次回车cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys #将自己的公钥追加到authorized_keys里

        用ssh登录到dellnode2、dellnode3上面执行相同的操作,并将产生的公钥发送给dellnode1

cd ~/.ssh/                     # 若没有该目录,请先执行一次ssh localhostssh-keygen -t rsa              # 会有提示,接着连按3次回车scp ./id_rsa.pub mpiuser@dellnode1:~/.ssh/node2_id_rsa.pub#避免名字重复加上对应节点的前缀,节点3就加node3

        将发送过来的公钥追加到authorized_keys

cat ~/.ssh/node2_id_rsa.pub >> ~/.ssh/authorized_keyscat ~/.ssh/node3_id_rsa.pub >> ~/.ssh/authorized_keys

        修改文件权限并将authorized_keys文件发送给另外2个节点

chmod 600 ~/.ssh/authorized_keys       #可能有时不修改也不影响无密登录但还是建议修改scp ./authorized_keys mpiuser@dellnode2:~/.ssh/authorized_keysscp ./authorized_keys mpiuser@dellnode3:~/.ssh/authorized_keys

        把"~/.ssh/"目录下的"node1_id_rsa.pub"等文件删除掉

rm ~/.ssh/node1_id_rsa.pub     #同上rm ~/.ssh/node2_id_rsa.pub     #同上

         验证ssh无密登录,如下3个节点节可以任意实现无密登录

   160120_oyD7_2812815.png

        如果无法成功,请检验追加的公钥是否正确,若还是不行请确保ssh服务开启

sudo vim /etc/ssh/sshd_config

        去掉注释:

        RSAAuthentication yes # 启用 RSA 认证

        PubkeyAuthentication yes # 启用公钥私钥配对认证方式

        AuthorizedKeysFile .ssh/authorized_keys # 公钥文件路径(和上面生成的文件同)

/bin/systemctl restart sshd.service

3、在其他机器上面安装mpich

        可以使用scp直接复制(要保证其他环境已经搭好,如各种编译器,否者可能无法正常编译运行程序),也可以对每台机器进行压缩包的解压安装。

scp -r /home/mpiuser/mpich mpiuser@dellnode2:/home/mpiuser/

        配置每台机器的环境变量

4.  新建一个servers文件,内容如下:

dellnode1:3  #运行3个进程dellnode2:3  #运行3个进程dellnode3:3  #运行3个进程

        执行下面命令,并指定servers文件

mpirun -n 9 -f ./servers ./mpich-3.2.1/examples/cpi     #在examples目录下

        若输出如下则代表环境配置成功

183314_lFeh_2812815.png

四、mpi程序演示

        演示程序:蒙特卡洛方法计算圆周率(参考:)

        其思想是假设我们向一个正方形的标靶上随机投掷飞镖,靶心在正中央,标靶的长和宽都是2 。同时假设有一个圆与标靶内切。圆的半径是1,面积是π的平方。如果击中点在标靶上是均匀分布的(我们总会击中正方形),那么飞镖击中圆的数量近似满足等式,飞镖落在圆内的次数/飞镖落在标靶内的总次数=π/4,环包含的面积与正方形面积的比值是π/4。环所包含的面积与正方形面积的比值是π/4。我们可以用这个公式和随机数产生器来估计π的值。

        新建 “pi.c” 源文件,其代码如下:

#include 
#include
#include
#include
#include
void read_num(long long int *num_point,int my_rank,MPI_Comm comm);void compute_pi(long long int num_point,long long int* num_in_cycle,long long int* local_num_point,int comm_sz,long long int *total_num_in_cycle,MPI_Comm comm,int my_rank);int main(int argc,char** argv){ long long int num_in_cycle,num_point,total_num_in_cycle,local_num_point; int my_rank,comm_sz; double begin,end; MPI_Comm comm; MPI_Init(NULL,NULL);//初始化 comm=MPI_COMM_WORLD; MPI_Comm_size(comm,&comm_sz);//得到进程总数 MPI_Comm_rank(comm,&my_rank);//得到进程编号 read_num(&num_point,my_rank,comm);//读取输入数据 begin=MPI_Wtime(); compute_pi(num_point,&num_in_cycle,&local_num_point,comm_sz,&total_num_in_cycle,comm,my_rank); end=MPI_Wtime(); if(my_rank==0){ printf("Elapsing time: %fs\n",end-begin); } MPI_Finalize(); return 0;}void read_num(long long int* num_point,int my_rank,MPI_Comm comm){ if(my_rank==0){ printf("please input num in sqaure \n"); scanf("%lld",num_point); } MPI_Bcast(num_point,1,MPI_LONG_LONG,0,comm);}void compute_pi(long long int num_point,long long int* num_in_cycle,long long int* local_num_point,int comm_sz,long long int *total_num_in_cycle,MPI_Comm comm,int my_rank){ *num_in_cycle=0; *local_num_point=num_point/comm_sz; double x,y,distance_squared; srand(time(NULL)); for(long long int i=0;i< *local_num_point;i++){ x=(double)rand()/(double)RAND_MAX; x=x*2-1; y=(double)rand()/(double)RAND_MAX; y=y*2-1; distance_squared=x*x+y*y; if(distance_squared<=1) *num_in_cycle=*num_in_cycle+1; } MPI_Reduce(num_in_cycle,total_num_in_cycle,1,MPI_LONG_LONG,MPI_SUM,0,comm); if(my_rank==0){ double pi=(double)*total_num_in_cycle/(double)num_point*4; printf("the estimate value of pi is %lf\n",pi); }}

        在pi.c同目录下新建servers文件,内容如下

dellnode1:1  #运行1个进程dellnode2:1  #运行1个进程

        编译、运行

mpicc -std=c99 -o pi.out pi.c        #编译scp ./pi mpiuser@dellnode2:/home/mpiuser/mpich/myMPIProgram/      #拷贝可执行程序到dellnode2同路径下mpirun -f servers -n 2 ./pi.out      #运行程序  注意加"./"

        由于服务器为多核设计,所以在没有其他设置的情况下,只是简单的设置进程数为2(不使用“-f servers”参数),则2个进程都在同一个节点上运行,虽然时间确实变快了2倍,单此情况并没有利用多个节点的性能,当进程数超过逻辑cpu个数时就不能再获得加速了,而这不是我们所期望的。(如下图所示)

201121_L0Yg_2812815.png

        要使程序在不同的节点上运行,需要指定参数“-f servers”,其中“servers”是我们自己建立的一个文件,用来指定每个节点运行的进程数等参数。同时为了保证其他节点(如dellnode2)能够正常运行程序,需要保证在与dellnode1可执行文件相同路径下有同样的可执行程序(使用scp拷贝或建立NFS共享目录,详情见写下一章),否则会报如下找不到文件的错误。

202106_gti0_2812815.png     

        正确的运行方式如下图: 

200837_eyWi_2812815.png

        可以看到,当取点的个数为10亿个时,单节点要运行44秒,使用2个节点并行只需22秒。

五、NFS共享目录安装配

(参考:)

如果不进行这一步mpi程序也可以正常运行,但是需要保证在每个节点上的相同路径下都有可执行文件,所以每次都要把可执行文件进行远程拷贝,非常麻烦!

服务端:dellnode1(10.10.1.1)

客户端:dellnode2(10.10.1.2)、dellnode3(10.10.1.3) 

1.服务端安装配置

        安装nfs-utils和rpcbind

sudo yum -y install nfs-utils rpcbind

        创建共享目录:

sudo mkdir /mpiShareDir

        配置/etc/exports

sudo vim /etc/exports

130954_6OLf_2812815.png

#参数说明#rw:read-write,可读写;#ro:read-only,只读;#sync:同步写入(文件同时写入硬盘和内存),适用在通信比较频繁且实时性比较高的场合#async:异步写入(文件先写入内存,稍候再写入硬盘),性能较好(速度快),适合超大或者超多文件的写入,但有数据丢失的风险,比如突然断电等情况;#注意:除非特別有需要,否则不建议使用 async。如果沒有指定 sync 或 async,NFS 服务器在启动的时候会印出警告信息。#no_root_squash:NFS客户端连接服务端时如果使用的是 root 的话,那么对服务端分享的目录也使用 root 权限。不安全!#root_squash:把客户端 root 身份的 UID/GID (0/0) 对应到服务端的 nobody 用户去,即服务端使用 nobody 用户来操作共享目录;#all_squash:不论NFS客户端连接服务端时使用什么用户,对服务端分享的目录来说都是拥有匿名用户权限;#anonuid:匿名用户的UID值,通常是nobody或nfsnobody,可以在此处自行设定;#anongid:匿名用户的GID值。

        启动服务,并设置开机启动

sudo service rpcbind startsudo service nfs startsudo chkconfig --level 2345 rpcbind onsudo chkconfig --level 2345 nfs on

2.客户端配置

        安装nfs-utils和rpcbind

sudo yum -y install nfs-utils rpcbind

        创建目录

sudo mkdir /mpiShareDir

        查看服务端共享目录

showmount -e 10.10.1.1

        挂载共享目录到本地,并测试读写:

sudo mount -t nfs 10.10.1.1:/mpiShareDir /mpiShareDir#最开始,我将共享目录放在/home/mpiuser下的mpiShareDir文件夹内,虽然mpiShareDir的权限为777#但是由于其父目录(即用户目录mpiuser)的权限为700,所以挂载时遇到服务器拒绝访问的问题#于是我将共享目录放在根目录下,并将其权限设置为777,否则需要增加用户目录的访问权限cd /mpiShareDir && touch test

        设置开机自动挂载:

sudo vim /etc/fstab
10.10.1.1:/mpiShareDir     /mpiShareDir                    nfs     defaults        0 0

        上述步骤完成后,以后只需将mpi程序放在mpiShareDir目录下就可以直接运行,而不需要使用远程拷贝。

133213_4ott_2812815.png

转载于:https://my.oschina.net/zctzl/blog/1560593

你可能感兴趣的文章
粤出"飞龙",打造新制造广东样本
查看>>
编玩边学获数千万元A轮融资,投资方为君联资本
查看>>
蓝图(Blueprint)详解
查看>>
Spark之SQL解析(源码阅读十)
查看>>
Android图片添加水印图片并把图片保存到文件存储
查看>>
比特币系统采用的公钥密码学方案和ECDSA签名算法介绍——第二部分:代码实现(C语言)...
查看>>
海贼王十大悲催人物
查看>>
BigDecimal 舍入模式(Rounding mode)介绍
查看>>
开源 免费 java CMS - FreeCMS1.2-标签 infoSign
查看>>
开源 免费 java CMS - FreeCMS1.9 移动APP生成栏目列表数据
查看>>
git reset 三种用法总结
查看>>
虚拟机新增加硬盘,不用重启读到新加的硬盘
查看>>
Java IO流详尽解析
查看>>
邮件服务系列之四基于虚拟用户的虚拟域的邮件系统(安装courier-authlib以及部分配置方法)...
查看>>
Linux VSFTP服务器
查看>>
DHCP中继数据包互联网周游记
查看>>
Squid 反向代理服务器配置
查看>>
Java I/O操作
查看>>
Tomcat性能调优
查看>>
项目管理心得
查看>>