问题及原因
在多网卡的情况下,有时候使用多个服务器作为MPI节点时会出现:
1. MPI_Recv之类的读函数读不到任何数据,
2. 或 MPI崩溃并提示无法connect to XXXX,这个XXXX多半是某个配属在其他网段的IP地址。
这是因为:
MPI默认选择了一个错误的网段尝试进行多机通讯,导致程序交互的失败。
例如:
某台机器的网络配置如下:
lo 127.0.0.1
eth0 192.168.0.2/24
eth1 10.11.13.14/24
其中eth0为内网IP地址,也是各个服务器间通讯时希望使用的网卡。eth1为一个公网IP地址,用于远程登录之类任务。假设内网中有两台这样的服务器a和b,内网IP分别为:192.168.0.11和192.168.0.22,并且都已经写入了各自的host文件。
当使用:mpirun -n 2 –host a,b program.exe 在机器a和机器b上同时启动MPI程序program.exe时,MPI系统可能会默认选择eth1网络,试图在10.11.13.14/24网络上寻找另一方,结果自然运行失败。
解决方法
在启动MPI时明确指明要使用的网卡或网段。
OpenMPI
详细说明请参见 https://www.open-mpi.org/faq/?category=tcp#tcp-selection
默认网卡选择方式
默认情况下,OpenMPI会尝试选择使用所有启动的网络设备(自环虚拟设备lo/loopback除外),但是能不能选对就不能保证了。默认情况下可能导致网卡指定错误,所以还是要显示的指定网卡。
显式指定方法
使用 btl_tcp_if_include 或 btl_tcp_if_exclude 选项启动MPI,来制定使用的或排除的网络设备。
例如
# This says to not use the eth0 and lo interfaces.
# (and implicitly use all the rest) Per the description
# above, IP loopback and all local-only devices *must*
# be included if the exclude list is specified.
shell$ mpirun --mca btl_tcp_if_exclude lo,eth0 ...
# This says to only use the eth1 and eth2 interfaces
# (and implicitly ignore the rest)
shell$ mpirun --mca btl_tcp_if_include eth1,eth2 ...
OpenMPI 1.5 开始,上述选项支持使用IP地址而不是设备名称来作为参数,例如:
# Only use the 192.168.1.0/24 and 10.10.0.0/16 subnets for MPI
# communications:
shell$ mpirun --mca btl_tcp_if_include 192.168.1.0/24,10.10.0.0/16 ...
MPICH/MPICH2
有很多基于MPICH开发的其他MPI实现,例如:的MSMPI,他们的基本特点都是一致的。
详细说明请参见: https://www.mpich.org/static/downloads/1.2.1p1/mpich2-1.2.1p1-README.txt 的IX. Environment Variables 部分。
默认网卡选择方式
MPICH默认会选择本机hostname所在的网段对应的网卡(由gethostbyname函数获取)。
显式指定方法
使用环境变量MPICH_INTERFACE_HOSTNAME,将之设置为所需要的网段的一个IP地址,通常是自己的IP地址。
通常也可以使用-env选项,直接在mpirun命令中设置它,例如:
mpiexec -np 1 -env MPICH_INTERFACE_HOSTNAME 192.168.0.11
program.exe
另外,也可以只用诸如MPICH_INTERFACE_HOSTNAME_R0、MPICH_INTERFACE_HOSTNAME_R1、MPICH_INTERFACE_HOSTNAME_R2的方式为每一个rank制定一个网卡。