我的每个进程都有一个值v
数组和一个相同大小的进程ID pid
数组。 pid[i]
指定发送项目v[i]
的进程。
我需要实现一个分散操作(当然还有相应的聚集操作)
进程ID数组很可能仅包含(但不是唯一地)相邻进程(在笛卡尔拓扑的意义上),并且大多数时间仅包含其自己的进程ID。 (MPI_Comm_rank()
返回的那个)。此外,映射仅初始化一次并在整个计算期间保持不变,而散射/收集操作经常被调用。
我已经完成了自己的实现,从一些值开始,以便将相邻元素发送到同一个进程,然后发送大量的ISend和IRecv。现在我遇到了MPI_Alltoallv
函数,我想知道我自己的编码是否更好,或者我是否应该使用MPI内部函数。有任何人对此有经验吗?
答案 0 :(得分:1)
没有看到你的代码,人们无法确定,但通常使用MPI集合调用将比使用单独的ISend和IRecv调用组成部分产生更好的性能和更易读的代码。特别是,MPI_Alltoallv函数会将列出的每个等级的相邻值批处理为单个发送或接收,并且无需创建单个非阻塞发送/接收所需的所有单独结构的开销。
此规则的一个重要例外是将数据转换为集合所期望的形式是不切实际的。由于您的模式在应用程序中保持不变,因此此异常可能不适用于您。
答案 1 :(得分:1)
如果您知道您的进程将始终以某种拓扑进行通信,那么可以真正减少您需要发送的消息数量的事情之一就是邻居集体。我不会在这里完成整个教程,但基本的想法是您向MPI提供拓扑信息,然后使用特殊的集合函数进行通信。特殊功能是:
MPI_NEIGHBOR_ALLGATHER(sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, comm)
MPI_NEIGHBOR_ALLGATHERV(sendbuf, sendcount, sendtype, recvbuf, recvcounts, displs, recvtype, comm)
MPI_NEIGHBOR_ALLTOALL(sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, comm)
MPI_NEIGHBOR_ALLTOALLV(sendbuf, sendcounts, sdispls, sendtype, recvbuf, recvcounts, rdispls, recvtype, comm)
MPI_NEIGHBOR_ALLTOALLW(sendbuf, sendcounts, sdispls, sendtypes, recvbuf, recvcounts, rdispls, recvtypes, comm)
加上所有非阻塞变种。通过使用它们,您不必编写自己的集合函数。您可以使用MPI内置的内容,这些内容将更好地优化并且更易于阅读。