2016-10-17 5 views
0

MPI_ScatterMPI_Gatherを複数回使用してこれらの2つのMPI関数が完了するのを待って結果を出力する方法を学びたいと考えています。プログラムの最上位のプロセス0では、Scatter and Gatherを呼び出すwhileループを使いたいと思います。すべての計算が完了したら、この配列をこれらの関数に送り返して、より多くの計算を行いたいと思います。私は何をしようとしているのかをコードで説明しました。 /*.....*/のコメントは私が達成しようとしている課題です。
次のコードは4つのプロセッサを使用して実行されます。
:$ mpicc test.c -o test
:$ mpirun -np 4 testループ内のMPI_ScatterとMPI_Gatherを再利用する方法

#include <mpi.h> 
#include <stdio.h> 
#include <stdlib.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 globaldata[8]; 
    int localdata[2]; 
    int counter, i; 
    if (rank == 0) 
    { 
     for (i=0; i<size*2; i++)//initializing array to all zeros, one time 
      globaldata[i] = 0; 

     /*counter=0; 
     do 
     { 
      counter++; */ 
      printf("Sending at Processor %d has data: ", rank); 
      for (i=0; i<size*2; i++) 
       printf("%d ", globaldata[i]); 
      printf("\n"); 

      /*After MPI_Gather is done, I want to get the newly assined array here. 
      Now the globaldata array should hold values: 0 0 1 1 2 2 3 3 
      Therefore, in the next iteration of this while loop, these array values need 
      to be send for a new calculation with Scatter & Gather 
     }while(counter<2);*/ 

     //Following need to be executed after all the scatter and gather has completed 
     printf("Finally at Processor %d has data: ", rank); 
     for (i=0; i<size*2; i++)//Here the result should be: 0 0 2 2 3 3 4 4 
      printf("%d ", globaldata[i]); 
     printf("\n"); 
    } 


    MPI_Scatter(globaldata, 2, MPI_INT, &localdata, 2, MPI_INT, 0, MPI_COMM_WORLD); 

    localdata[0]= localdata[0]+rank; 
    localdata[1]= localdata[1]+rank; 

    MPI_Gather(&localdata, 2, MPI_INT, globaldata, 2, MPI_INT, 0, MPI_COMM_WORLD); 

    if (rank == 0) {//Currently I can only see the newly assinged array values if I print out the result at the bottom 
     printf("At the bottom, Processor %d has data: ", rank); 
     for (i=0; i<size*2; i++) 
      printf("%d ", globaldata[i]); 
     printf("\n"); 
    } 


    MPI_Finalize(); 
    return 0; 
} 

もっと私は上記のやろうとしています何の説明: 私はすべてのプロセッサに自分のglobaldata配列を送信したいのです。更新されたglobaldata配列を取得します。更新された配列を取得したら、この配列を他のすべてのプロセスに再送して、計算をやり直したいと思います。私はMPI_SendとMPI_Recvを使って同様の仕事をする次のコードを書いています。私はすべてのプロセッサに私の配列を送信するためにMPI_Sendを使用しています。次に、この配列はそれを変更し、ルート/プロセス0に戻します。変更された配列を取得すると、do whileループが再度実行され、より多くの計算が実行されます。私がしようとしているのは、MPI_ScatterとMPI_Gatherを同様の方法で使用することです。私はその配列を変更するために更新globaldata配列を取得し、MPI_ScatterとMPI_Gatherに戻ってそれを送信する場合は、再び

#include <mpi.h> 
#include <stdio.h> 
#include <stdlib.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 globaldata[8]; 
    int counter, i; 
    if (rank == 0) 
    { 
     for (i=0; i<size*2; i++) 
      globaldata[i] = 0; 

     counter=0; 
     do 
     { /*becase of this do while loop "globaldata" array will always be updated and resend for more caculations*/ 
      counter++; 
      printf("Sending at Processor %d has data: ", rank); 
      for (i=0; i<size*2; i++) 
       printf("%d ", globaldata[i]); 
      printf("\n"); 

      for(i = 0; i < 4; i++) 
      { 
       MPI_Send(&globaldata, 8, MPI_INT, i, 0, MPI_COMM_WORLD); 
      } 
      for(i = 1; i < 4; i++) 
      {   
       MPI_Recv(&globaldata, 8, MPI_INT, i, 99, MPI_COMM_WORLD, MPI_STATUS_IGNORE); 
      } 

     }while(counter<2); 

     /*Following executes after all the above calculations has completed*/ 
     printf("Finally at Processor %d has data: ", rank); 
     for (i=0; i<size*2; i++) 
      printf("%d ", globaldata[i]); 
     printf("\n"); 
    } 

    counter=0; 
    do 
    { 
     counter++; 
     MPI_Recv(&globaldata, 8, MPI_INT, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE); 
     globaldata[rank]=globaldata[rank]+rank; 
     globaldata[rank+1]=globaldata[rank+1]+rank; 
     MPI_Send(&globaldata, 8, MPI_INT, 0, 99, MPI_COMM_WORLD); 
    }while(counter<2); 

    MPI_Finalize(); 
    return 0; 
} 
+0

