Vivado的加速之路:Slurm Cluster!

天锦 发表于 码农也得有格调 分类,标签: Vivado的加速之路

相爱相杀,又爱又恨呀

去年10月,我被Vivado的龟速所逼,研究了Vivado的加速之道,研究了如何在远程服务器上实现和综合,见文章《Vivado的加速之路:Launch runs on Remote hosts》当时看到了有两种远程方式,一种是简单的丢在远程服务器上运行的runs on Remote hosts,一种是Cluster集群的方式,当时使用的是Vivado 2018,只支持IBM的LSF集群调度,由于LSF是商业软件,我连安装包都找不到,所以就只研究了runs on Remote hosts。最近升级到了Vivado 2019,发现这次除了LSF之外,新添加了Slurm的集群支持,Slurm是一个开源的集群调度系统,资料也比较好找,软件包也能下得到,如今就来一探究竟!

据说在我国首次获得世界TOP500计算机排名第一的天河一号计算机上使用的集群管理和作业调度系统,就是基于SLURM二次开发的,突然就感觉自己玩的东西好高级哈哈哈~

先建个几个虚拟机把集群跑起来。因为是摸索,我就用虚拟机跑了,如果可行就用实体机去跑。建立了三个虚拟机,运行CentOS7 x64,可以先建立一台虚拟机,把该装的软件都装了,注意Vivado需要桌面环境,记得安装成带桌面的CentOS并添加一个一般用户user(下文以user代指该用户)再从这台虚拟机里面克隆出来用作其他虚拟机。这里三台虚拟机IP和主机名如下

主机名IP地址集群中角色
c010.10.10.10

集群控制器、数据库、数据库控制器

c110.10.10.11计算节点
c210.10.10.12计算节点

先建立c0虚拟机,安装CentOS系统和必要软件之后再克隆出c1和c2,新建虚拟机跟装系统就略过。

创建全局用户

安装slurm需要安装Munge。Slurm和Munge需要跨集群中的每个节点一致的UID和GID。对于所有节点(控制节点和计算节点),在安装Slurm或Munge之前创建用户:

export MUNGEUSER=1001
groupadd -g $MUNGEUSER munge
useradd  -m -c "MUNGE Uid 'N' Gid Emporium" -d /var/lib/munge -u $MUNGEUSER -g munge  -s /sbin/nologin munge
export SLURMUSER=1002
groupadd -g $SLURMUSER slurm
useradd  -m -c "SLURM workload manager" -d /var/lib/slurm -u $SLURMUSER -g slurm  -s /bin/bash slurm

这里的1001和1002是用于创建指定的用户组的GID,如果提示该GID已经存在了那就换个更大的,可以在/etc/group中看那些GID还没有用的

[root@c0 ~]# cat /etc/group

安装Munge

安装EPEL源

[root@c0 ~]# yum install epel-release

然后使用EPEL安装Munge

[root@c0 ~]# yum install munge munge-libs munge-devel -y

在安装Munge之后,需要把Munge的key从控制节点配置到所有的计算节点。在计算节点上blog1创建Munge的key,只需要在控制节点上创建Munge的key。首先安装rng-tools

[root@c0 ~]# yum install rng-tools -y
[root@c0 ~]# rngd -r /dev/urandom
[root@c0 ~]# /usr/sbin/create-munge-key -r
[root@c0 ~]# dd if=/dev/urandom bs=1 count=1024 > /etc/munge/munge.key
[root@c0 ~]# chown munge: /etc/munge/munge.key
[root@c0 ~]# chmod 400 /etc/munge/munge.key

创建完成之后,需要将控制节点的key发送到所有的计算节点中,这里我的其他计算节点都是等部分软件部署完成之后从c0克隆的,所以分发key可以跳过,如果你是分别独立安装的需要注意。

[root@c0 ~]# scp /etc/munge/munge.key root@c1:/etc/munge/
[root@c0 ~]# scp /etc/munge/munge.key root@c2:/etc/munge/
......

