0%

openmpi集群搭建

前言

高性能计算课。搭建了openmpi,然后使用多个主机(两台以上)来进行集群的搭建,然后进行并行计算。
大概方式就是各个主机之间使用ssh免密码登录,然后使用openmpi来一起运行某个位置的应用程序。

前提:需要安装好openmpi,可以看我之前的一篇博客–>openmpi-2.0.4安装


安装nfs并挂载

多台机器之间进行文件交流,用nfs服务器比较好,具体搭建nfs的方法可以我之前的一篇博客–>Ubuntu&Deepin系统上搭建nfs服务器
挂载:$ sudo mount -t nfs localhost:/home/xuan/rootfs /mnt
在每台机器上完成挂载。并且验证下是否挂载正常。


安装ssh&&host配置&&无密码登录

安装ssh

在给同学进行搭建的时候发现基本都没有ssh,所以安装一下ssh

1
2
3
$ sudo apt-get install openssh-server
$ sudo service sshd status
//可以看到ssh的服务起来了

如果状态显示不是actived的话那么可以开启
$ sudo service sshd start或者sudo /etc/init.d/ssh start

host配置

因为不同的电脑有不同的ip的地址,而且在不设置静态ip的情况下每次开关机很有可能会导致ip地址的变动,所以在这里设置一个ip地址的别名比较方便。
使用命令编辑$ sudo gedit /etc/hosts文件
在末尾加上对应的IP地址和hostname,比如

1
2
3
//IPAddress hostname
192.168.1.111 jiemy
192.168.1.109 dengyg

保存之后使用ping指令就能看到已经成功修改

1
2
3
$ ping jiemy
<--output-->
PING jiemy (192.168.1.111) 56(84) bytes of data.

无密码登录

装ssh就是为了能够让几台主机之间在进行数据交换的过程中不需要密码能够完成,所以接下来就开始配置,使用$ ssh-keygen来生成对应的ssh公钥。
具体的做法可以在我之前的一篇博客–>ssh免密码登录(ssh-keygen)中找到,首先确认nfs挂在是否正常,然后开始下面的操作

1
2
3
4
5
6
7
8
9
10
11
12
//在每台机器上生成自己的自己的ssh公钥
$ ssh-keygen //一路回车确认即可
//在每台机器上将*自己的公钥文件*重命名成自己的名字(例如jr.pub)放到共享文件夹
$ sudo cp ./.ssh/id_rsa.pub /mnt/jr.pub
//每台机器都完成后可以看到
$ ls /mnt/
dyg.pub jiemy.pub jr.pub Zx.pub
//在*某台机器*上将所有的公钥集合到authorized_keys中去
$ cd /mnt/
$ cat jr.pub jiemy.pub Zx.pub dyg.pub >> authorized_keys
//然后将authorized_keys放到*每个机器*的.ssh文件夹下
$ sudo cp authorized_keys ~/.ssh/

这样就完成了四台主机之间的相互登录,但是在登录的时候会有个坑。
就是你如果使用$ ssh jiemy来访问另一台主机的时候,就会出现不同用户名不同的情况,使用你自己的用户名来登录另一台主机。
解决方法就是在~/.ssh/config文件中添加hostname对应的用户名,如果没有config文件就自己创建一个$ sudo gedit ~/.ssh/config

1
2
3
4
5
6
//格式如下
Host hostname
user name
//给个例子
Host jiemy
user jiemy

然后尝试$ ssh jiemy,如果顺利SSH进入这台主机说明已经配置完成。


测试并行计算

以上的工作完成了,说明机器之间可以相互进行远程登录以及文件之间的拷贝,接下来需要做的就是测试我们的并行环境是否能够正常地使用了。
以下内容都在大家挂载的/mnt中进行。原因是,多台机器在做并行计算,执行的exe文件需要按照路径寻找。默认ssh链接过去是该台主机的家目录,我在尝试过程中每次都会遇到文件找不到的情况。大概报错如下,所以使用一个大家都挂载/mnt/test目录在玩就好了。

1
2
3
4
5
6
7
8
--------------------------------------------------------------------------
mpiexec was unable to launch the specified application as it could not access
or execute an executable:

Executable: /home/xuan/a.out
Node: jiemy

while attempting to start process rank 2.

测试demo

这里给一个我自己写的demo吧,创建一个test文件夹,创建一个hello_c.c

1
2
3
$ mkdir /mnt/test
$ cd /mnt/test
$ sudo gedit hello_c.c

文件代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
//hello_c.c
#include<mpi.h>
#include<stdio.h>
#include<string.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

void get(char *hname){
struct hostent *hent;
gethostname(hname, 128);//sizeof(hname)
//hent = gethostent();
hent = gethostbyname(hname);
//printf("hostname: %s/naddress list: ", hent->h_name);
}

int main(int argc,char *argv[])
{
int my_rank;/*进程序号*/
int p; /*进程总数*/
int source;/*发送者序号*/
int dest;/*接受者序号*/
int tag=0;/*消息标签*/
char message[100];/*消息储存*/
MPI_Status status;/*return status for*/

/*receive*/
/*启动MPI*/
MPI_Init(&argc,&argv);
/*查找进程号*/
MPI_Comm_rank(MPI_COMM_WORLD,&my_rank);
/*查找进程总数*/
MPI_Comm_size(MPI_COMM_WORLD,&p);

if(my_rank!=0)
{/*创建消息*/
//得到本机的ip地址
char hostname[128];
get(hostname);
sprintf(message,"Greeting from process %d,and ip is %s!",my_rank,hostname);
dest=0;
/*Use strlen+1 so that \0 gets transmitted*/
MPI_Send(message,strlen(message)+1,MPI_CHAR,dest,tag,MPI_COMM_WORLD);
}else{/*my rank ==0*/
for(source=1;source<p;source++){
MPI_Recv(message,100,MPI_CHAR,source,tag,MPI_COMM_WORLD,&status);
printf("%s\n",message);
}
char hostname[128];
get(hostname);
printf("Greeting from process %d,and ip is %s!\n",my_rank,hostname);
}
/*关闭MPI*/
MPI_Finalize();
}/*主函数结束*/

然后还是在这个test目录下创建一个hosts文件(注意不是/etc/hosts),这个文件的作用就是告诉你各个节点的信息。使用”slots”属性来制定进程的个数。(这个文件中#是注释)

1
2
3
# hostname slots=4
localhost slots=2
jiemy slots=2

注:要设置slots,我在没有设置的时候发现默认全都是在自己的机器上跑的,也就是输出都是Greeting from process X,and ip is xuan-PC!

编译运行

我在demo中写了一个获取本机的hostname的函数,这样可以很清晰地看到究竟是在哪台机器上进行的执行。当前目录还是在/mnt/test下。

1
2
3
4
5
6
7
$ mpicc hello.c
$ mpiexec -hostfile hosts -np 4 ./a.out
<--output-->
Greeting from process 1,and ip is xuan-PC!
Greeting from process 2,and ip is jiemy-virtual-machine!
Greeting from process 3,and ip is jiemy-virtual-machine!
Greeting from process 0,and ip is xuan-PC!

这个结果说明正确地按照了当前目录下hosts中的内容,分别有2个进程在xuan和jiemy的机器上执行的。


参考资料

1.参考了openMPI小集群安装
2.在SSH时出现了用户名不同的情况–>SSH Automatic Login(免密码)

听说好看的人都关注了我的公众号《泫言》