spark-vllm-docker 集群网络配置
DGX Spark 网络配置
以下指南从双节点集群开始,但同样适用于更大的集群。
6-8 节点 Spark 集群的示例请参见这篇帖子。
请记住,张量并行的 vLLM 部署通常在节点数为 2 的幂(例如 2、4 或 8 个节点)时效果最好。3 节点 mesh 主要用于流水线并行或数据并行。
本指南假设节点命名为 spark 和 spark2,但你可以使用任何名称。
IP 地址也是如此:我们使用 192.168.177.0/24 子网,为两个节点分别分配 .11 和 .12,但你可以使用任何 IP 地址,只要它们在同一子网内即可。
DGX Spark ConnectX 的特殊之处
DGX Spark 的 ConnectX 配置相当独特。
要达到 200G 的传输速度,ConnectX 网卡需要约 x8 条 PCIe 5.0 通道。
然而,由于硬件限制,DGX Spark SOC 每个设备最多只能提供 x4 条 PCIe 通道。
因此,为了在单线缆连接上达到 200G,每个物理端口共享同一对 PCIe5 x4 连接。
每条 PCIe 5 x4 链路由两个以太网接口和两个 RoCE 接口表示:
eugr@spark:~$ ibdev2netdev
rocep1s0f0 port 1 ==> enp1s0f0np0 (Down)
rocep1s0f1 port 1 ==> enp1s0f1np1 (Up)
roceP2p1s0f0 port 1 ==> enP2p1s0f0np0 (Down)
roceP2p1s0f1 port 1 ==> enP2p1s0f1np1 (Up)
在这种情况下,单根线缆插在靠外侧的 QSFP 端口(从背面看是右侧那个)。
该端口关联了两对"孪生"接口:
- 以太网:
enp1s0f1np1和enP2p1s0f1np1 - RoCE/IB:
rocep1s0f1和roceP2p1s0f1
每个孪生接口代表一条 PCIe x4 链路,可提供最高 100G 的链路速度。
对于 vLLM,我们需要 RoCE 之上的 RDMA,因此以太网速度并不那么重要,这就是为什么我们可以只给其中一个端口分配 IP - 在本例中是 enp1s0f1np1。
然而,要在 NCCL RDMA 模式下获得完整带宽,我们需要同时利用两个 RoCE 孪生接口。通过将 NCCL_IB_HCA 设置为两个 RoCE 接口来实现:export NCCL_IB_HCA=rocep1s0f1,roceP2p1s0f1
./launch-cluster.sh 会自动完成这项设置,连同接口的自动发现一起,所以只要你正确配置了以太网接口,vLLM 就会利用两个 RoCE 孪生接口。
另外,请注意,使用两个端口连接两台 Spark 并不会带来明显的带宽优势,因此单连接就足够了。
如果你通过菊花链方式连接 3 台 Spark,每对 Spark 之间只能维持 100G。
不使用交换机将 3 台 Spark 连接成 mesh 集群
三台 Spark 可以在不使用独立 RoCE 交换机的情况下连接成集群。
但是,所有三台 Spark 都需要通过其 10G 以太网端口(RJ-45,不是 QSFP)处于同一个有线网络中。处于同一无线网络应该也可以,但不推荐,且未经测试。
你需要确保它们按以下方式连接:一台 Spark 的 port 0 应连接到另一台 Spark 的 port 1(与非 mesh 配置不同)。
示意图示例:
使用交换机在集群中连接超过 2 台 Spark
要连接超过 2 台 Spark,你需要一台合适的交换机,例如 Microtik CRS812-DDQ 或 Mikrotik CRS804-DDQ。
搭建 6-8 节点 Spark 集群的示例请参考这篇帖子。
网络配置
双 Spark 或使用 QSFP 交换机的多台 Spark
假设两者都使用靠右侧的 QSFP 端口连接(从背面看)。
在 spark 上创建 /etc/netplan/40-cx7.yaml:
network:
version: 2
ethernets:
enp1s0f1np1:
dhcp4: no
dhcp6: no # 显式禁用 DHCPv6
link-local: [] # 将 link-local 地址限制为仅静态 IPv4
mtu: 9000
addresses: [192.168.177.11/24]
enP2p1s0f1np1:
dhcp4: no
dhcp6: no
link-local: []
mtu: 9000
addresses: [192.168.178.11/24]
在 spark2 上创建 /etc/netplan/40-cx7.yaml:
network:
version: 2
ethernets:
enp1s0f1np1:
dhcp4: no
dhcp6: no # 显式禁用 DHCPv6
link-local: [] # 将 link-local 地址限制为仅静态 IPv4
mtu: 9000
addresses: [192.168.177.12/24]
enP2p1s0f1np1:
dhcp4: no
dhcp6: no
link-local: []
mtu: 9000
addresses: [192.168.178.12/24]
不要在两个"孪生"接口上使用相同的子网 - 这会干扰自动发现并搞乱路由。
然后在每个节点上运行:
sudo chmod 600 /etc/netplan/40-cx7.yaml
sudo netplan apply
设置免密码 ssh。在 spark 上:
wget https://raw.githubusercontent.com/NVIDIA/dgx-spark-playbooks/refs/heads/main/nvidia/connect-two-sparks/assets/discover-sparks
chmod +x discover-sparks
./discover-sparks
MTU 设置(测试):
sudo ip link set dev enp1s0f1np1 mtu 9000
3 节点 mesh
3 节点 mesh 的配置方式与双机集群或使用 QSFP 交换机的集群不同。
假设你的 Spark 按照上面的示意图连接:
在 spark1 上创建 /etc/netplan/40-cx7.yaml:
network:
version: 2
ethernets:
enp1s0f0np0:
dhcp4: no
dhcp6: no # 显式禁用 DHCPv6
link-local: [] # 将 link-local 地址限制为仅静态 IPv4
mtu: 9000
addresses: [192.168.177.11/24]
enP2p1s0f0np0:
dhcp4: no
dhcp6: no
link-local: []
mtu: 9000
addresses: [192.168.178.11/24]
enp1s0f1np1:
dhcp4: no
dhcp6: no # 显式禁用 DHCPv6
link-local: [] # 将 link-local 地址限制为仅静态 IPv4
mtu: 9000
addresses: [192.168.187.11/24]
enP2p1s0f1np1:
dhcp4: no
dhcp6: no
link-local: []
mtu: 9000
addresses: [192.168.188.11/24]
在 spark2 上创建 /etc/netplan/40-cx7.yaml:
network:
version: 2
ethernets:
enp1s0f0np0:
dhcp4: no
dhcp6: no # 显式禁用 DHCPv6
link-local: [] # 将 link-local 地址限制为仅静态 IPv4
mtu: 9000
addresses: [192.168.197.12/24]
enP2p1s0f0np0:
dhcp4: no
dhcp6: no
link-local: []
mtu: 9000
addresses: [192.168.198.12/24]
enp1s0f1np1:
dhcp4: no
dhcp6: no # 显式禁用 DHCPv6
link-local: [] # 将 link-local 地址限制为仅静态 IPv4
mtu: 9000
addresses: [192.168.177.12/24]
enP2p1s0f1np1:
dhcp4: no
dhcp6: no
link-local: []
mtu: 9000
addresses: [192.168.178.12/24]
在 spark3 上创建 /etc/netplan/40-cx7.yaml:
network:
version: 2
ethernets:
enp1s0f0np0:
dhcp4: no
dhcp6: no # 显式禁用 DHCPv6
link-local: [] # 将 link-local 地址限制为仅静态 IPv4
mtu: 9000
addresses: [192.168.187.13/24]
enP2p1s0f0np0:
dhcp4: no
dhcp6: no
link-local: []
mtu: 9000
addresses: [192.168.188.13/24]
enp1s0f1np1:
dhcp4: no
dhcp6: no # 显式禁用 DHCPv6
link-local: [] # 将 link-local 地址限制为仅静态 IPv4
mtu: 9000
addresses: [192.168.197.13/24]
enP2p1s0f1np1:
dhcp4: no
dhcp6: no
link-local: []
mtu: 9000
addresses: [192.168.198.13/24]
然后运行(在每台 Spark 上):
sudo chmod 600 /etc/netplan/40-cx7.yaml
sudo netplan apply
免密码 SSH 和基准测试
设置免密码 ssh。在第一台 spark 上:
wget https://raw.githubusercontent.com/NVIDIA/dgx-spark-playbooks/refs/heads/main/nvidia/connect-two-sparks/assets/discover-sparks
chmod +x discover-sparks
./discover-sparks
连接基准测试(使用 perftest 包):
在 spark2 节点上运行接收端:
ib_write_bw -d rocep1s0f1 --report_gbits -q 4 -R --force-link IB
然后在 spark 上运行:
$ ib_write_bw 192.168.177.12 -d rocep1s0f1 --report_gbits -q 4 -R --force-link IB
---------------------------------------------------------------------------------------
RDMA_Write BW Test
Dual-port : OFF Device : rocep1s0f1
Number of qps : 4 Transport type : IB
Connection type : RC Using SRQ : OFF
PCIe relax order: ON
ibv_wr* API : ON
TX depth : 128
CQ Moderation : 1
Mtu : 1024[B]
Link type : IB
Max inline data : 0[B]
rdma_cm QPs : ON
Data ex. method : rdma_cm
---------------------------------------------------------------------------------------
local address: LID 0000 QPN 0x03ec PSN 0xb680ae
local address: LID 0000 QPN 0x03ed PSN 0x808800
local address: LID 0000 QPN 0x03ee PSN 0x5b694a
local address: LID 0000 QPN 0x03ef PSN 0xe2efd1
remote address: LID 0000 QPN 0x03eb PSN 0x75f6ee
remote address: LID 0000 QPN 0x03ec PSN 0x436140
remote address: LID 0000 QPN 0x03ed PSN 0x81698a
remote address: LID 0000 QPN 0x03ee PSN 0x4a8b11
---------------------------------------------------------------------------------------
#bytes #iterations BW peak[Gb/sec] BW average[Gb/sec] MsgRate[Mpps]
65536 20000 111.72 111.71 0.213070
---------------------------------------------------------------------------------------
延迟测试:
在 spark2 节点上运行接收端:
ib_write_lat -d rocep1s0f1 --report_gbits -R --force-link IB
然后在 spark 上运行:
ib_write_lat 192.168.177.12 -d rocep1s0f1 --report_gbits -R --force-link IB
---------------------------------------------------------------------------------------
RDMA_Write Latency Test
Dual-port : OFF Device : rocep1s0f1
Number of qps : 1 Transport type : IB
Connection type : RC Using SRQ : OFF
PCIe relax order: OFF
ibv_wr* API : ON
TX depth : 1
Mtu : 1024[B]
Link type : IB
Max inline data : 220[B]
rdma_cm QPs : ON
Data ex. method : rdma_cm
---------------------------------------------------------------------------------------
local address: LID 0000 QPN 0x02ee PSN 0xb0c21c
remote address: LID 0000 QPN 0x02ee PSN 0x14568b
---------------------------------------------------------------------------------------
#bytes #iterations t_min[usec] t_max[usec] t_typical[usec] t_avg[usec] t_stdev[usec] 99% percentile[usec] 99.9% percentile[usec]
2 1000 1.42 1.93 1.47 1.47 0.00 1.57 1.93
---------------------------------------------------------------------------------------
NCCL 测试
双 Spark 或通过 QSFP 交换机连接的 Spark
来自 https://build.nvidia.com/spark/nccl/stacked-sparks
# 安装依赖并构建 NCCL
sudo apt-get update && sudo apt-get install -y libopenmpi-dev
git clone -b v2.30u1 https://github.com/NVIDIA/nccl.git ~/nccl/
cd ~/nccl/
make -j src.build NVCC_GENCODE="-gencode=arch=compute_121,code=sm_121"
# 设置环境变量
export CUDA_HOME="/usr/local/cuda"
export MPI_HOME="/usr/lib/aarch64-linux-gnu/openmpi"
export NCCL_HOME="$HOME/nccl/build/"
export LD_LIBRARY_PATH="$NCCL_HOME/lib:$CUDA_HOME/lib64/:$MPI_HOME/lib:$LD_LIBRARY_PATH"
构建 NCCL 测试套件:
# 克隆并构建 NCCL 测试
git clone https://github.com/NVIDIA/nccl-tests.git ~/nccl-tests/
cd ~/nccl-tests/
make MPI=1
在两个节点上测试:
# 设置网络接口环境变量(使用你的活动接口)
export UCX_NET_DEVICES=enp1s0f1np1
export NCCL_SOCKET_IFNAME=enp1s0f1np1
export OMPI_MCA_btl_tcp_if_include=enp1s0f1np1
export NCCL_IB_HCA=rocep1s0f1,roceP2p1s0f1
export NCCL_IB_DISABLE=0
# 在两个节点上运行 all_gather 性能测试
mpirun -np 2 -H 192.168.177.11:1,192.168.177.12:1 \
--mca plm_rsh_agent "ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no" \
-x LD_LIBRARY_PATH=$LD_LIBRARY_PATH \
$HOME/nccl-tests/build/all_gather_perf -b 16G -e 16G -f 2
3 节点 mesh
# 安装依赖并构建 NCCL
sudo apt-get update && sudo apt-get install -y libopenmpi-dev
git clone -b v2.30u1 https://github.com/NVIDIA/nccl.git ~/nccl/
cd ~/nccl/
make -j src.build NVCC_GENCODE="-gencode=arch=compute_121,code=sm_121"
# 设置环境变量
export CUDA_HOME="/usr/local/cuda"
export MPI_HOME="/usr/lib/aarch64-linux-gnu/openmpi"
export NCCL_HOME="$HOME/nccl/build/"
export LD_LIBRARY_PATH="$NCCL_HOME/lib:$CUDA_HOME/lib64/:$MPI_HOME/lib:$LD_LIBRARY_PATH"
构建 NCCL 测试套件:
# 克隆并构建 NCCL 测试
git clone https://github.com/NVIDIA/nccl-tests.git ~/nccl-tests/
cd ~/nccl-tests/
make MPI=1
在所有三个节点上测试(将 spark1、spark2 和 spark3 替换为非 QSFP 接口上的实际主机名或 IP 地址):
# 设置环境变量
export CUDA_HOME="/usr/local/cuda"
export MPI_HOME="/usr/lib/aarch64-linux-gnu/openmpi"
export NCCL_HOME="$HOME/nccl/build/"
export LD_LIBRARY_PATH="$NCCL_HOME/lib:$CUDA_HOME/lib64/:$MPI_HOME/lib:$LD_LIBRARY_PATH"
# 对于 3 节点 mesh,OOB 通信必须使用 10G 接口!
export UCX_NET_DEVICES=enP7s7
export NCCL_SOCKET_IFNAME=enP7s7
export OMPI_MCA_btl_tcp_if_include=enP7s7
export NCCL_IB_HCA=rocep1s0f0,roceP2p1s0f0,rocep1s0f1,roceP2p1s0f1
export NCCL_IB_DISABLE=0
# 在所有三个节点上运行 all_gather 性能测试
mpirun -np 3 -H spark1:1,spark2:1,spark3:1 \
--mca plm_rsh_agent "ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no" \
-x LD_LIBRARY_PATH=$LD_LIBRARY_PATH -x NCCL_IB_MERGE_NICS=0 -x NCCL_NET_PLUGIN=none -x NCCL_IB_SUBNET_AWARE_ROUTING=1 \
$HOME/nccl-tests/build/all_gather_perf -b 16G -e 16G -f 3 最后更新于 2026-08-13 23:12:14 并被添加「」标签,已有 41 位童鞋阅读过。
本站使用「署名 4.0 国际」创作共享协议,可自由转载、引用,但需署名作者且注明文章出处
此处评论已关闭