高速互联 InfiniBand
InfiniBand 基础
InfiniBand(IB)是专为高性能计算设计的高速网络互联技术,提供极低延迟和极高带宽。
InfiniBand vs 以太网:
指标 InfiniBand HDR 25GbE RoCE 100GbE RoCE
带宽 200Gbps 25Gbps 100Gbps
延迟 ~600ns ~1-2μs ~1μs
CPU 开销 极低(RDMA) 低(RDMA) 低(RDMA)
协议 原生 RDMA RoCE v2 RoCE v2
成本 高 低 中
适用场景 HPC/AI 训练 通用 大规模 AIInfiniBand 网络架构
胖树(Fat-Tree)拓扑
标准 Fat-Tree 拓扑(k=4,16 节点):
核心层(Core):k/2 × k/2 = 4 台交换机
汇聚层(Aggregation):k = 4 个 Pod,每 Pod k/2 = 2 台
接入层(Edge):k = 4 个 Pod,每 Pod k/2 = 2 台
服务器:k³/4 = 16 台
特点:
- 任意两台服务器间:最多 2k-1 跳
- 全双工无阻塞(超额订阅比 1:1)
- 线性扩展
实际大规模部署(k=40,HDR 200Gbps):
核心层:400 台 × 40 端口交换机
汇聚层:800 台 × 40 端口交换机
接入层:800 台 × 40 端口交换机
服务器:16,000 台Dragonfly+ 拓扑(超大规模)
适用:10,000+ 节点的超大规模集群
特点:
- 比 Fat-Tree 使用更少的交换机
- 全局路由,任意两节点 2-3 跳
- 适合 AI 大模型训练集群InfiniBand 安装配置
驱动安装
bash
# 下载 MLNX_OFED 驱动(Mellanox/NVIDIA InfiniBand 驱动)
# 从 NVIDIA 官网下载对应版本
# https://network.nvidia.com/products/infiniband-drivers/linux/mlnx_ofed/
# 安装
tar xf MLNX_OFED_LINUX-23.10-0.5.5.0-rhel8.8-x86_64.tgz
cd MLNX_OFED_LINUX-23.10-0.5.5.0-rhel8.8-x86_64
./mlnxofedinstall --all --force
# 重启 OpenFabrics 服务
/etc/init.d/openibd restart
# 验证安装
ibstat
# 关注:
# State: Active
# Physical state: LinkUp
# Rate: 200 Gb/sec(HDR)
# Link layer: InfiniBand
# 查看 IB 设备
ibv_devinfo子网管理器(Subnet Manager)
bash
# 每个 IB 子网需要一个子网管理器(SM)
# 通常运行在管理节点或 IB 交换机上
# 安装 OpenSM(软件 SM)
yum install -y opensm
# 配置 OpenSM
cat > /etc/opensm/opensm.conf << 'EOF'
# 日志级别
log_flags 0x03
# 优先级(多个 SM 时,优先级高的成为 Master)
sm_priority 15
# 子网前缀
subnet_prefix 0xfe80000000000000
EOF
# 启动 OpenSM
systemctl enable opensm
systemctl start opensm
# 验证 SM 运行
sminfo
# 输出:SM lid 1, SM key 0x0000000000000000, priority 15, state 3 (Master)网络验证
bash
# 查看 IB 网络拓扑
ibnetdiscover | head -50
# 查看所有 IB 节点
ibnodes
# 测试节点间连通性
ibping -G <目标节点GUID>
# 带宽测试
# 服务端
ib_write_bw -d mlx5_0 -i 1 --report_gbits
# 客户端
ib_write_bw -d mlx5_0 -i 1 --report_gbits <server-hostname>
# 延迟测试
ib_write_lat -d mlx5_0 -i 1 <server-hostname>
# 预期结果(HDR 200Gbps):
# 带宽:~23 GB/s(接近理论值 25 GB/s)
# 延迟:~600ns(P50)RDMA 编程
基本 RDMA 操作
c
// RDMA Write 示例(简化版)
#include <infiniband/verbs.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFFER_SIZE (1024 * 1024) // 1MB
int main() {
struct ibv_device **dev_list;
struct ibv_device *ib_dev;
struct ibv_context *ctx;
struct ibv_pd *pd;
struct ibv_mr *mr;
struct ibv_cq *cq;
struct ibv_qp *qp;
char *buffer = malloc(BUFFER_SIZE);
memset(buffer, 0, BUFFER_SIZE);
// 1. 获取 IB 设备列表
dev_list = ibv_get_device_list(NULL);
ib_dev = dev_list[0];
// 2. 打开设备
ctx = ibv_open_device(ib_dev);
// 3. 分配保护域
pd = ibv_alloc_pd(ctx);
// 4. 注册内存区域(允许 RDMA 访问)
mr = ibv_reg_mr(pd, buffer, BUFFER_SIZE,
IBV_ACCESS_LOCAL_WRITE |
IBV_ACCESS_REMOTE_WRITE |
IBV_ACCESS_REMOTE_READ);
printf("内存注册成功\n");
printf(" 虚拟地址: %p\n", buffer);
printf(" 远程密钥: 0x%x\n", mr->rkey);
printf(" 本地密钥: 0x%x\n", mr->lkey);
// ... 创建 QP,连接到远端,执行 RDMA 操作
// 清理
ibv_dereg_mr(mr);
ibv_dealloc_pd(pd);
ibv_close_device(ctx);
ibv_free_device_list(dev_list);
free(buffer);
return 0;
}IB 网络监控
bash
# 监控 IB 端口统计
perfquery -x # 查看所有端口错误计数器
# 关键错误计数器:
# SymbolErrors:符号错误(物理层问题)
# LinkRecovers:链路恢复次数
# LinkDowned:链路断开次数
# RcvErrors:接收错误
# XmtDiscards:发送丢弃
# 实时监控带宽
watch -n 1 'perfquery | grep -E "RcvData|XmtData"'
# 使用 ibmon 监控(如果安装)
ibmon -d mlx5_0 -p 1 -i 1
# Prometheus + IB Exporter 监控
# 安装 infiniband-exporter
# 配置 Prometheus 抓取 :9683/metrics