配置Munge权限

chown -R munge: /etc/munge/ /var/log/munge/
chmod 0700 /etc/munge/ /var/log/munge/

克隆计算节点

克隆c0到c1和c2,记得更改ip和主机名

免密登陆和HOSTS

修改hosts文件,映射主机名和IP地址,并将编辑好的hosts文件分发到每一台主机上

127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
10.10.10.10    c0
10.10.10.11    c1
10.10.10.12    c2

后面会有很多scp和ssh等集群内部几个机器的通信过程,所以我设置了ssh-key免密码登陆,建议配置

[root@c0 ~]# ssh-keygen -t rsa
[root@c0 ~]# cat id_rsa.pub >> authorized_keys
[root@c1 ~]# ssh-keygen -t rsa
[root@c1 ~]# ssh-copy-id -i c0
[root@c2 ~]# ssh-keygen -t rsa
[root@c2 ~]# ssh-copy-id -i c0
.....
[root@c0 ~]# cat .ssh/authorized_keys 
ssh-rsa AAAAB3NzaC... root@c0
ssh-rsa CCCCCCCCCC... root@c1
ssh-rsa AADDDDDDDD... root@c2
[root@c0 ~]# scp /root/.ssh/authorized_keys c1:/root/.ssh/
[root@c0 ~]# scp /root/.ssh/authorized_keys c2:/root/.ssh/
.....

启动Munge

[root@c0 ~]# systemctl enable munge
[root@c0 ~]# systemctl start munge
[root@c1 ~]# systemctl enable munge
[root@c1 ~]# systemctl start munge
[root@c2 ~]# systemctl enable munge
[root@c2 ~]# systemctl start munge
......

测试Munge

每个计算节点与控制节点都互相测试一下连接。

[root@c0 ~]# munge -n
[root@c0 ~]# munge -n | unmunge
[root@c0 ~]# munge -n | ssh c1 unmunge
[root@c0 ~] remunge

安装Slurm依赖

在所有的节点上安装slurm依赖,slurm在创建安装包时需要 perl-ExtUtils-MakeMaker和 gcc,你也可以在克隆虚拟机之前安装这些依赖,会比较省事一些。

[root@c0 ~]# yum install openssl openssl-devel pam-devel numactl numactl-devel hwloc hwloc-devel lua lua-devel readline-devel rrdtool-devel ncurses-devel man2html libibmad libibumad -y
[root@c0 ~]# yum install perl-ExtUtils-MakeMaker gcc python3 -y
[root@c1 ~]# yum install openssl openssl-devel pam-devel numactl numactl-devel hwloc hwloc-devel lua lua-devel readline-devel rrdtool-devel ncurses-devel man2html libibmad libibumad -y
[root@c1 ~]# yum install perl-ExtUtils-MakeMaker gcc python3 -y
[root@c2 ~]# yum install openssl openssl-devel pam-devel numactl numactl-devel hwloc hwloc-devel lua lua-devel readline-devel rrdtool-devel ncurses-devel man2html libibmad libibumad -y
[root@c2 ~]# yum install perl-ExtUtils-MakeMaker gcc python3 -y
......

编译Slurm

在c0上下载Slurm的源码并且编译创建安装包,再把安装包分发给各个计算节点进行安装。

注意需要安装MariaDB(MySQL)服务器后才能编译Slurm,否则编译打包过程中会报错:

File not found: ......../apps/slurm/lib64/slurm/accounting_storage_mysql.so

这里先安装MariaDB,后面在配置Slurm时再配置MariaDB

[root@c0 ~]# yum install mariadb-server mariadb-devel -y

下载最新版本Slurm(20.02.3)的源码并编译打包

[root@c0 ~]# wget https://download.schedmd.com/slurm/slurm-20.02.3.tar.bz2
[root@c0 ~]# yum install rpm-build -y
[root@c0 ~]# rpmbuild -ta slurm-20.02.3.tar.bz2

