基础
- 多GPU两种连接方式:
1)多GPU通过单个节点连接到PCIe总线上
2)多GPU连接到集群中的网络交换机上 - 梁总常见的GPU通信模式
1)没必要进行数据交换,GPU间没有数据共享
2)有部分数据交换,GPU需要冗余数据存储
第2)中方式要避免通过主机内存中转数据(从GPU复制到Ram,再复制到另一个GPU上)
-
cudaError_t cudaGetDeviceCount(int* count);
获得的GPU数量 -
cudaError_t cudaSetDevice(int id);
指定使用哪个GPU.从0到n-1,默认设置为0.可以使用循环向多个GPU发送指令,异步不会阻塞 -
cudaError_t cudaGetDeviceProperties(struct cudaDeviceProp *prop,int device);
获得GPU属性
点对点通信
- 点对点访问:在CUDA内核和GPU间直接加载和存储地址
- 点对点传输:在GPU间直接复制数据
- 两个GPU连接到不同的PCIe根节点上,不允许直接进行点对点访问.
-
cudaError_t cudaDeviceCanAccessPeer(int* canAccessPeer, int device, int peerDevice);
支持P2P返回1,否则返回0 -
cudaError_t cudaDeviceEnablePeerAccess(int peerDevice,unsigned int flag);
显式启用点对点内存访问,一旦启用成功,立刻能访问对等设备,这个授权是单向的,不允许对方访问 -
cudaError_t cudaDeviceDisablePeerAccess(int peerDevice);
关闭P2P
点对点内存复制
-
cudaError_t cudaMemcpyPeerAsync(void* dst, int dstDev,void* src,int srcDev,size_t nBytes, cudaStream_t stream);
启动P2P后,异步复制设备上的数据,从srcDev传输到dstDev内存中.如果srcDev和dstDev共享相同的PCIe根节点,则数据通过PCIe最短路径传输
统一寻址的点对点访问
- UVA将CPU系统内存和设备的全局内存映射到单一的虚拟地址空间中.所有cudaHostAlloc分配的主机内存和cudaMalloc分配的设备内存主流在统一的地址空间内.
跨GPU集群拓展应用程序
- MPI(消息传递接口)标准化的数据通信API,通过分布式进程之间的消息进行数据通信
- GPU之间不同节点上移动数据的MPI有两种实现方式:
1)传统的MPI :GPU内存要先复制到主机内存,再传输
2)CUDA-aware MPI:吧GPU内存直接传输,对InfiniBand
集群,MVAPICH2
是被广泛使用的开源MPI库 - MPI程序包括4个步骤
1)初始化MPI环境
2)使用阻塞或非阻塞MPI函数在不同节点间的进程传递消息
3)跨节点同步
4)清理MPI环境
CPU连接CPU