现在运行MPI任务要么在单节点上,要么直接提交到集群,基本用不到自己部署多节点的MPI环境。正因为有十多年没折腾了,今天在内部多台电脑上自行部署和运行MPI程序,差点就翻车了。本文稍作记录。

1. 部署MPI环境

如果需要在节点上编译程序,需要安装MPI编译器及开发包。主流的两个MPI实现有OpenMPI和MPICH,采用哪个可根据项目需求或者个人爱好来选择。因为为之前使用OpenMPI有不好的体验,另外MPICH支持Windows,所以本人更倾向于使用MPICH

在Ubuntu/Debian上安装MPICH非常简单:apt install mpich。注意需要在所有运行程序的节点上安装MPI环境。

有了编译和运行环境,另外一个主要内容是要配置NFS文件系统。除非你有每个节点都能访问的共享盘,否则NFS必要的:例如程序要读取 /home/xxx/xxx.dat,最笨的方法是每个节点都复制一份,更好的方法是共用同一份。因为读可以复制和同步,输出的文件多节点复制和同步就更繁琐了。

配置NFS可以参考本文之前折腾的文章: 服务器配置札记(分区调整和NFS服务),也可以问ChatGPT等。一般是主节点做服务端,其它节点做客户端,所有节点共用相同的路径,可同时对文件进行读写。

最后需要做的就是做节点间的免密登录。操作也很简单:用 ssh-keygen 生成公钥和密钥,然后使用 ssh-copy-id 分发到各个子节点即可。

有了MPI编译运行环境,加上所有节点可以共享同一个路径及文件,运行MPI程序就已经准备好了。

2. 跨节点MPI的两个问题

这里主要记录一下本次跨节点运行MPI程序的两个问题。

第一个问题是动态库的加载问题。根据 mpiexec 的说明,会自动把环境变量传递到各个子进程,但实际测试并不是。在主节点设置 LD_LIBRARY_PATH 环境变量,本机运行没有问题,其它节点运行就会提示某些 so 库无法加载。在其它节点上编辑 ~/.bashrc 文件配置环境变量,情况照旧,还是无法找到程序目录下的 so 文件。

最后的解决办法是通过ssh完成:创建 .ssh/environment 文件,按照 key=value 的格式导出需要同步的环境变量,然后编辑 /etc/ssh/sshd_config 文件,设置 PermitUserEnvironment yes,重启 ssh 就好了。

虽然解决了问题,但是这个解决方案很别扭,应该有更好的解决方法。

第二个问题是创建子通讯子的问题。程序运行时,只要有 MPI_Comm_dup 调用就会崩掉。为了迅速解决问题,刚开始把程序中的相关调用关了。但没想到第三方库中也调用了这个函数,运行到特点时间点还是会崩。

终于在某个帖子下面,发现使用 mpiexec 时,不能使用主机名指定运行的节点,需要直接写ip才行。例如在两个节点运行,mpiexec -host node1,node2,这样就会崩,但是写成 mpiexec -h 192.168.0.2,192.168.0.3 就没问题。但是,假如只在单节点上运行, mpiexec -host node2 ,这样运行是没问题的。目前发现几个MPICH版本都有这个问题,不知道是bug还是说本来就应该用ip。

3. 总结

今天匆忙中部署了多节点的MPI运行环境,虽然成功的让程序跑起来没问题,但是解决方法太异于寻常,不知道算坑还是准备不足。欣慰的是,没耽误正常下班~