MPI 程序造成网络负载过重后,Ubuntu 22.04 中的 TCP/IP 网络变得无响应

MPI 程序造成网络负载过重后,Ubuntu 22.04 中的 TCP/IP 网络变得无响应

我有两台运行 Ubuntu 22.04.3 LTS 的相同服务器。两个系统均配备 2 个 AMD 9654 CPU,共有 192 个内核和 512 GB RAM。每台服务器的主板上内置有两个 10G 以太网端口。这些 10G 端口配置为使用 netplan 创建单个链路聚合。

整个网络配置在正常负载下运行良好。以下是第一台服务器 (Thor) 的 $ip a 的输出:

Thor$ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: Ethernet-10G-1: <BROADCAST,MULTICAST,SLAVE,UP,LOWER_UP> mtu 1500 qdisc mq master Bond-10G state UP group default qlen 1000
    link/ether 00:00:00:00:00:04 brd ff:ff:ff:ff:ff:ff permaddr a0:36:bc:c8:c6:9b
    altname enp15s0f0
3: Ethernet-10G-2: <BROADCAST,MULTICAST,SLAVE,UP,LOWER_UP> mtu 1500 qdisc mq master Bond-10G state UP group default qlen 1000
    link/ether 00:00:00:00:00:04 brd ff:ff:ff:ff:ff:ff permaddr a0:36:bc:c8:c6:9c
    altname enp15s0f1
4: Bond-10G: <BROADCAST,MULTICAST,MASTER,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 00:00:00:00:00:04 brd ff:ff:ff:ff:ff:ff
    inet 10.0.1.203/22 brd 10.0.3.255 scope global dynamic noprefixroute Bond-10G
       valid_lft 31554381sec preferred_lft 31554381sec
    inet6 fe80::200:ff:fe00:4/64 scope link 
       valid_lft forever preferred_lft forever

以下是正常情况下从第一台服务器到第二台服务器 (Loki) 的 ping 输出:

Thor$ ping loki
PING loki.elliptic.loc (10.0.1.204) 56(84) bytes of data.
64 bytes from Loki.elliptic.loc (10.0.1.204): icmp_seq=1 ttl=64 time=0.139 ms

这表明延迟很低,为 139 微秒。两台服务器都连接到同一台交换机,即 Netgear XS728T 28 端口 10 Gigabit L2+ 智能交换机。我还使用 iperf 进行了网络测试。结果(此处未显示,但如果有用则可用)确认两台主机之间的持续带宽为 10.0 GB/秒。

现在谈谈我的问题。我是应用数学专业的博士生,我使用这些服务器来运行大规模数值模拟代码。仿真程序采用MPI。我已经测试过这个程序,它一次可以在一台主机上的 192 个内核上完美运行。如果我使用少量核心(例如每个核心 8 个),我还可以在两台主机上运行该程序。但是,当我尝试使用大量内核运行它时,MPI 程序会挂起,因为它丢失了进程之间的 TCP 连接。以下是我尝试在每台主机上的 192 个核心(总共 384 个核心)上运行它但失败时的错误输出示例:

WARNING: Open MPI failed to TCP connect to a peer MPI process.  This
should not happen.

Your Open MPI job may now hang or fail.

  Local host: Thor
  PID:        8076
  Message:    connect() to 10.0.1.204:1162 failed
  Error:      No route to host (113)

此外,即使在 MPI 程序终止后,一台或两台服务器上的 IP 网络也不再起作用。在网络出现故障后,我可以使用带外 IPMI 工具来访问服务器。一旦 TCP/IP 网络失效,对 ping 的调用将导致错误消息“目标主机无法访问”。在这种状态下,机器甚至无法 ping 通路由器或网络交换机。在这种情况下我能够恢复它的唯一方法是完全重新启动。

在这种情况下,我检查了远程服务器上 $ip a 的输出,它看起来与它开始的位置相同。如果我遗漏了什么,我会将其粘贴在下面:

