2

我正在 MPI 中寻找一个类似于 allgather 的函数,除了它只从所有处理器的某个子集收集数据。

此外,我想按不依赖于处理器等级的顺序组合数据。

有这样的功能吗?如果没有,如何有效地实现这一点?

谢谢!

4

2 回答 2

2

基本上,您的问题有两种解决方案。第一个解决方案是创建一个通信器,将必须发送数据的节点放置在其中;但是,这不允许您打乱收集的数据。第二种解决方案是使用 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。

于 2013-08-13T22:59:03.687 回答
1

我认为没有任何方法可以更改 MPI 调用本身内部的顺序(尽管如果您愿意,您可以在之后轻松地重新排序),但是解决第一个问题相对容易。

在 MPI 中,不需要所有的集体调用都发生在 MPI_COMM_WORLD(它包含在执行开始时启动的所有进程)。您可以创建新的通信器,其中包含您喜欢的原始进程组的任何子集。执行此操作的调用是 MPI_COMM_CREATE。

要使用 MPI_COMM_CREATE,您需要使用适当的函数(MPI_GROUP_EXCL、MPI_GROUP_INCL、MPI_GROUP_INTERSECTION 等)来操作要放入新通信器的 MPI_Group 进程。网络上通常有很多教程,如果不是很明显,您可以在其中找到如何做这些事情。

于 2013-08-08T04:23:39.650 回答