收集MPI,但不收集MPI_Gather

时间:2016-06-21 21:07:24

标签: c mpi

我需要做类似MPI_Gather的事情,但我需要将收集的数据存储在依赖于与流程级别不同的顺序的顺序中。我以为我可以这样做:

int i;
int gathervals[10];
int my_val, my_place_in_storage;

/* init MPI etc ... then ... */

my_val = some_fcn_of_rank(my_rank, ...)
my_place_in_storage = some_other_fcn(my_val, my_rank, ...)

if (my_rank == 0){
/* my_val on proc 0 does go in gathervals[0], which simplifies
   things */
   gathervals[0] = my_val;
   for (i=1; i<num_procs; i++){
      MPI_Recv(&gathervals[i], 1, MPI_INT, MPI_ANY_SOURCE,
               i, MPI_COMM_WORLD, stat_mpi);
   }
}else{
   MPI_Send(&mv_val, 1, MPI_INT, 0, my_place_in_storage,
            MPI_COMM_WORLD);
}

我的想法是proc 0将启动循环并等待从my_place_in_storage为1的proc发送Send,然后proc 0将接收该消息并将值放入gathervals[1]。然后它将迭代并等待,直到它看到来自proc my_place_in_storage为2等的帖子

这应该有用吗?我在proc 0上遇到了一个段错误,我试图找出原因。我认为这段代码可能有点不正统,可以从这里开始。我已验证所有my_place_in_storage值的正确性。

2 个答案:

答案 0 :(得分:5)

另一种选择是使用MPI_Comm_split创建一个新的通信器,其中包含与MPI_COMM_WORLD相同的所有进程,但是根据&#34; my_place_in_storage&#34;置换为新的顺序。你可以这样做,如果每个人都提供了相同的&#34;颜色&#34;所以他们都属于同一个传播者,但使用了&#34; my_place_in_storage&#34;作为&#34;键&#34;。

Communicator创建有一些开销,但如果你使用相同的&#34; my_place_in_storage&#34;的值多次执行此操作,这可能比使用两个收集更有效。请注意,在新的通信器中,您还可以使用聚集,它也应该比gatherv更快。

答案 1 :(得分:3)

是的,这应该有效,但你有更好的选择。使用MPI_Gather收集my_place_in_storage并将其用作MPI_Gatherv的置换数组。一些事情:

 if (my_rank == 0) {
     int displacements[10];
     int recvcounts[10] = {1,1,1,1,1,1,1,1,1,1};
     MPI_Gather(&my_place_in_storage, 1, MPI_INT,
                displacements, 1, MPI_INT, 0, MPI_COMM_WORLD); 
     MPI_Gatherv(&my_val, 1, MPI_INT, gathervals, recvcounts,
                 displacements, MPI_INT, 0, MPI_COMM_WORLD);
 } else {
     MPI_Gather(&my_place_in_storage, 1, MPI_INT,
                NULL, 1, MPI_INT, 0, MPI_COMM_WORLD); 
     MPI_Gatherv(&my_val, 1, MPI_INT, NULL, 1, NULL,
                 MPI_INT, 0, MPI_COMM_WORLD);
 }

通常,最好使用集合而不是多个点对点消息。这更具可扩展性,允许通过MPI实现进行更多优化。