MCCL 和 MPI
API
MCCL API 和 MPI 的使用方式相似,但存在许多细微差别。以下列表总结了这些差异:
每个进程使用多个设备
类似于 MPI 端点的概念,MCCL 不要求 rank 与进程一一对应。一个 MCCL 通信器可以与单个进程关联的多个 rank(多个设备)。因此,如果与 MPI 一起使用,单个 MPI rank(一个 MCCL 进程)可能与多个设备关联。
ReduceScatter 操作
mcclReduceScatter 操作类似于 MPI_Reduce_scatter_block 操作,而不是 MPI_Reduce_scatter 操作。MPI_Reduce_scatter 函数本质上是一个"向量"函数,而 MPI_Reduce_scatter_block(后来定义以填补缺失的语义)提供与镜像函数 MPI_Allgather 类似的常规计数。这是 MPI 的一个特殊设计,出于合理的向后兼容性原因,MCCL 不遵循这一点。
发送和接收计数
在许多集体操作中,MPI 允许不同的发送和接收计数和类型,只要 sendcount*sizeof(sendtype) == recvcount*sizeof(recvtype)。MCCL 不允许这样做,定义了一个单一的计数和一个单一的数据类型。
对于 AllGather 和 ReduceScatter 操作,计数等于每个 rank 的大小,这是最小的数量;另一个计数等于 nranks*count。函数原型清楚地显示了提供哪个计数。mcclAllGather 有一个 sendcount 作为参数,而 mcclReduceScatter 有一个 recvcount 作为参数。
注意:当执行或比较使用 ReduceScatter 和 AllGather 的组合进行 AllReduce 操作时,将 sendcount 和 recvcount 定义为总计数除以 rank 数,如果它不是 rank 数的整数倍,则向上取整。
其他集体操作和点对点操作
MCCL 没有为 sendrecv、gather、gatherv、scatter、scatterv、alltoall、alltoallv、alltoallw 或邻居集体定义特定的操作。所有这些操作都可以简单地使用 mcclSend、mcclRecv 和 mcclGroupStart 与 mcclGroupEnd 的组合来表示,类似于如何使用 MPI_Isend、MPI_Irecv 和 MPI_Waitall 来表示。
mcclRecv 不支持 MPI_ANY_SOURCE 的等效项;必须始终提供特定的源 rank。同样,提供的 接收计数必须与发送计数匹配。此外,没有消息标签的概念。
原地操作
有关更多信息,请参见 原地操作。
在 MPI 程序中使用 MCCL
MCCL 可以很容易地与 MPI 结合使用。MCCL 集体操作类似于 MPI 集体操作,因此,从 MPI 通信器创建 MCCL 通信器是直接的。因此,使用 MPI 进行 CPU 到 CPU 通信和 MCCL 进行 GPU 到 GPU 通信是容易的。
然而,MPI 中的一些实现细节可能导致在 MPI 程序中使用 MCCL 时出现问题。
MPI Progress
MPI 定义了一个 Progress 进度的概念,这意味着 MPI 操作需要程序调用 MPI 函数(可能多次)以取得进展并最终完成。
在一些实现中,一个 rank 上的进度可能需要在另一个 rank 上调用 MPI。虽然这通常对性能不利,但可以认为这是一个有效的 MPI 实现。
因此,阻塞在 MCCL 集体操作上,例如调用 musaStreamSynchronize,有时可能会造成死锁,因为不在某个 rank 上调用 MPI 可能会阻塞其他 rank,阻止它们到达会解锁第一个 rank 上的 MCCL 集体操作的 MCCL 调用。
在这种情况下,应该用以 下循环替换 musaStreamSynchronize 调用:
musaError_t err = musaErrorNotReady;
int flag;
while (err == musaErrorNotReady) {
err = musaStreamQuery(args->streams[i]);
MPI_Iprobe(MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &flag, MPI_STATUS_IGNORE);
}
与 MUSA 感知 MPI 的 GPU 间通信
使用 MCCL 与 MUSA 感知 MPI 同时执行 GPU 间通信可能会造成死锁。
MCCL 创建了设备间的依赖关系,这意味着在它启动后,MCCL 内核将等待(并可能阻塞 MUSA 设备),直到通信器中的所有 rank 启动它 们的 MCCL 内核。根据 MPI 实现的不同,MUSA 感知 MPI 也可能在设备之间创建这样的依赖关系。
因此,同时使用 MPI 和 MCCL 在同一组 MUSA 设备之间执行传输并不保证是安全的。

