5

プロセッサをグループに分割し、各グループの合計を個別に追加しようとしています...しかし、今まで結果を正しく見つけることができませんでした。簡単な例は次のとおりです。

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);
}

ここに何が欠けているのかわかりません...誰か助けてくれますか?

4

1 に答える 1

16

MPI_Reduce集合操作です。つまり、参加しているコミュニケーターのすべてのタスクがMPI_Reduce()呼び出しを行う必要があります。上記では、ランク 0 は呼び出しを行わないMPI_Reduce()ため、他のプロセッサの一部がランク 0 からの参加を待機しているため、このプログラムは停止します。

また、コミュニケータ全体での一括操作であるため、リダクションを分割するための作業が必要です。1 つの方法は、単に 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 
于 2013-02-11T15:12:11.980 に答える