我在MPI中寻找类似于allgather的函数,除了它只收集来自所有处理器的某个子集的数据。
此外,我想按照不依赖于处理器等级的顺序组合数据。
有这样的功能吗?如果没有,怎么能有效地实现这个?
谢谢!
答案 0 :(得分:1)
我认为没有办法改变MPI调用本身的顺序(如果你愿意的话,你可以随后自己重新排序),但解决第一个问题相对容易。
在MPI中,并不要求所有集合调用都发生在MPI_COMM_WORLD(其中包含在执行开始时启动的所有进程)。您可以创建包含您喜欢的原始进程组的任何子集的新通信器。执行此操作的调用是MPI_COMM_CREATE。
要使用MPI_COMM_CREATE,您需要使用适当的函数(MPI_GROUP_EXCL,MPI_GROUP_INCL,MPI_GROUP_INTERSECTION等)操作要放入新通信器的进程的MPI_Group。网上通常有很多教程,如果不是很明显的话,你可以找到如何做这些事情。
答案 1 :(得分:1)
基本上,您的问题有两种解决方案。第一个解决方案是创建一个通信器,在那里放置必须发送数据的节点;但是,这不允许您对收集的数据进行随机播放。第二种解决方案是使用MPI_Gatherv而不是MPI_Gather。
MPI_Gatherv与MPI_Gather的作用相同,但您指定从每个处理器收集的元素数量以及放置它们的位置。考虑例如您可能希望收集流程0的2个值,流程1的3个值,流程2中的值和流程3中的1个值。
然后你必须用以下参数调用MPI_Gatherv(我把数组放在方括号中,所以这不是有效的代码; mycount是当前进程必须发送的元素数,因此对于进程0它将是2 ,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和displ仅与root相关;在其他节点上传递空指针是安全的。另一个注意事项是你必须在不发送数据的节点中调用MPI_Gatherv:在这些情况下,mycount必须设置为0;如果你想避免在没有值发送的节点上调用MPI_Gatherv,你必须设置一个不同的通信器,然后调用MPI_Gatherv。