安装Slurm

先在所有节点上建立一个文件夹用来存放安装包

[root@c0 ~]#  mkdir -p /hpc/software
[root@c1 ~]#  mkdir -p /hpc/software
[root@c2 ~]#  mkdir -p /hpc/software

控制节点上

[root@c0 ~]#  mv /root/rpmbuild/RPMS/x86_64/* /hpc/software
[root@c0 ~]#  cd /hpc/software
[root@c0 software]#  yum localinstall slurm-*.rpm
[root@c0 x86_64]#  scp /hpc/software/* c1:/hpc/software/    
[root@c0 x86_64]#  scp /hpc/software/* c1:/hpc/software/

计算节点上

[root@c1 ~]#  cd /hpc/software
[root@c1 software]#  yum localinstall slurm-*.rpm
[root@c2 ~]#  cd /hpc/software
[root@c2 software]#  yum localinstall slurm-*.rpm
......

配置Slurm

Slurm的配置文件有三个,对应不同功能,注意区分

文件名对应服务
用途
slurm.confslurmctld、slurmd全局配置
slurmdbd.confslurmdbd数据库管理器
cgroup.confslurmd计算节点

slurm.conf为全局配置文件,控制器、数据库管理器以及计算节点都要用到,要配置slurm.conf文件,可以访问 http://slurm.schedmd.com/configurator.easy.html  动态生成,也可以从/etc/slurm/slurm.conf.example复制得来,需要修改的是NodeName、CPUs和SlurmctldHost,下面是我的slurm.conf供参考:

# slurm.conf file generated by configurator easy.html.
# Put this file on all nodes of your cluster.
# See the slurm.conf man page for more information.
#
SlurmctldHost=c0
#
#MailProg=/bin/mail
MpiDefault=none
#MpiParams=ports=#-#
ProctrackType=proctrack/cgroup
ReturnToService=1
SlurmctldPidFile=/var/run/slurmctld.pid
#SlurmctldPort=6817
SlurmdPidFile=/var/run/slurmd.pid
#SlurmdPort=6818
SlurmdSpoolDir=/var/spool/slurmd
SlurmUser=slurm
#SlurmdUser=root
StateSaveLocation=/var/spool
SwitchType=switch/none
TaskPlugin=task/affinity
#
ReturnToService=1
SlurmctldPidFile=/var/run/slurmctld.pid
#SlurmctldPort=6817
SlurmdPidFile=/var/run/slurmd.pid
#SlurmdPort=6818
SlurmdSpoolDir=/var/spool/slurmd
SlurmUser=slurm
#SlurmdUser=root
StateSaveLocation=/var/spool
SwitchType=switch/none
TaskPlugin=task/affinity
#
#
# TIMERS
#KillWait=30
#MinJobAge=300
#SlurmctldTimeout=120
#SlurmdTimeout=300
#
#
# SCHEDULING
SchedulerType=sched/backfill
SelectType=select/cons_tres
SelectTypeParameters=CR_Core
#
#
# LOGGING AND ACCOUNTING
AccountingStorageType=accounting_storage/none
ClusterName=cluster
#JobAcctGatherFrequency=30
JobAcctGatherType=jobacct_gather/none
#SlurmctldDebug=info
#SlurmctldLogFile=
#SlurmdDebug=info
#SlurmdLogFile=
#
#
# COMPUTE NODES
NodeName=c[1-2] CPUs=8 State=UNKNOWN
PartitionName=lab Nodes=c[1-2] Default=YES MaxTime=INFINITE State=UP

slurm.conf编辑好后要分发给所有的节点

[root@c0 ~]# scp /etc/slurm/slurm.conf root@c1:/etc/slurm/
[root@c0 ~]# scp /etc/slurm/slurm.conf root@c2:/etc/slurm/

