文章作者:童闻焕
目录提纲
背景简介
集群定义
高性能集群的常见用途
集群的条件
构造一个简单的Linux集群实现
并行计算设计
实验遇到问题
实验心得
背景简介
随着摩而定律的慢慢失效,单CPU的集成电路技术和工艺慢慢走到了技术的极限。然后,人们为了追求信息系统的高性能和高可靠性,集群技术随之产生和发展。(计算的速度变得更快?提高时钟频率,提高一个时钟周期执行的指令条数,更快的存储器,不同级别的并行)一般而言,现在集群技术是针对应用层系统的,而且往往具有下列几方面的特性:
1) 高可用性2) 高可靠性3) 高伸缩性4) 高性能
由于开放源码软件概念的采用,以及集群技术的精炼,使得高性能计算(HPC)正在变得越来越简单。加上Linux的优越性能和其他相关免费的资源,使得基于Linux 集群在很多领域变得非常流行。
实验主要完成Linux 集群技术的高性能计算(HPC)及相关测试,从基本的概念,并行,集群,到展示如何构建集群并编写并行程序。构建集群以及对集群进行基准测试,一步步入手,是对一个完全陌生的知识的摸索过程。集群环境的构建通过MPI来做,在实验中也结合了主要是网络和其他的相关的资料。
在Linux 上 FORTRAN、C 和 C++ 使用的高质量的 MPI 实现可以免费获得,在这里我们使用构建一个基于 MPICH 的 Linux 集群。
集群定义
集群(一组协同工作的计算机)是充分利用计算资源的一个重要概念,
因为它能够将工作负载从一个超载的系统(或节点)迁移到集群中的另一个系统上。其处理能力是与专用计算机(小型机,大型机)可相比,但其性价比高于专用计算机.
集群的分类
故障迁移集群、负载均衡集群 、高性能集群
1)故障迁移集群
最简单的故障迁移集群有两个节点:一个节点是活动的,另外一个节点是备用的,不过它会一直对活动节点进行监视。一旦活动节点出现故障,备用节点就会接管它的工作,这样就能使得关键的系统能够持续工作。
2)负载均衡集群
负载均衡集群通常会在非常繁忙的 Web 站点上采用,它们有多个节点来承担相同站点的工作,每个获取 Web 页面的新请求都被动态路由到一个负载较低的节点上。
3) 高性能集群
高性能集群用来运行那些对时间敏感的并行程序,它们对于科学社区来说具有特殊的意义。高性能集群通常会运行一些模拟程序和其他对 CPU 非常敏感的程序,这些程序在普通的硬件上运行需要花费大量的时间。
高性能集群的常见用途
几乎所有的产业界都需要快速的处理能力。随着越来越便宜而且快速的计算机的出现,更多公司表现出了对利用这些技术优势的兴趣。人们对于计算处理能力的需求是没有上限的;尽管处理能力在迅速提高,但是人们的需求仍然超出计算能力所能提供的范围。
1)生命科学研究
蛋白质分子是非常复杂的链,实际上可以表示为无数个 3D 图形。对于蛋白质折叠的研究非常重要。
2)石油和天然气勘探
震动图中包含有大陆和洋底内部特性的详细信息,对这些数据进行分析可以帮助我们探测石油和其他资源。这种分析显然需要大量的计算能力。这个领域对于计算能力的需求是如此旺盛,以至于超级计算机大部分都是在处理这种工作。
3)图像呈现
在工程领域(例如航天引擎设计)操纵高分辨率的交互式图像在性能和可伸缩性方面历来都是一种挑战将渲染屏幕的任务分割到集群中的各个节点上,在每个节点上都利用自己的图形硬件来呈现自己这部分屏幕的图像,并将这些像素信息传送到一个主节点上,主节点对这些信息进行组合,最终形成一个完整的图像。
GNU/Linux 操作系统(Linux)已经在集群中得到了大量的采用。Linux 可以在很多硬件上运行,并且具有高质量的编译器和其他软件,例如并行文件系统和 MPI 实现在 Linux 上都是免费的。采用 Linux,用户还可以针对自己的任务负载对内核进行定制。Linux 是构建 HPC 集群的一个非常好的平台。
集群的条件
有工作站和互联网两个部分组成。
至少有两个系统,这里用了windows下的虚拟机安装两个Linux来作为主从节点来实现。
工作站中间能实现通信,利用高速的局域网来构成一个并行的计算平台
构造一个简单的Linux集群实现
步骤 1
Linux环境的配置
对于我们的集群,要使用 MPICH 和一组普通的 Linux 工作站。我们学习更是了解突出其中的基本原理,我们将构建最小的裸系统,在集群环境中可以使用它来运行并行程序。同时实验是在基于windwos下的两个 VMware 映像来做的,可能算步上正真的集群。 VMware,因为 CPU 需要进行共享。在性能上不会有优势。首先安装windwos下的Linux虚拟机。
(*注意)同时安装时候注意相关的服务的开启,防火墙的设置,在vm下安装完Linux系统,配置好相关的参数环境。设置网络,至少能够使用机器名相互 ping 通。这些在下面要设置,最好系统安装前后完成。
步骤 2
安装 GNU C 编译器和 GNU FORTRAN 编译器。
当然这步应该最好在Linux初始安装时候完成,没有初始安装的,通过服务设置,也可以x-window 可视话或者命令来设置启用相关的服务。
步骤 3a
主机名:host1 host2
● 修改/etc/hosts文件,将所有节点名称及其ip地址填入。例如:
192.168.0.31 host1 #(主节点) ‘#’做注释
192.168.0.41 host2
每个节点都进行类似的配置。这样做的目的是使节点之间能够通过host1 和host1 2的名称相互访问。你可以通过ping noden 或 ssh noden进行测试。(noden为主机名)
● 修改(或创建)/etc/hosts.equiv文件
将所有你允许访问本机进行mpi计算的机器名填入,一行一个机器名。这一步是为了使节点对其它的节点放权。
例如,我的机器host1 的/etc/hosts.equiv文件是这样的:
host1 #给自己放权,这样在只有一台机器时也可以模拟并行计算环境
host2
在host2的/etc/hosts.equiv文件:
host1 #对host1 放权
host2
● 使用nfs共享文件
首先决定一个用于启动集群计算的用户名,不提倡使用root进行集群计算。这里在每个节
点上建立新用户linux,他们的主目录都是/home/linux,假设用host1做为计算的服务节点,在host1上建立~/mirror,修改文件/etc/exports,(~/为home用户目录文件)在其中增加一行:
/home/linux/mirror host1(rw) host2(rw)
使得机器host1和host2的用户可以使用/home/linux/mirror。
在其他节点host2也建立/home/linux /mirror,在/etc/fstab文件中增加一行:
host1:/home/linux/mirror /home/linux /mirror nfs rw,bg,soft 0 0
这样节点host2即可使用mirror与host1共享文件。
● 修改~/.bash_profile文件 (在安装mpi后更改)
建议把将来计算程序放在相同的路径上,当然也可以不放在同一个目录下面,但是用起来比较麻烦,需要一一指定每个节点程序的路径。譬如你的程序为:fpi.f和a.out,把a.out放在~/linux/mirror/下即可。
修改~/.bash_profile文件,主要是加入下列几行脚本:
export PATH=$PATH:/usr/local/mpi/bin
export MPI_USEP4SSPORT=yes
export MPI_P4SSPORT=22
export P4_RSHCOMMAND=ssh
这里我们预定了将来mpich的运行环境安装在目录/usr/local/mpi下面。其余的三个变量是用来通知mpi运行环境采用ssh来作为远程shell。
linux的运行环境到此就配置完毕了。
●配置ssh
安装以后,应该保证各节点之间能够用ssh相互登录。每个节点的sshd都应该能正常提供服务。
以设定的用于启动mpi计算的用户登录,运行ssh-keygen –t dsa(SSH2)或是ssh-keygen(SSH1)
–t rsa1,这将生成一个私有/公开密钥对,分别存放在~/.ssh/id_dsa和~/.ssh/id_dsa.pub或是
~/.ssh/identity和~/.ssh/identity.pub文件中。然后进行访问授权,运行:
cp ~/.ssh/identity.pub ~/.ssh/authorized_keys 或是cp ~/.ssh/id-dsa.pub ~/.ssh/authorized_keys2
chmod go-rwx ~/.ssh/authorized_keys或是chmod go-rwx ~/.ssh/authorized_keys2
ssh-agent $SHELL
ssh-add
在每个节点干一遍。
将所有节点的密钥authorized_keys或是authorized_keys2收集起来,放到一个密钥文件中,
然后分发到各个节点。这样做的目的是使各节点相互之间访问无需输入密码。在每个节点登
录其它节点,ssh shallow,则在~/.ssh/下生成一个known_hosts文件,里面记录登录用户密钥。
为所有节点配置 SSH,允许不询问密码就可以执行命令。这样做的目的是能够不需询问密码就可以执行 ssh -n host whoami 这样的命令。SSH 用作不同机器之间的通信方法。(也可以使用 rsh 来实现这种功能。)
无法用ssh登录,则可以用ipchains -L命令查看ipchains rules,进行正确的配置,使得ssh服务正常工作。若你对系统安全不是太在乎,则可以使用ipchains -F命令将所有的规则清空。
为了确保所有的配置都能正常工作,请执行下面的命令:ssh -n hostname 'date',并查看这个命令能否成功执行,而不会出现任何错误。应该对所有节点都执行这种测试,这样就可以确保所有节点上的设置都没有问题。
注意:可能还需要修改防火墙的配置,使其允许节点彼此之间相互进行通信。
步骤 4a
接下来,我们将安装 MPICH。
步骤 4b
下载最新的mpich: MPICH,或者
。拷贝到一个临时目录下,
我是从中科院 下在来的 MPICH 1.2.7p1 版本,安装说明综合网上资料,见上面。
我放在/home/mpi/mirror下了。/root下都可以,主要看解压到的地方,这里我们-prefix=/usr/local/mpi文件中
首先,用tar xzpvf mpich-1.x.x.tar.gz解压。生成mpich-1.x.x.目录。
cd mpich-1.x.x
./configure -prefix=/usr/local/mpi -rsh=ssh —— 这告诉 MPICH 使用 ssh 作为通信机制
上面的一次编译不成功用下面的命令,下面的命令通过测试
// ./configure -prefix=/usr/local/mpi --disable-weak-symbols
切换到mpich-1.x.x.目录。
运行预处理:./configure -c++=pgCC -cc=pgcc -fc=pgf77 -f90=pgf90 \
-cflags="-Msignextend -tp athlon -DUSE_U_INT_FOR_XDR -DHAVE_RPC_RPC_H=1" \
-fflags="-tp athlon" -c++flags="-tp athlon" -f90flags="-tp athlon"\
-prefix=/usr/local/mpich -opt=-fast -rsh=ssh
我采用了Portland Group的编译器,因此需要在预处理时指定使用的编译器和常用的选项,
-tp athlon为AMD athlon产生代码。mpich的安装位置为/usr/local/mpich,运行环境的远程host2
为ssh。
-DUSE_U_INT_FOR_XDR -DHAVE_RPC_RPC_H=1在有的系统上不需要
有时候需要设置环境变量:
setenv LIBS "-L/usr/local/pgi/linux86/lib -lpgftnrtl -lpgc"
编译:make
安装:make install
分别将”/usr/local/mpi/bin” 和 “/usr/local/mpi/man” 加入到环境变量PATH和MANPATH中。
只需在目录/etc/profile.d中创建两个文件mpich.sh和mpich.csh,它们分别对Bourne shell和C shell 起作业,这两个文件的内容如下:
– /etc/profile.d/mpich.sh:
#!/bin/bash
export MANPATH=${MANPATH}:/usr/local/mpi/man
export PATH=${PATH}:/usr/local/mpi/bin
– /etc/profile.d/mpich.csh:
#!/bin/csh
if ( $?MANPATH == 0 ) then
setenv MANPATH :/usr/local/mpi/man
else
setenv MANPATH ${MANPATH}:/usr/local/mpi/man
endif
setenv PATH ${PATH}:/usr/local/mpi/bin
步骤 5
要让 MPICH 知道所有的节点,请编辑文件 /tmp/mpich-1.x.x /util/machines/machines.LINUX,并将所有节点的主机名添加到这个文件中,这样安装的 MPICH 就可以知道所有的节点了。如果以后再添加新的节点,也请修改这个文件。
host1
host2
若是多CPU计算机,需要在节点名称后用:num加以说明。
每个节点都这样干一遍。
步骤 6
将目录 /tmp/mpich-1.x.x 拷贝到集群中的所有节点上。
步骤 7
在 examples 中运行几个测试程序:
现在集群已经准备好了!正如我们可以看到的一样,所有的重头戏都可以留给 MPI 实现来完成。正如前面介绍的一样,这是一个裸集群,所需的大部分手工工作只是确保机器之间可以彼此进行通信(我们配置了 ssh,MPICH 是手工拷贝的,等等)。
以设定的用户登录(我的是linux)host1,将mpich-1.x.x /examples/basic/fpi.f文件拷贝到
~/mpi/mirror下,编译:
C 程序
mpicc -o cpi cpi.c .
mpirun -np 1 cpi
mpirun -np 2 cpi
Fortran 程序
mpif77 -o pi3 pi3.f .
mpirun -np 1 pi3
mpirun -np 2 pi3
mpif77 fpi.f,生成a.out文件,运行:
mpirun -np 2 a.out —— 告诉 MPICH 在 2 个处理器上运行程序;如果配置中没有 2 个处理器,也不用担心;MPICH 会创建一些进程来补偿物理硬件的缺失。
这里采用2个节点进行计算。进行ssh连接后,程序等待输入,这时可以在节点机上用命令:
ps -A | grep aout
查看进程,应该能看到数个fpi进程,其中第一个是本机所执行的进程,其它的是异地进程
镜像。在sea上输入一个整值,再次在各节点上执行
ps -A | grep a.out
可以发现计算时间在不断增长,表明计算的确是在多台主机上同时进行的。
至此,整个安装配置过程结束
并行计算设计
在并行计算中,由于并行算法可以对性能产生重大的影响,因此受到广泛的重视,并行算法也成为一个专门的十分活跃的研究领域,并行算法设计也是并行程序设计的前提,没有好的并行算法,就没有好的并行程序。因此在并行程序设计之前,必须首先考虑好并行算法该算法要能够将并行机和实际的问题很好地结合起来,既能够充分利用并行机体系结构的特点,又能够揭示问题内在的并行性。
程序代码:
用FORTRAN 77+MPI 实现的"HELLO WORLD"
??program main
??include 'mpif.h'
??character * (MPI_MAX_PROCESSOR_NAME) processor_name
??integer myid, numprocs, namelen, rc,ierr
??call MPI_INIT( ierr )
C 程序初始化
call MPI_COMM_RANK( MPI_COMM_WORLD, myid, ierr )
C 得到当前进程号
call MPI_COMM_SIZE( MPI_COMM_WORLD, numprocs, ierr )
C得到总的进程数
call MPI_GET_PROCESSOR_NAME(processor_name, namelen, ierr)
C得到处理器名字
write(*,10) myid,numprocs,processor_name
10 FORMAT('Hello World! Process ',I2,' of ',I1,' on ', 20A)
call MPI_FINALIZE(rc)
C结束
end
输出结果
??Hello World! Process 1 of 2 on tp5
??Hello World! Process 0 of 2 on tp5
【代码分析】
MPI程序一般分为几个部分?
讲解:
??第一部分,首先要有MPI相对于FORTRAN实现的头文件mpif.h,对于MPI相对于C语言的实现,其头文件是不同的。即用FORTRAN语言编写的MPI并行程序,必须有MPI的FORTRAN头文件mpif.h。
??第二部分,定义程序中所需要的与MPI有关的变量。MPI_MAX_PROCESSOR_NAME是MPI预定义的宏,即某一MPI的具体实现中允许机器名字的最大长度,机器名放在变量processor_name中;整型变量myid和numprocs分别用来记录某一个并行执行的进程的标识和所有参加计算的进程的个数;namelen是实际得到的机器名字的长度;rc和ierr分别用来得到MPI过程调用结束后的返回结果和可能的出错信息。
??第三部分,MPI程序的开始和结束必须是MPI_INIT和MPI_FINALIZE,分别完成MPI程序的初始化和结束工作。
??第四部分,MPI程序的程序体,包括各种MPI过程调用语句和FORTRAN语句。MPI_COMM_RANK得到当前正在运行的进程的标识号,放在myid中;MPI_COMM_SIZE得到所有参加运算的进程的个数,放在numprocs中;MPI_GET_PROCESSOR_NAME得到运行本进程的机器的名称,结果放在processor_name中,它是一个字符串,而该字符串的长度放在namelen中;write语句是普通的FORTRAN语句,它将本进程的标识号,并行执行的进程的个数,运行当前进程的机器的名字打印出来,和一般的FORTRAN程序不同的是这些程序体中的执行语句是并行执行的,每一个进程都要执行。不妨指定本程序启动时共产生4个进程同时运行,而运行本程序的机器的机器名为"tp5",4个进程都在tp5上运行,其标识分别为0,1,2,3,执行结果如图所示,虽然这一MPI程序本身只有一条打印语句,但是由于它启动了四个进程同时执行,每个进程都执行打印操作,故而最终的执行结果有四条打印语句。
编写一个FORTRAN+MPI的程序,实现每一个进程都打印出自己的进程号,总的进程数,本进程所在的机器名以及"SAY HELLO TO MPI"。
??program main
??include 'mpif.h'
??character * (MPI_MAX_PROCESSOR_NAME) processor_name
??integer myid, numprocs, namelen, rc,ierr
??call MPI_INIT( ierr )
??call MPI_COMM_RANK( MPI_COMM_WORLD, myid, ierr )
??call MPI_COMM_SIZE( MPI_COMM_WORLD, numprocs, ierr )
??call MPI_GET_PROCESSOR_NAME(processor_name, namelen, ierr)
??write(*,10) myid,numprocs,processor_name
FORMAT('Process ',I2,' of ',I1,' SAY HELLO TO MPI on ', 10A)
??call MPI_FINALIZE(rc)
??end
例子:
编写一个C+MPI的程序,实现每一个进程都打印出自己的进程号,总的进程数,本进程所在的机器名以及"SAY HELLO TO MPI"。
??#include "mpi.h"
??#include
??#include
??void main(argc,argv)
??int argc;
??char *argv[];
???{
????int myid, numprocs;
????int namelen;
????char processor_name[MPI_MAX_PROCESSOR_NAME];
????MPI_Init(&argc,&argv);/*程序初始化*/
????MPI_Comm_rank(MPI_COMM_WORLD,&myid);/*得到当前进程号*/
????MPI_Comm_size(MPI_COMM_WORLD,&numprocs);/*得到总的进程数*/
????MPI_Get_processor_name(processor_name,&namelen);/*得到机器名*/
????fprintf(stderr," Process %d of %d SAY HELLO TO MPI on %s\n",
????myid, numprocs, processor_name);
????MPI_Finalize();/*结束*/
???}
实验遇到问题
1.mpich无法安装上去,出现说编译后安装通不过,make install°几处出错。
多次编译解压尝试,make install 好像要运行两次才行。
2.Linux网络无法链接,实现机子间的通讯,不能简单的ping
由于vm虚拟机的安装会在windos系统上安装两个虚拟网卡,VMware的几种网络模式:
· bridged(桥接模式) :等于让Guest和Host系统并列在同一个子网中,占用两个ip,相互独立
(对于绑定网卡的子网络就不适用了,而且Guest的包就直接出去了,
Host管不了)
· host-only(主机模式) :对应Host里面的"VMnet1",Guest的ip由VMware的DHCP提供,
相当于与Host网线直连
如果要访问外网,还需要手工做网桥。。。。
· NAT (网络地址转换模式) :这个对于让Guest OS访问Internet是最简单的,对应"VMnet8",
直接使用Guest认的网卡就行了,ip是VMware的DHCP对应VMnet8分配的,
与外网无关,但Guest对外的访问,会自动转换出去,linux下的网络中设置静态ip,同时定义不同主机名。有的时候因为更改ip造成网络后没有激活。或者是只是更改了ip但在系统文件中没有修改而造成,可能要该host.equiv,hosts.machine几个文件,有的时候设置完毕后需要在win网上邻居中重新开启一次本地链接,同时设置38PO 上的 本地连接 2也能实现链接。
3.SSh使用的时候出现Connecton refused 的信息错误。
由于是因为linux系统下的firework的级别设置的问题,把级别设置低就可以了。Setup命令来更改
4.Mpirun -np 2 a.out 并行计算出现 Child process exsied while making connection of remoto process on host2:0 Internet net
Send:could not write to fd=4,errno =32;
再最后次重新安装按照上面的步骤没有出现上面的问题了
实验心得
通过本次实验的学习,对并行程序设计有一个具体的基本的概念,对MPI有比较全面的了解,掌握MPI的基本功能,并且可以编写基本的MPI程序,可以用MPI来解决实际的比较基本的并行计算问题。实验使我接触和学习了很多知识,特别是对linux系统环境有了一个更深刻的认识,通过不断的网络的摸索和学习, 对原先很不懂的linux目录文件,linux快捷键等等很好的认识,在后来的阶段我感觉终端的操作还快于图形界面的操作。也理解和弄清出了很多的概念,集群,并行,节点,mpich,在实验过程中也接触了其他的知识(如何windows访问Linux系统,用Putty等软件来实现,怎么实现Linux系统下面加载windos分区等等ext2fsnt)
vi 命令的使用 vi 文件名,ls 操作文件显示文件属性等等,ls –l ls –a alt+F1 系统菜单 F7窗体的移动。终端中首字母+Tab快速输入文件名 显示主机名hostname -a更改主机名hostname host1 本机ip hostname -i
命令来关闭防火墙
用IPTables -F 或setup
开启ssh
/etc/rc.d/init.d/sshd restart 或者 service sshd start
测试 netstat -tl
rsh 开启 /etc/rc.d/init.d/xinetd restart
测试 netstat -an /grep 514
各种服务 ntsysv
网络状态查看 netstat -x (x包括i,t,s,r)
修改文件权限chmod
MPI程序中的输出语句和一般串行程序中输出语句的执行结果的不同――MPI程序中的输出语句每一个进程都执行,执行时有几个进程就有几条输出语句,而串行程序中输出语句只有本进程输出结果。
不同进程对同一个内容的输出,其顺序是随机的。
当然,目前的实验知识最基本的裸机的实验。真正的知识和应用还远远不够
Linux集群管理,如何有效地实现简单而高可维护行的linux集群,用的其他的工具等等,实验中存在暴露了自己很多存在的不足之处,努力在今后的编程中不断的加强改进。当然这次实验做的不是很完整,但给我一次很好的锻炼的机会,无论是练习和尝试都好,对自己的能力的认识,对新知识的吸收都是一个挑战,Linux一个优秀的系统,我想它对我的吸引一定会使我在今后不断自我。集群一个很实用且是目前广泛应用的东西,希求能更远更好的认识和掌握它。