Loki $ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: Ethernet-10G-1: <BROADCAST,MULTICAST,SLAVE,UP,LOWER_UP> mtu 1500 qdisc mq master Bond-10G state UP group default qlen 1000
    link/ether 00:00:00:00:00:05 brd ff:ff:ff:ff:ff:ff permaddr a0:36:bc:c8:c7:2b
    altname enp15s0f0
3: Ethernet-10G-2: <BROADCAST,MULTICAST,SLAVE,UP,LOWER_UP> mtu 1500 qdisc mq master Bond-10G state UP group default qlen 1000
    link/ether 00:00:00:00:00:05 brd ff:ff:ff:ff:ff:ff permaddr a0:36:bc:c8:c7:2c
    altname enp15s0f1
4: Bond-10G: <BROADCAST,MULTICAST,MASTER,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 00:00:00:00:00:05 brd ff:ff:ff:ff:ff:ff
    inet 10.0.1.204/22 brd 10.0.3.255 scope global dynamic noprefixroute Bond-10G
       valid_lft 31555883sec preferred_lft 31555883sec
    inet6 fe80::200:ff:fe00:5/64 scope link 
       valid_lft forever preferred_lft forevera

我已经取得了一些小进步,这让我相信问题与 TCP 网络无法跟上快速创建的许多连接的负载并发送大量流量有关。通读 OpenMPI 文档,我看到一些提示:应该调整几个 Linux 内核参数才能在 10 GB TCP/IP 网络上运行 MPI。我将这些更改输入到 /etc/sysctl.d/21-net.conf 中,如下所示:

net.core.rmem_max               = 16777216
net.core.wmem_max               = 16777216
net.ipv4.tcp_rmem               = 4096 87380 16777216
net.ipv4.tcp_wmem               = 4096 65536 16777216
net.core.netdev_max_backlog     = 30000
net.core.rmem_default           = 16777216
net.core.wmem_default           = 16777216
net.ipv4.tcp_mem                = 16777216 16777216 16777216
net.ipv4.route.flush            = 1

在进行这些更改之前,我什至无法让程序在每个节点上运行 8 个 MPI 进程。进行更改后,每个节点上可以运行 32 个 MPI 进程。我又进行了一轮更改,并进一步增加了它们,将 net.core.rmem_max 和 net.ipv4.tcp_mem 提高到最大值 2^31-1。通过此更改,该程序能够在两台主机上的每台主机上的 128 个核心上运行,但当我尝试使用所有 192 个核心时仍然挂起。

这是最后一个数据点。我使用我的博士导师提供的两台完全不同的计算机重复了这个测试。它们有点旧,每个都有 28 个 CPU,运行 Ubuntu 20.04 LTS。一切都处于完全典型的配置中:没有任何网络绑定的千兆位网络。我能够准确地复制我的机器上遇到的问题。唯一的区别是旧机器在每个节点上只有 8 个 MPI 进程的网络负载下不堪重负。

这是我的直觉。 MPI 使用共享内存在同一节点上的进程之间进行通信。它非常快并且不会给 TCP/IP 网络带来任何负载。跨不同节点的一对 MPI 进程之间的每个连接都需要一个套接字和一个 TCP 连接。当在多个内核上运行大型模拟时,这会给 TCP/IP 网络带来巨大的负载。增加缓冲区大小会有所帮助,但仍然很慢并且容易使 TCP 网络完全崩溃。我认为这是 HPC 世界中的一种边缘情况,因为大多数大型超级计算集群都使用更快的网络解决方案,例如 Infiniband。我还没有遇到任何其他人试图通过 10 GB 以太网扩展到 1000 个 CPU。

如果 Stack Exchange 上有人熟悉此类问题并有任何建议,我将非常感激。我现在是博士课程的第四年,我已经花了两周多的时间来解决这个问题。非常感谢一位长期会员。

-迈克尔

相关内容