控制器和数据库管理器这两个角色可以在不同的主机上分开来做,也可以在一台机器上来做,这两个角色是两个不同的守护进程来负责的,这里资源有限,我都交给c0来做了,也就是说c0既是控制器,也要跑MariaDB数据库,也要跑Slurm的数据库管理器,注意后面这两个是两个不同的东西,一个是我们常见的数据库服务器,一个是Slurm的数据库管理器,不是一个服务。前面我安装了MariaDB,但是没有配置,现在先配置MariaDB后配置Slurm的数据库管理器,最后再配置Slurm的控制器。

[root@c0 ~]# systemctl start mariadb  # 开启服务
[root@c0 ~]# systemctl enable mariadb  # 设置为开机自启动服务
[root@c0 ~]# mysql_secure_installation #去设置MariaDB的root密码
[root@c0 ~]# mysql -u root -p    #    测试登陆并进入MariaDB控制台
Enter password:
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 8Server version: 5.5.60-MariaDB MariaDB Server
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MariaDB [(none)]>

创建数据库和slurmdb用户,赋予用户权限

MariaDB [(none)]> create database slurm_acct_db;
MariaDB [(none)]> create user slurmdb IDENTIFIED BY 'change_your_password';
MariaDB [(none)]> GRANT ALL PRIVILEGES ON slurm_acct_db.* to slurmdb@%  IDENTIFIED BY 'change_your_password';
MariaDB [(none)]> GRANT ALL PRIVILEGES ON slurm_acct_db.* to slurmdb@c0  IDENTIFIED BY 'change_your_password';
MariaDB [(none)]> GRANT ALL PRIVILEGES ON slurm_acct_db.* to slurmdb@localhost  IDENTIFIED BY 'change_your_password';
MariaDB [(none)]>exit

找一个数据库管理软件(Navicat或者phpMyAdmin)测试一下连接是否正常,防止因为数据库配置的问题到配置数据库管理器的时候出问题抓瞎。

关掉防火墙和SElinux(所有节点都需要)

[root@c0 ~]# systemctl disable firewalld
[root@c0 ~]# vim /etc/selinux/config    #设置SELINUX=disabled
[root@c0 ~]# reboot

接下来继续在c0上配置数据库管理器,编辑/etc/slurm/slurmdbd.conf,需要修改的是Database info下的信息,也就是用于连接MariaDB数据库的信息,包括IP、端口、用户名和密码。Slurm默认的数据库是slurm_acct_db我已经创建了不用另行指定数据库名了,参考如下:

#
# Example slurmdbd.conf file.
#
# See the slurmdbd.conf man page for more information.
#
# Archive info
#ArchiveJobs=yes
#ArchiveDir="/tmp"
#ArchiveSteps=yes
#ArchiveScript=
#JobPurge=12
#StepPurge=1
#
# Authentication info
AuthType=auth/munge
#AuthInfo=/var/run/munge/munge.socket.2
#
# slurmDBD info
DbdAddr=localhost
DbdHost=localhost
#DbdPort=7031
SlurmUser=slurm
#MessageTimeout=300
DebugLevel=verbose
#DefaultQOS=normal,standby
LogFile=/var/log/slurm/slurmdbd.log
PidFile=/var/run/slurmdbd.pid
#PluginDir=/usr/lib/slurm
#PrivateData=accounts,users,usage,jobs
#TrackWCKey=yes
#
# Database info
StorageType=accounting_storage/mysql
StorageHost=10.10.10.10
StoragePort=3306
StoragePass=change_your_password
StorageUser=slurmdb
#StorageLoc=slurm_acct_db

创建slurm需要的目录

[root@c0 ~]# mkdir /var/log/slurm/

测试数据库管理器,当看到Everything rolled up时即配置正确,出现err是需要看情况解决。

[root@c0 ~]# slurmdbd -vvvvDDDD

测试没有问题后,启动slurmdbd守护进程

[root@c0 ~]# systemctl enable slurmdbd
[root@c0 ~]# systemctl start slurmdbd

