Wie werden MPI_Scatter und MPI_Gather von C verwendet?

Lesezeit: 4 Minuten

Benutzer-Avatar
Force444

Bisher liest meine Anwendung eine txt-Datei mit einer Liste von Ganzzahlen ein. Diese Ganzzahlen müssen vom Master-Prozess, dh dem Prozessor mit Rang 0, in einem Array gespeichert werden. Dies funktioniert einwandfrei.

Wenn ich jetzt das Programm ausführe, habe ich eine if-Anweisung, die überprüft, ob es sich um den Master-Prozess handelt, und wenn dies der Fall ist, führe ich den aus MPI_Scatter Befehl.

Soweit ich weiß, wird dies das Array mit den Zahlen unterteilen und an die Slave-Prozesse weitergeben, dh alle mit Rang > 0 . Allerdings bin ich mir nicht sicher, wie ich damit umgehen soll MPI_Scatter. Wie “abonniert” der Slave-Prozess das Sub-Array? Wie kann ich den Nicht-Master-Prozessen sagen, dass sie etwas mit dem Subarray machen sollen?

Kann mir bitte jemand ein einfaches Beispiel geben, um mir zu zeigen, wie der Master-Prozess Elemente aus dem Array sendet und dann die Slaves die Summe addieren und diese an den Master zurücksenden, der alle Summen addiert und ausdruckt?

Mein Code bisher:

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

Benutzer-Avatar
Jonathan Dursi

Dies ist ein häufiges Missverständnis darüber, wie der Betrieb bei MPI mit neuen Leuten funktioniert; insbesondere bei kollektiven Operationen, bei denen die Leute versuchen, mit der Nutzung von Rundfunk zu beginnen (MPI_Bcast) nur von Rang 0, in der Erwartung, dass der Aufruf die Daten irgendwie an die anderen Prozessoren “pusht”. Aber so funktionieren MPI-Routinen nicht wirklich; Die meiste MPI-Kommunikation erfordert, dass sowohl der Sender als auch der Empfänger MPI-Aufrufe tätigen.

Im Speziellen, MPI_Scatter() und MPI_Gather() (und MPI_Bcastund viele andere) sind Kollektiv Operationen; sie müssen angerufen werden alle der Aufgaben im Kommunikator. Alle Prozessoren im Kommunikator tätigen denselben Anruf, und die Operation wird ausgeführt. (Deshalb benötigen sowohl Scatter als auch Gather als einen der Parameter den “Root”-Prozess, wo alle Daten hingehen/herkommen). Auf diese Weise hat die MPI-Implementierung viel Spielraum, um die Kommunikationsmuster zu optimieren.

Also hier ist ein einfaches Beispiel (Aktualisiert zu sammeln):

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

Laufen gibt:

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

1369480cookie-checkWie werden MPI_Scatter und MPI_Gather von C verwendet?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy