AI服务器GPUDirect配置:让GPU绕过CPU直接读网卡
GPUDirect RDMA 解决的问题很具体:训练时网卡收到数据后,默认要先拷贝到主机内存,再由 CPU 参与搬到 GPU 显存。
开启后,网卡可以直接读写 GPU 显存,减少一次拷贝和 CPU 占用。
但这套能力不是装完驱动就自动生效,需要驱动版本、内核模块和测试工具三方面对齐。
先确认硬件和软件是否具备条件
在动手改配置前,先检查三件事,任何一项不满足都可能导致后续步骤白做。
GPU 和网卡在同一个 PCIe 交换域内。 用 nvidia-smi topo -m 查看拓扑,如果 GPU 和网卡之间的连接显示为 SYS,说明跨了 NUMA 节点,GPUDirect 性能会受影响;
显示 PIX 或 PHB 才比较理想。
NVIDIA 驱动和 CUDA 已安装。 执行 nvidia-smi 应能看到 GPU 和驱动版本。
GPUDirect RDMA 对驱动版本有最低要求,较新的网卡和 GPU 组合建议使用近两年的驱动分支。
OFED/RDMA 驱动栈已安装。 执行 ibv_devinfo 能看到 RDMA 设备,且状态为 PORT_ACTIVE。
如果没有这个命令,说明缺少 rdma-core 或 MLNX_OFED。
安装和加载 nvidia-peermem 模块
GPUDirect RDMA 的核心是 nvidia-peermem 模块,它负责把 GPU 显存注册给 RDMA 子系统。
这个模块通常随 NVIDIA 驱动一起安装,但不会默认加载。
先确认模块文件是否存在:
modinfo nvidia-peermem
如果输出包含 filename 和 version,说明文件已就位。
然后加载模块:
sudo modprobe nvidia-peermem
lsmod | grep nvidia_peermem
lsmod 能看到 nvidia_peermem 说明加载成功。
为了让重启后自动生效,可以写入 /etc/modules-load.d/ 下的配置文件:
echo "nvidia-peermem" | sudo tee /etc/modules-load.d/nvidia-peermem.conf
如果 modprobe 报错 Module not found,先检查驱动安装是否完整,再确认内核版本与驱动编译时使用的内核头文件一致。
用带宽测试验证是否真正生效
模块加载成功不代表数据路径已经走 GPU 显存。
需要用支持 CUDA 的 RDMA 测试工具验证。
在服务端启动监听:
ib_write_bw -d mlx5_0 --use_cuda=0 -a
在客户端发起测试:
ib_write_bw -d mlx5_0 --use_cuda=0 -a <服务端IP>
关键参数是 --use_cuda=0,它指定测试数据放在 0 号 GPU 显存中。
如果测试能跑通且带宽接近网卡线速,说明 GPUDirect 路径已经工作。
如果报错 Couldn't allocate CUDA memory 或直接回退到主机内存,优先检查 nvidia_peermem 是否加载、GPU 是否被其他进程独占。
常见失败原因和规避方式
驱动版本不一致。 NVIDIA 驱动、CUDA Toolkit 和 OFED 驱动如果来自不同发行版或不同时间点,nvidia-peermem 可能编译失败或加载后不工作。
建议在同一个维护窗口内成套升级,不要单独升级其中一个。
Secure Boot 拦截模块加载。 开启 Secure Boot 的服务器会拒绝加载未签名的内核模块。
用 mokutil --sb-state 查看状态,如果为 enabled,需要为 NVIDIA 模块签名或暂时关闭 Secure Boot。
容器内测试失败。 在 Docker 或 Kubernetes 中运行测试时,需要把 /dev/infiniband 和 GPU 设备都挂载进容器,并确保容器内能加载 nvidia_peermem。
宿主机验证通过后再迁移到容器环境,可以少走弯路。
配置完成后的检查清单
nvidia-smi正常输出 GPU 信息,驱动版本与 OFED 兼容。lsmod | grep nvidia_peermem有输出,且重启后仍然存在。ibv_devinfo显示 RDMA 网卡端口为PORT_ACTIVE。ib_write_bw --use_cuda=0测试通过,带宽与网卡规格相符。nvidia-smi topo -m中 GPU 与网卡拓扑不是SYS。
如果测试带宽明显偏低,先看拓扑再查模块,不要急着调整网卡参数。
GPUDirect 配置本身不复杂,难的是驱动栈版本对齐和模块加载这两个前置条件。