接下来配置控制器slurmctld,创建相关文件夹:

[root@c0 ~]# mkdir /var/spool/slurmctld
[root@c0 ~]# chown slurm: /var/spool/slurmctld
[root@c0 ~]# chmod 755 /var/spool/slurmctld
[root@c0 ~]# touch /var/log/slurmctld.log
[root@c0 ~]# chown slurm: /var/log/slurmctld.log
[root@c0 ~]# touch /var/log/slurm_jobacct.log /var/log/slurm_jobcomp.log
[root@c0 ~]# chown slurm: /var/log/slurm_jobacct.log /var/log/slurm_jobcomp.log

使用slurmctld -vvvvDDDD,进行调试启动,查看启动过程中有无错误。无错误后启动

[root@c0 ~]# systemctl enable slurmctld 
[root@c0 ~]# systemctl start slurmctld 
[root@c0 ~]# systemctl status slurmctld

控制器和数据库管理器都配置好了,接下来是计算节点的配置

创建cgroup.conf文件,默认即可

[root@c1 ~]# cp /etc/slurm/cgroup.conf.example /etc/slurm/cgroup.conf
[root@c1 ~]# systemctl enable slurmd
[root@c1 ~]# systemctl start slurmd
[root@c1 ~]# systemctl status slurmd
[root@c2 ~]# cp /etc/slurm/cgroup.conf.example /etc/slurm/cgroup.conf
[root@c2 ~]# systemctl enable slurmd
[root@c2 ~]# systemctl start slurmd
[root@c2 ~]# systemctl status slurmd
......

在任意节点都可以使用sinfo可以查看集群状态

[root@c1 ~]# sinfo 
PARTITION AVAIL  TIMELIMIT  NODES  STATE NODELIST 
lab*         up   infinite      2   idle c[1-2]

Tips:

当出现节点状态为drain时,可以使用scontrol show node 查看节点状态详细信息和drain的原因,并且可以使用update更改节点状态

[root@c0 ~]# scontrol update NodeName=c1 State=DOWN Reason=UnDrain
[root@c0 ~]# scontrol update NodeName=c1 State=RESUME

使用srun测试一下集群运行情况,-N指定运行的节点个数,这里为全部的计算节点也就是2,运行hostname命令查看运行任务的主机的主机名,可以看到c1和c2都正常分到了任务

[root@c0 ~]# srun -N 2 hostname
c2
c1

至此Slurm已经配置完成

配置Vivado

接下来配置终端的Vivado软件,我本想的是在我的运行Vivado的Ubuntu的系统上安装一个什么客户端之类的软件就能使用了,呵呵,还是太年轻啊。折腾的心酸就不提了,我最终选择了克隆其中一个计算节点为c3,在c3上面安装Vivado,用root用户安装到/tools/Xilinx目录下面,然后用nfs把/tools和/home这两个目录exports共享出来,其他节点再把这两个目录挂载到自己的文件系统上了,这样就实现了文件统一和都有Vivado程序可用(怪不得超算中心也用无盘拿NFS去挂文件系统,文件全局统一可用很重要啊)。安装完成之后在c3上打开Vivado(记得是桌面环境)测试。

注意这里有一些细节一定要搞清楚,我就是因为这个差点就放弃治疗了:

安装Vivado到/tools/Xilinx时需要使用root用户安装,但是运行的时候需要使用一般用户user去运行,安装完Vivado之后记得给/tools/Xilinx目录添加权限否则普通用户是运行不起来的

接下来在c3上打开Vivado,点击Run Synthesis,在弹出的Launch Runs窗口中点击Launch runs on Cluster 旁边的设置按钮,选择slurm,点击Test Configuration按钮测试连接。

launchruns1.png

setting.png

test.png

测试成功,瞬间就有点小激动了。设置好在集群上运行后跑个综合试试看。