質問はしていません。 –

+0

私もあなたの質問を理解していません。あなたが理解していないより具体的なものがありますか?あなたは何か特別な問題がありますか?うまくいかないものを試しましたか?あなたは、質問をより明確にするために、その質問をよく編集するべきです。 :-) – MakisH

+0

コメントありがとうございました。私はここで何を達成しようとしているのか説明しようとしました。これが少なくとも少し助けてくれることを願っています。 – Newlearner

答えて

0

ただ散乱を入れて、ループ内でローカル処理と一緒に集まる:

if (rank == 0) 
{ 
    for (i = 0; i < size*2; i++) 
     globaldata[i] = 0; 
} 

for (counter = 0; counter < 2; counter++) 
{ 
    // if (rank == 0) 
    // { 
    // pre-process globaldata 
    // } 

    MPI_Scatter(globaldata, 2, MPI_INT, localdata, 2, MPI_INT, 0, MPI_COMM_WORLD); 

    localdata[0] += rank; 
    localdata[1] += rank; 

    MPI_Gather(localdata, 2, MPI_INT, globaldata, 2, MPI_INT, 0, MPI_COMM_WORLD); 

    // if (rank == 0) 
    // { 
    // post-process globaldata 
    // } 
} 

if (rank == 0) 
{ 
    printf("Finally at Processor %d has data: ", rank); 
     for (i=0; i<size*2; i++) 
     printf("%d ", globaldata[i]); 
    printf("\n"); 
} 

あなたは別の「マスター」プロセスのためのロジックを維持することを好む場合は、:

if (rank == 0) 
{ 
    for (i = 0; i < size*2; i++) 
     globaldata[i] = 0; 

    for (counter = 0; counter < 2; counter++) 
    { 
     // pre-process globaldata 

     MPI_Scatter(globaldata, 2, MPI_INT, localdata, 2, MPI_INT, 0, MPI_COMM_WORLD); 

     // Not really useful as rank == 0 and it changes nothing 
     localdata[0] += rank; 
     localdata[1] += rank; 

     MPI_Gather(localdata, 2, MPI_INT, globaldata, 2, MPI_INT, 0, MPI_COMM_WORLD); 

     // post-process globaldata 
    } 

    printf("Finally at Processor %d has data: ", rank); 
     for (i=0; i<size*2; i++) 
     printf("%d ", globaldata[i]); 
    printf("\n"); 
} 
else 
{ 
    for (counter = 0; counter < 2; counter++) 
    { 
     MPI_Scatter(globaldata /* or NULL */, 2, MPI_INT, localdata, 2, MPI_INT, 
        0, MPI_COMM_WORLD); 

     localdata[0] += rank; 
     localdata[1] += rank; 

     MPI_Gather(localdata, 2, MPI_INT, globaldata /* or NULL */, 2, MPI_INT, 
       0, MPI_COMM_WORLD); 
    } 
} 

は、コードの両方のセクションでループが同じNUを持っていることを確認してください繰り返しのmber。また、MPI_Scatterglobaldataのチャンクをルート・ランクにも送信し、MPI_Gatherはルートからチャンクを収集するため、マスター・プロセスも一部のデータ処理を実行することが予想されます。

+0

@Hristolliev例を示し、詳細を説明してくれてありがとう。とても役に立ちました。私は 'if(rank == 0){...} else {...}'を使わない限り、これを行う他の方法はないと思いますか? – Newlearner

+0

マスターランク用のソースファイルとワーカー用のソースファイルを1つ書くことができ、 'if(rank == 0){master(); } else {worker();ほとんどのMPI実装で、各ランクごとに異なる実行可能ファイルを持つ能力を利用しています。たとえば 'mpiexec -n 1 ./master:-n 15。/ worker' –

関連する問題