我正在 MPI 中寻找一个类似于 allgather 的函数,除了它只从所有处理器的某个子集收集数据。
此外,我想按不依赖于处理器等级的顺序组合数据。
有这样的功能吗?如果没有,如何有效地实现这一点?
谢谢!
我正在 MPI 中寻找一个类似于 allgather 的函数,除了它只从所有处理器的某个子集收集数据。
此外,我想按不依赖于处理器等级的顺序组合数据。
有这样的功能吗?如果没有,如何有效地实现这一点?
谢谢!
基本上,您的问题有两种解决方案。第一个解决方案是创建一个通信器,将必须发送数据的节点放置在其中;但是,这不允许您打乱收集的数据。第二种解决方案是使用 MPI_Gatherv 而不是 MPI_Gather。
MPI_Gatherv 与 MPI_Gather 的作用相同,但您指定从每个处理器收集的元素数量以及放置它们的位置。考虑例如,您可能想要收集进程 0 的 2 个值、进程 1 的 3 个值、进程 2 的没有值和进程 3 的 1 个值。
然后您必须使用以下参数调用 MPI_Gatherv(我将数组放在方括号中,因此这不是有效代码;mycount 是当前进程必须发送的元素数,因此进程 0 为 2,进程 0 为 3过程1,...):
MPI_Gatherv(sendbuffer, mycount, type,
recvbuffer, [2, 3, 0, 1], [0, 2, 5, 5], type,
root, comm)
注意第二个数组,参数“displs”指定recvbuffer中的偏移量,从相应的进程接收到的元素将被保存在该位置:
ProcID Portion Size
0 [0, 2) 2
1 [2, 5) 3
2 [5, 5) 0
3 [5, 6) 1
例如,如果您更喜欢以流程反转的顺序存储值,即来自流程 3 的值位于开头,而来自流程 0 的值位于末尾,您应该改为:
MPI_Gatherv(sendbuffer, mycount, type,
recvbuffer, [2, 3, 0, 1], [4, 1, 1, 0], type,
root, comm)
这样,“职业计划”看起来像:
ProcID Portion Size
0 [4, 6) 2
1 [1, 4) 3
2 [1, 1) 0
3 [0, 1) 1
如果你想要一个随机分布,你将“只是”必须随机生成一个数组“displ”,并(大量)注意使其保持一致。
作为最后两点,请注意两个数组 recvcounts 和 displs 仅与 root 相关;在其他节点上,传递空指针是安全的。另一个注意事项是,您还必须在不发送数据的节点中调用 MPI_Gatherv:在这些情况下,必须将 mycount 设置为 0;如果你想避免在没有值发送的节点上调用 MPI_Gatherv,你必须设置一个差分通信器,然后调用 MPI_Gatherv。
我认为没有任何方法可以更改 MPI 调用本身内部的顺序(尽管如果您愿意,您可以在之后轻松地重新排序),但是解决第一个问题相对容易。
在 MPI 中,不需要所有的集体调用都发生在 MPI_COMM_WORLD(它包含在执行开始时启动的所有进程)。您可以创建新的通信器,其中包含您喜欢的原始进程组的任何子集。执行此操作的调用是 MPI_COMM_CREATE。
要使用 MPI_COMM_CREATE,您需要使用适当的函数(MPI_GROUP_EXCL、MPI_GROUP_INCL、MPI_GROUP_INTERSECTION 等)来操作要放入新通信器的 MPI_Group 进程。网络上通常有很多教程,如果不是很明显,您可以在其中找到如何做这些事情。