【问题标题】:Need help understanding MPI_Comm_create需要帮助了解 MPI_Comm_create
【发布时间】:2016-08-08 20:33:42
【问题描述】:

关于 MPI_Comm_create,MPI 标准说

MPI_COMM_CREATE(comm, group, newcomm)

...该函数是集体的,必须由所有进程调用 通讯组。

我的意思是,例如,如果 comm 参数是 MPI_COMM_WORLD,那么 所有 进程必须调用 MPI_COMM_WORLD。

但是,我对 Internet 上可用的代码编写了一个变体,演示了 MPI_Comm_create 的使用。它在下面。您可以看到有两个地方调用了 MPI_Comm_create,而所有进程没有。然而代码运行良好。

我走运了吗?我是否偶然发现了一些依赖于实现的功能?我误解了 MPI 标准吗?这两个调用一起导致每个人都调用 MPI_Comm_create 的想法是否“最终”没关系?谢谢。代码如下:

#include <stdio.h>
#include <stdlib.h>
#include "mpi.h"


int main(int argc, char **argv) {

   MPI_Comm even_comm, odd_comm;
   MPI_Group even_group, odd_group, world_group;
   int id, even_id, odd_id;
   int *even_ranks, *odd_ranks;
   int num_ranks, num_even_ranks, num_odd_ranks;
   int err_mpi, i, j;
   int even_sum, odd_sum;


   err_mpi = MPI_Init(&argc, &argv);
   MPI_Comm_size(MPI_COMM_WORLD, &num_ranks);
   MPI_Comm_rank(MPI_COMM_WORLD, &id);

   MPI_Comm_group(MPI_COMM_WORLD, &world_group);

   num_even_ranks = (num_ranks+1)/2;
   even_ranks = (int *)malloc(num_even_ranks*sizeof(int));
   j=0;
   for (i=0; i<num_ranks; i++){
      if (i%2 == 0) {
         even_ranks[j] = i;
         j++;
      }
   } 

   num_odd_ranks = num_ranks/2;
   odd_ranks = (int *)malloc(num_odd_ranks*sizeof(int));
   j=0;
   for (i=0; i<num_ranks; i++){
      if (i%2 == 1) {
         odd_ranks[j] = i;
         j++;
      }
   } 

   if (id%2 == 0){
      MPI_Group_incl(world_group, num_even_ranks, even_ranks, &even_group);
      // RIGHT HERE, all procs are NOT calling!
      MPI_Comm_create(MPI_COMM_WORLD, even_group, &even_comm);
      MPI_Comm_rank(even_comm, &even_id);
      odd_id = -1;
   } else {
      MPI_Group_incl(world_group, num_odd_ranks, odd_ranks, &odd_group);
      // RIGHT HERE, all procs are NOT calling!
      MPI_Comm_create(MPI_COMM_WORLD, odd_group, &odd_comm);
      MPI_Comm_rank(odd_comm, &odd_id);
      even_id = -1;
   }

   // Just to have something to do, we'll some up the ranks of
   // the various procs in each communicator.       
   if (even_id != -1) MPI_Reduce(&id, &even_sum, 1, MPI_INT, MPI_SUM, 0, even_comm);
   if (odd_id != -1) MPI_Reduce(&id, &odd_sum, 1, MPI_INT, MPI_SUM, 0, odd_comm);

   if (odd_id == 0) printf("odd sum: %d\n", odd_sum);
   if (even_id == 0) printf("even sum: %d\n", even_sum);

   MPI_Finalize();

}

【问题讨论】:

    标签: mpi communicator


    【解决方案1】:

    虽然 comm_create 是从两行不同的代码调用的,但重要的是 COMM_WORLD 中的所有进程都在同时调用 comm_create。它们不是来自同一行代码的事实无关紧要 - 事实上,MPI 库甚至不知道从哪里调用 comm_create。

    一个更简单的例子是从两个分支调用 Barrier;无论执行哪一行,所有进程都在执行 same 屏障,因此代码将按预期工作。

    您可以轻松地重写要从同一行调用的代码:只需使用名为“num_ranks”、“mycomm”、“mygroup”和“myid”的变量以及名为“ranks”的数组并将它们设置为等于偶数或奇数变量取决于等级。然后所有进程都可以调用:

    MPI_Group_incl(world_group, num_ranks, ranks, &mygroup);
    MPI_Comm_create(MPI_COMM_WORLD, mygroup, &mycomm);
    MPI_Comm_rank(mycomm, &myid);
    

    如果你真的想要,你可以在之后重新分配这些,例如

    if (id%2 == 0) even_comm = mycomm;
    

    【讨论】:

      猜你喜欢
      • 2017-06-19
      • 2016-05-03
      • 1970-01-01
      • 2021-01-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-31
      相关资源
      最近更新 更多