[root@c0 ~]# squeue 
             JOBID PARTITION     NAME     USER ST       TIME  NODES NODELIST(REASON) 
                 2       lab /home/us     root  R       2:16      1 c1

在集群中能看到作业已经提交到队列里面了,可是我等了很久都没有结果,就像是无响应一样,可以看到这个作业被提交到了c1结点上,ssh c1去看看,htop一看,根本就没在运行嘛,这里忘了一件事情,Vivado的环境变量!

c1这台机器并不知道vivado命令的PATH,哎,逐台节点设置PATH:

[root@c0 ~]# echo 'export PATH=$PATH:/tools/Xilinx/Vivado/2019.2/bin/' >> /etc/profile
[root@c0 ~]# ssh c1 "echo 'export PATH=$PATH:/tools/Xilinx/Vivado/2019.2/bin/' >> /etc/profile"
[root@c0 ~]# ssh c2 "echo 'export PATH=$PATH:/tools/Xilinx/Vivado/2019.2/bin/' >> /etc/profile"
[root@c0 ~]# ssh c3 "echo 'export PATH=$PATH:/tools/Xilinx/Vivado/2019.2/bin/' >> /etc/profile"

为了能保证PATH能够生效,我把所以节点全部重启了一道。重启完之后发现集群所有节点全部down了……又手动更新了全部节点状态:

[root@c0 ~]# sinfo 
PARTITION AVAIL  TIMELIMIT  NODES  STATE NODELIST 
lab*         up   infinite      3   down c[1-3]
[root@c0 ~]# scontrol update NodeName=c[1-3] state=idle
[root@c0 ~]# sinfo 
PARTITION AVAIL  TIMELIMIT  NODES  STATE NODELIST 
lab*         up   infinite      3   idle c[1-3]

这次应该可以了,在c3上再次启动Vivado,运行综合,成功了!

[root@c0 ~]# sinfo 
PARTITION AVAIL  TIMELIMIT  NODES  STATE NODELIST 
lab*         up   infinite      1    mix c1 
lab*         up   infinite      2   idle c[2-3]

虽然这次Vivado跟Slurm集群的结合实验摸索出来了,但是通过看sinfo也好,看squeue也好,都发现Vivado依旧是只使用一个节点一个CPU,依旧是吃单核主,上再庞大的集群也是没有。最后是c1节点在运行作业时的htop截图,典型的单核程序:

htop.png


后续更新

登陆节点

在参考国内各HPC系统使用手册时发现除了计算节点外还有提供登陆节点,即用户登入系统提交作业的节点,并不作为计算节点提供计算服务,但是Slurm手册中没有提到所谓的登陆节点,我在测试Vivado时所用的c3节点也是计算节点之一,那么,按道理来讲,Vivado的bin应用程序已经通过nfs共享挂载在c1、c2计算节点上了,任意一个计算节点应该都能作为用户运行Vivado向集群中提交任务的“登陆节点”,实际测试也是如此。但是国内各HPC系统的登陆就只是登陆和提交,并没有作为计算节点,又是怎么回事?这很让我迷惑,当我重新修改slurm.conf文件,将c3节点从系统中去除后,也就是:

NodeName=c[1-2] CPUs=8 State=UNKNOWN
PartitionName=lab Nodes=c[1-2] Default=YES MaxTime=INFINITE State=UP

再在c3上将slurmd服务停掉,其他节点同步更新slurm.conf文件并重启对应的各slurmctld、slurmd进程,此时c3在集群中不再是计算节点,也没有其他角色,再次运行Vivado,可以正常提交任务,此时的c3便是单纯的登陆节点了,即安装了Slurm应用包,保有集群的slurm.conf,但是没有配置任何角色的节点就是登陆节点了。

这次折腾虽没能解决Vivado卡卡卡的毛病,但也带我了解了一个新的领域也是很Happy的,先挖个坑,后续会继续更新相关的内容的。超想做个带有FPGA的异构集群的。