如题:
最近在看MPI方面的东西,主要是Python下的MPI4PY,学校有超算机房可以使用MPI,但是需要申请什么的比较麻烦,目的也本就是为了学习一下,所以就想着在自己的电脑上先配置一下。
现有硬件:两台装有Ubuntu18.04的操作系统(下面简称A电脑,B电脑)
A电脑: 24物理核心(48逻辑核心)
B电脑:6物理核心(12逻辑核心)
网络:
A、B电脑之间使用100M以太网交换机连接(就是TP-Link路由器)。
A、B电脑上都装有docker并且有多个物理网卡,因此各个电脑的网络情况比较复杂,具体:
A电脑网络配置:
docker0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500 inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255 ether 02:42:78:17:6c:07 txqueuelen 0 (Ethernet) RX packets 0 bytes 0 (0.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 0 bytes 0 (0.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 enp7s0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 10.105.219.170 netmask 255.255.0.0 broadcast 10.105.255.255 inet6 2001:da8:a800:af00:2e4d:54ff:fe44:a14b prefixlen 64 scopeid 0x0<global> inet6 fe80::2e4d:54ff:fe44:a14b prefixlen 64 scopeid 0x20<link> ether 2c:4d:54:44:a1:4b txqueuelen 1000 (Ethernet) RX packets 2892225 bytes 321651342 (321.6 MB) RX errors 0 dropped 3 overruns 0 frame 0 TX packets 251303 bytes 155089869 (155.0 MB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 device memory 0xc6400000-c647ffff enp8s0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 192.168.11.66 netmask 255.255.255.0 broadcast 192.168.11.255 inet6 fe80::2e4d:54ff:fe44:a14c prefixlen 64 scopeid 0x20<link> inet6 2001:da8:a800:af00:2e4d:54ff:fe44:a14c prefixlen 64 scopeid 0x0<global> ether 2c:4d:54:44:a1:4c txqueuelen 1000 (Ethernet) RX packets 3260138 bytes 1003925411 (1.0 GB) RX errors 66178 dropped 3 overruns 0 frame 53701 TX packets 319204 bytes 22576077 (22.5 MB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 device memory 0xc6300000-c637ffff lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536 inet 127.0.0.1 netmask 255.0.0.0 inet6 ::1 prefixlen 128 scopeid 0x10<host> loop txqueuelen 1000 (Local Loopback) RX packets 42491 bytes 26674547 (26.6 MB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 42491 bytes 26674547 (26.6 MB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
B电脑:
docker0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500 inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255 ether 02:42:b9:51:8d:33 txqueuelen 0 (以太网) RX packets 0 bytes 0 (0.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 0 bytes 0 (0.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 enp5s0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 10.105.246.82 netmask 255.255.0.0 broadcast 10.105.255.255 inet6 2001:da8:a800:af00:645d:7de8:7fe8:99e9 prefixlen 64 scopeid 0x0<global> inet6 2001:da8:a800:af00:61f7:413d:2daf:e00a prefixlen 64 scopeid 0x0<global> inet6 fe80::4ed5:7f18:afc3:59e4 prefixlen 64 scopeid 0x20<link> ether 94:c6:91:7e:20:24 txqueuelen 1000 (以太网) RX packets 2824242 bytes 259143858 (259.1 MB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 62606 bytes 48094535 (48.0 MB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 enx000ec6c08c64: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 192.168.11.206 netmask 255.255.255.0 broadcast 192.168.11.255 inet6 fe80::a036:3b28:aad9:62ac prefixlen 64 scopeid 0x20<link> inet6 2001:da8:a800:af00:531e:f6f1:a573:9dbc prefixlen 64 scopeid 0x0<global> inet6 2001:da8:a800:af00:a15e:c952:ce3e:f155 prefixlen 64 scopeid 0x0<global> ether 00:0e:c6:c0:8c:64 txqueuelen 1000 (以太网) RX packets 3089507 bytes 227967288 (227.9 MB) RX errors 0 dropped 2977 overruns 0 frame 0 TX packets 549163 bytes 822545241 (822.5 MB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536 inet 127.0.0.1 netmask 255.0.0.0 inet6 ::1 prefixlen 128 scopeid 0x10<host> loop txqueuelen 1000 (本地环回) RX packets 45005 bytes 13777274 (13.7 MB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 45005 bytes 13777274 (13.7 MB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
其中,A、B电脑的各自两个网卡均处在两个局域网中,即:192.168.11.0/24 , 10.105.0.0/24 。
在子网:192.168.11.0/24 中,
A电脑网卡:enp8s0 , B电脑网卡:enx000ec6c08c64
在子网:10.105.0.0/24 中,
A电脑网卡:enp7s0 , B电脑网卡:enp5s0
为举例说明,使用下面的MPI4PY代码:
from mpi4py import MPI import numpy as np comm = MPI.COMM_WORLD size = comm.Get_size() rank = comm.Get_rank() sendbuf = np.zeros(100*10000, dtype='i') + rank recvbuf = None if rank == 0: recvbuf = np.empty([size, 100*10000], dtype='i') print( MPI.Get_processor_name() ) import time a = time.time() for _ in range(1): comm.Gather(sendbuf, recvbuf, root=0) b = time.time() if rank == 0: print(b-a)
代码意思比较简单,不进行信息pickle和unpickle情况下做个信息收集gather操作。
本文前提假设已经安装好了openmpi及mpi4py,单机环境已经配置好。A、B两电脑之间免密码ssh登录也已经配置好,本文不对此进行介绍。
说明:
本文只是学习目的,没有实际生成价值意义,毕竟分布式mpi大家都是用几千上万的infiband网络连接,而不会使用3元、5元一米网线的以太网TCP连接。
=============================================================
最初的运行方式:
mpiexec -np 8 -host 192.168.11.66:4 -host 192.168.11.206:4 python x.py
报错:
WARNING: Open MPI accepted a TCP connection from what appears to be a
another Open MPI process but cannot find a corresponding process
entry for that peer.
This attempted connection will be ignored; your MPI job may or may not
continue properly.
[[61134,1],0][btl_tcp_endpoint.c:626:mca_btl_tcp_endpoint_recv_connect_ack] received unexpected process identifier [[61134,1],2]
[[61134,1],0][btl_tcp_endpoint.c:626:mca_btl_tcp_endpoint_recv_connect_ack] received unexpected process identifier [[61134,1],1]
=======================================================
如上面运行的报错,引出了一个问题:多网卡系统下如何使用tcp协议实现MPI的分布式多机运行
如题所述,在单网卡的环境中多个电脑都配置好了openmpi,mpi4py等软件,而且在各个电脑上都有相同的用户,运行文件都存在相同的路径下,Python的运行路径也都相同,各个电脑之间也都配置好了免密登录,那么运行代码自然不会出现上述的问题,但是如果你的电脑上每个电脑都不是只有一个网卡呢,就像本文中每台电脑均有两个物理网卡并且均有一个虚拟网卡,这个情况下如果运行代码就会上面的错误。为什么多个电脑之间使用mpi,如果只有一个网卡就不报错,而电脑如果有超过一个网卡的话就会报错呢???
最终找到了答案,具体看下面的相关讨论:
相关讨论:
https://www.javaroad.cn/questions/122550
相关资料:
https://blog.csdn.net/ljhandlwt/category_6317687.html
==========================================================
从上面的讨论可以知道使用mpi的时候如果不设置主机之间通信使用的具体网卡或网段,mpi会对所有网卡均进行通信尝试,从而造成错误。
那么使用mpi在多机分布式使用tcp协议的时候如果主机有多个网卡该如何设置呢???下面给出几种解决方法:
1. 运行时通过设置参数指定运行的网段
设置参数: --mca btl_tcp_if_include 192.168.11.0/24
上文可以知道网络中的主机A、B之间其实是存在两个局域网互联的,网段分别为:192.168.11.0/24,10.105.0.0/16
如果不指定具体使用的网段那么A、B主机会对这两个网段均进行通信尝试,这时可能会出现A主机在网段192.168.11.0/24上对B通信,而此时B在网段10.105.0.0/16上工作,从而导致报错。设定工作的具体网段后A、B主机均会使用该网段通信,从而避免了上述的错误。
这里我们的具体运行命令为:
mpirun --mca btl_tcp_if_include 192.168.11.0/24 -np 8 -host 192.168.11.66:4 -host 192.168.11.206:4 /home/xxxxxx/anaconda3/bin/python x.py
2. 通过mpi配置文件指定工作的具体网卡:
在当前linux用户的home文件夹下建立 .openmpi 文件夹,并在~/.openmpi 文件夹下面建立openmpi配置文件 mca-params.conf 并为其编写配置:
~/.openmpi/mca-params.conf
分别在A、B两个主机上对应的配置文件上添加内容:
主机A 192.168.11.66 对应网卡enp8s0
btl_tcp_if_include=enp8s0
主机B 192.168.11.206 对应网卡 enx000ec6c08c64
btl_tcp_if_include=enx000ec6c08c64
此时执行运行命令:
mpirun -np 8 -host 192.168.11.66:4 -host 192.168.11.206:4 /home/xxxxxx/anaconda3/bin/python x.py
以上两种方法均可解决mpi在多机分布式使用tcp协议的多网卡主机通信报错问题。