关于MPI_Comm_create,MPI标准说
MPI_COMM_CREATE(comm,group,newcomm)
...该函数是集体的,必须由所有进程调用 通讯组。
我认为这意味着,例如,如果comm参数是MPI_COMM_WORLD,那么所有进程必须调用MPI_COMM_WORLD。
但是,我写了一个互联网上可用代码的变体,演示了MPI_Comm_create的使用。它在下面。您可以看到有两个位置调用MPI_Comm_create,并且所有进程都不。然而代码运行得很好。
我幸运了吗?我是否偶然发现了一些与实现相关的功能?我误解了MPI标准吗?是这两个呼叫一起导致每个人都调用MPI_Comm_create这样的想法"在一天结束时#34;好吗?谢谢。这是代码:
#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();
}
答案 0 :(得分:2)
虽然comm_create是从两行不同的代码调用的,但重要的是COMM_WORLD中的所有进程都在同时调用comm_create。它们不是来自同一行代码的事实是不相关的 - 事实上,MPI库甚至不知道调用comm_create的位置。
一个更简单的例子就是从两个分支中调用Barrier;无论执行哪一行,所有进程都在执行相同的障碍,因此代码将按预期工作。
您可以轻松地重写要从同一行调用的代码:只需要调用&#34; num_ranks&#34;,&#34; mycomm&#34;,&#34; mygroup&#34;和&#34; myid&#34;和一个名为&#34; rank&#34;并根据等级将它们设置为偶数或奇数变量。然后所有进程都可以调用:
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;