GPUDirect P2P核心是显式调用cudaDeviceEnablePeerAccess启用直连,需先用nvidia-smi topo -p验证PCIe拓扑是否支持(如同一switch下),且受限于硬件约束(如不跨Root Complex);启用后cudaMemcpyPeer才走P2P路径,否则静默回退至主机内存中转。

GPUDirect P2P:多GPU间绕过主机内存的直连传输
要让两个GPU之间不经过CPU和主存直接交换数据,核心是启用并验证 cudaDeviceEnablePeerAccess,而不是靠 cudaMemcpy 或手动管理PCIe地址。它不是“自动生效”的功能,必须显式开启,且受硬件拓扑严格约束。
- 先用
nvidia-smi topo -p确认两卡是否在同一个PCIe switch下;如果显示PHB→PXB→DSB或中间有PIX,大概率支持;若出现NOPEER或跨NUMA节点,则基本不可用 - 调用前必须确保两卡已初始化(
cudaSetDevice各自执行一次),否则cudaDeviceEnablePeerAccess返回cudaErrorInvalidValue - 启用后,
cudaMemcpyPeer才能真正走P2P路径;若仍 fallback 到 host memory 中转,cudaGetLastError()通常不会报错,但nvidia-smi dmon -s u会显示rx/tx带宽远低于理论值 - 注意:P2P不等于零拷贝——它只是省掉一次host memory copy,GPU显存页仍需通过IOMMU映射,且不能跨PCIe root complex(即不能跨CPU socket)
GPUDirect RDMA:网卡直写GPU显存的关键配置
让NIC(如ConnectX-6/7)把网络数据直接DMA进GPU显存,不经过CPU内存,依赖三个硬性条件同时满足:驱动、注册内存方式、IB访问标志。漏掉任意一个,就会静默退化为传统路径。
- NIC驱动必须启用
ib_umad和rdma_cm,且内核中mlx5_core要加载时传入enable_ptys=1参数(否则ibv_reg_mr对设备内存失败) - GPU内存必须用
cudaMalloc分配,**不能**用malloc+cudaHostRegister;后者注册的是host memory,RDMA无法寻址到GPU物理页 -
ibv_reg_mr时必须设置IBV_ACCESS_ON_DEMAND标志(尤其在CUDA 11.8+和Linux 6.x之后),否则注册成功但后续ibv_post_send会触发IB_WC_RETRY_EXC_ERR - 验证是否生效:用
ibstat查端口状态,再运行ib_write_bw -d mlx5_0 -R --report_gbits并观察nvidia-smi dmon -s u中对应GPU的rx值是否跳变;若无变化,说明数据根本没进显存
GPUDirect over UB:UB总线不是可选插件,而是底层依赖
UB(UnifiedBus)不是用户态API或库,而是硬件级互联架构,类似NVLink但面向多节点扩展。你无法在代码里“调用UB”,只能确认系统是否搭载支持UB的芯片组(如NVIDIA Grace Hopper Superchip中的NVLink-C2C + UB fabric),然后通过配套固件和驱动暴露能力。
- UB本身不提供新API;它让原有的
cudaMalloc分配的显存对远端NIC或存储控制器可见,因此ibv_reg_mr才能成功注册设备内存 - 检查方法:运行
lspci | grep -i "unified\|grace",若输出含Grace CPU或UB Bridge,再查/sys/firmware/acpi/platform/rsdt是否存在UB相关表项 - UB启用后,
cudaMalloc分配的内存默认具备“device-local + fabric-visible”属性,无需额外cudaHostRegister或cudaMallocManaged;但若混用非UB平台代码(如老版本NCCL),可能因识别不到fabric而fallback - 目前UB仅在NVIDIA DGX GH200等特定服务器平台落地,x86+独立GPU组合不支持;别指望在普通PC上编译出UB功能
容易被忽略的调试盲区:不是代码写错,而是路径没通
GPUDirect类技术最常卡在“看起来跑通了,其实没走直达路径”。因为错误往往不抛异常,只默默降级——你看到 cudaMemcpyPeer 返回 success,ibv_post_send 没报错,但带宽和延迟完全不对。
- 不要只信返回值,务必用
nvidia-smi dmon -s u -d 1实时看GPU的rx/tx;若数据来自网卡却没看到rx上升,说明RDMA根本没写进显存 -
cuda-memcheck --tool memcheck对GPUDirect无效;真正有效的是nccl-tests中的all_reduce_perf,它强制走NCCL底层路径,能暴露P2P/RDMA是否被实际启用 - NCCL环境变量如
NCCL_P2P_DISABLE=1或NCCL_IB_DISABLE=1会全局禁用对应路径,即使你手写cudaMemcpyPeer也无济于事——它们控制的是底层通信原语的调度开关 - UB平台下,
cudaMalloc分配的地址空间可能被映射到fabric地址域,此时用cudaPointerGetAttributes查询type字段,应为cudaMemoryTypeDevice,但device字段可能指向一个逻辑fabric device ID,而非物理GPU ID
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











