2012-12-13 18 views
25

これまでのところ、私のアプリケーションは整数のリストを持つtxtファイルを読み込んでいます。これらの整数は、マスタプロセス、つまりランク0のプロセッサによって配列に格納される必要があります。これは正常に動作しています。CからMPI_ScatterとMPI_Gatherはどのように使用されますか?

私はプログラムを実行するときに、それがマスタプロセスかどうかをチェックするif文を持っています。もしそうなら、私はMPI_Scatterコマンドを実行しています。

私が理解するところでは、これは配列を数値で細分し、それをスレーブプロセス、つまりrank> 0のすべてに渡します。しかし、私はどのようにMPI_Scatterを処理するか分からない。スレーブプロセスはどのようにサブアレイを取得するために「購読する」のですか?マスター以外のプロセスにサブアレイを使って何かをさせるにはどうすればいいですか?

マスタープロセスが配列から要素をどのように送信してから、スレーブに合計を加えてこれをマスターに返すかを示す簡単な例を提供できますか?すべての合計をまとめて出力しますか?これまで

マイコード:

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

//A pointer to the file to read in. 
FILE *fr; 

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

int rank,size,n,number_read; 
char line[80]; 
int numbers[30]; 
int buffer[30]; 

MPI_Init(&argc, &argv); 
MPI_Comm_rank(MPI_COMM_WORLD, &rank); 
MPI_Comm_size(MPI_COMM_WORLD, &size); 

fr = fopen ("int_data.txt","rt"); //We open the file to be read. 

if(rank ==0){ 
printf("my rank = %d\n",rank); 

//Reads in the flat file of integers and stores it in the array 'numbers' of type int. 
n=0; 
while(fgets(line,80,fr) != NULL) { 
    sscanf(line, "%d", &number_read); 
    numbers[n] = number_read; 
    printf("I am processor no. %d --> At element %d we have number: %d\n",rank,n,numbers[n]); 
    n++; 
} 

fclose(fr); 

MPI_Scatter(&numbers,2,MPI_INT,&buffer,2,MPI_INT,rank,MPI_COMM_WORLD); 

} 
else { 
MPI_Gather (&buffer, 2, MPI_INT, &numbers, 2, MPI_INT, 0, MPI_COMM_WORLD); 
printf("%d",buffer[0]); 
} 
MPI_Finalize(); 
return 0; 
} 

答えて

56

これは、操作はそれに新しい人とMPIにどのように動作するかの一般的な誤解です。とりわけ集団操作では、人々は呼び出しが何らかの理由で他のプロセッサにデータを「プッシュ」することを期待して、ランク0からのブロードキャスト(MPI_Bcast)の使用を開始しようとします。しかし、それは実際にMPIルーチンがどのように機能するかではありません。ほとんどのMPI通信では、送信者と受信者の両方がMPI呼び出しを行う必要があります。

特に

MPI_Scatter()及びMPI_Gather()(及びMPI_Bcast、および他の多く)は、集合操作です。コミュニケータのタスクのすべてによって呼び出されなければなりません。コミュニケータ内のすべてのプロセッサが同じ呼び出しを行い、操作が実行されます。 (そのため、分散と集約の両方が、すべてのデータの送受信元となる「ルート」プロセスのパラメータの1つとして必要です)。このようにすることで、MPIの実装では通信パターンを最適化するための範囲が広がります。

#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=NULL; 
    int localdata; 

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

     printf("Processor %d has data: ", rank); 
     for (int i=0; i<size; i++) 
      printf("%d ", globaldata[i]); 
     printf("\n"); 
    } 

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

    printf("Processor %d has data %d\n", rank, localdata); 
    localdata *= 2; 
    printf("Processor %d doubling the data, now has %d\n", rank, localdata); 

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

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

    if (rank == 0) 
     free(globaldata); 

    MPI_Finalize(); 
    return 0; 
} 

ことができます実行:

gpc-f103n084-$ mpicc -o scatter-gather scatter-gather.c -std=c99 
gpc-f103n084-$ mpirun -np 4 ./scatter-gather 
Processor 0 has data: 1 3 5 7 
Processor 0 has data 1 
Processor 0 doubling the data, now has 2 
Processor 3 has data 7 
Processor 3 doubling the data, now has 14 
Processor 2 has data 5 
Processor 2 doubling the data, now has 10 
Processor 1 has data 3 
Processor 1 doubling the data, now has 6 
Processor 0 has data: 2 6 10 14 
+2

何優れた答え

は、だからここに(集まる含めるを更新)簡単な例です。それは非常にまっすぐ進むようになり、私はそれが今どのように動作するかを見ます。私はそれを集合的な操作として考えていない間違いをしました。 ありがとう! – DSF

+2

うわー!あなたは私の日を救った、乾杯。ありがとうございました – irobo

+0

ほとんどのMPIイントロ – WakaChewbacca

関連する問題