我正在尝试将处理器分成组,然后添加每个组的总和 独立......但直到现在我才能正确找到结果。 一个简单的例子如下:
int main(int argc, char** argv)
{
int size, rank,i=0,localsum1=0,globalsum1=0,localsum2=0,globalsum2=0;
MPI_Init(&argc,&argv);
MPI_Comm_size(MPI_COMM_WORLD,&size);
MPI_Comm_rank(MPI_COMM_WORLD,&rank);
if(rank==0)
{
}
else if(rank==1)
{
localsum1 += 5;
MPI_Reduce(&localsum1,&globalsum1,2,MPI_INT,MPI_SUM,0,MPI_COMM_WORLD);
}
else if(rank==2)
{
localsum2 += 10;
MPI_Reduce(&localsum2,&globalsum2,2,MPI_INT,MPI_SUM,0,MPI_COMM_WORLD);
}
if(rank==0)
{
printf("globalsum1 = %d \n",globalsum1);
printf("globalsum2 = %d \n",globalsum2);
}
MPI_Finalize();
return (EXIT_SUCCESS);
}
我无法弄清楚这里缺少什么......有人可以帮忙吗?
答案 0 :(得分:14)
MPI_Reduce是collective operation。这意味着参与的通信器中的所有任务必须进行MPI_Reduce()
呼叫。在上面,排名0从不调用MPI_Reduce()
所以这个程序会挂起,因为其他一些处理器等待0级的参与永远不会来。
另外,因为它是整个通信器的集体操作,所以你需要做一些工作来划分减少。一种方法是减少一个int数组,并让每个处理器只贡献给它在数组中的元素:
#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>
int main(int argc, char** argv)
{
int size, rank;
MPI_Init(&argc,&argv);
MPI_Comm_size(MPI_COMM_WORLD,&size);
MPI_Comm_rank(MPI_COMM_WORLD,&rank);
int localsum[2] = {0,0};
int globalsum[2] = {0,0};
if(rank % 2 == 1)
{
localsum[0] += 5;
}
else if( rank > 0 && (rank % 2 == 0))
{
localsum[1] += 10;
}
MPI_Reduce(localsum,globalsum,2,MPI_INT,MPI_SUM,0,MPI_COMM_WORLD);
if(rank==0)
{
printf("globalsum1 = %d \n",globalsum[0]);
printf("globalsum2 = %d \n",globalsum[1]);
}
MPI_Finalize();
return (EXIT_SUCCESS);
}
现在正在运行
$ mpicc -o reduce reduce.c
$ mpirun -np 3 ./reduce
globalsum1 = 5
globalsum2 = 10
否则,您可以创建仅连接您希望参与每个总和的处理器的通信器,并在每个通信器中进行减少。下面是一个不太漂亮的方法。这通常非常强大,但比第一个解决方案更复杂:
#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>
int main(int argc, char** argv)
{
int size, rank;
MPI_Init(&argc,&argv);
MPI_Comm_size(MPI_COMM_WORLD,&size);
MPI_Comm_rank(MPI_COMM_WORLD,&rank);
int localsum = 0;
int globalsum = 0;
MPI_Comm comm_evens_plus_root, comm_odds_plus_root;
MPI_Group grp_evens_plus_root, grp_odds_plus_root, grp_world;
MPI_Comm_group(MPI_COMM_WORLD, &grp_world);
int *ranks = malloc((size/2 + 1) * sizeof(rank));
int i,j;
for (i=1, j=0; i<size; i+=2, j+=1)
ranks[j] = i;
MPI_Group_excl(grp_world, j, ranks, &grp_evens_plus_root);
MPI_Comm_create(MPI_COMM_WORLD, grp_evens_plus_root, &comm_evens_plus_root);
for (i=2, j=0; i<size; i+=2, j+=1)
ranks[j] = i;
MPI_Group_excl(grp_world, j, ranks, &grp_odds_plus_root);
MPI_Comm_create(MPI_COMM_WORLD, grp_odds_plus_root, &comm_odds_plus_root);
free(ranks);
if(rank % 2 == 1)
{
localsum += 5;
MPI_Reduce(&localsum,&globalsum,1,MPI_INT,MPI_SUM,0,comm_odds_plus_root);
}
else if( rank > 0 && (rank % 2 == 0))
{
localsum += 10;
MPI_Reduce(&localsum,&globalsum,1,MPI_INT,MPI_SUM,0,comm_evens_plus_root);
}
if(rank==0)
{
MPI_Reduce(&localsum,&globalsum,1,MPI_INT,MPI_SUM,0,comm_odds_plus_root);
printf("globalsum1 = %d \n",globalsum);
MPI_Reduce(&localsum,&globalsum,1,MPI_INT,MPI_SUM,0,comm_evens_plus_root);
printf("globalsum2 = %d \n",globalsum);
}
MPI_Comm_free(&comm_odds_plus_root);
MPI_Comm_free(&comm_evens_plus_root);
MPI_Group_free(&grp_odds_plus_root);
MPI_Group_free(&grp_evens_plus_root);
MPI_Finalize();
return (EXIT_SUCCESS);
}
跑步给出
$ mpicc -o reduce2 reduce2.c
$ mpirun -np 3 ./reduce
globalsum1 = 5
globalsum2 = 10