Verwenden von MPI_Bcast für die MPI-Kommunikation

73

Ich versuche, eine Nachricht vom Stammknoten mit MPI_Bcast an alle anderen Knoten zu senden. Wenn ich dieses Programm jedoch ausführe, hängt es immer am Anfang. Weiß jemand, was daran falsch ist?

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

int main(int argc, char** argv) {
        int rank;
        int buf;
        MPI_Status status;
        MPI_Init(&argc, &argv);
        MPI_Comm_rank(MPI_COMM_WORLD, &rank);

        if(rank == 0) {
                buf = 777;
                MPI_Bcast(&buf, 1, MPI_INT, 0, MPI_COMM_WORLD);
        }
        else {
                MPI_Recv(&buf, 1, MPI_INT, 0, 0, MPI_COMM_WORLD, &status);
                printf("rank %d receiving received %d\n", rank, buf);
        }

        MPI_Finalize();
        return 0;
}
David
quelle

Antworten:

137

Dies ist eine häufige Quelle der Verwirrung für MPI-Neulinge. Sie verwenden MPI_Recv()keine Daten, die von einer Sendung gesendet werden. Sie verwenden MPI_Bcast().

Was Sie beispielsweise wollen, ist Folgendes:

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

int main(int argc, char** argv) {
        int rank;
        int buf;
        const int root=0;

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

        if(rank == root) {
           buf = 777;
        }

        printf("[%d]: Before Bcast, buf is %d\n", rank, buf);

        /* everyone calls bcast, data is taken from root and ends up in everyone's buf */
        MPI_Bcast(&buf, 1, MPI_INT, root, MPI_COMM_WORLD);

        printf("[%d]: After Bcast, buf is %d\n", rank, buf);

        MPI_Finalize();
        return 0;
}

Für die kollektive MPI-Kommunikation muss sich jeder beteiligen . Jeder muss den Bcast oder den Allreduce anrufen oder was hast du? (Aus diesem Grund verfügt die Bcast-Routine über einen Parameter, der den "Stamm" angibt oder angibt, wer das Senden ausführt. Wenn nur der Absender bcast heißt, benötigen Sie diesen nicht.) Jeder ruft den Broadcast auf, einschließlich der Empfänger. Die Empfänger senden nicht nur einen Empfang.

Der Grund dafür ist, dass die kollektiven Operationen jeden in die Kommunikation einbeziehen können, sodass Sie angeben, was geschehen soll (jeder erhält die Daten eines Prozesses) und nicht, wie dies geschieht (z. B. Root-Prozessor-Schleifen über alle anderen Ränge und Aktionen) ein Senden), so dass Spielraum für die Optimierung der Kommunikationsmuster besteht (z. B. eine baumbasierte hierarchische Kommunikation, die log(P)Schritte anstelle von PSchritten für P-Prozesse ausführt).

Jonathan Dursi
quelle
Danke, dass du es so erklärt hast. Ich bin jedoch immer noch verwirrt darüber, wie jeder Knoten die Nachricht mit MPI_Recv empfangen soll. Ich habe versucht, einen MPI_Recv-Aufruf in einen if (rank! = 0) -Block und ohne einen zu packen, aber mein Programm druckt immer noch nichts. Wissen Sie, wie Sie die Nachricht auch auf jedem Knoten empfangen können?
David
2
Das tust du nicht. MPI_Bcast ist nicht wie ein Send; Es ist eine kollektive Operation, an der jeder teilnimmt, Absender und Empfänger, und am Ende des Anrufs hat der Empfänger den Wert, den der Absender hatte. Der gleiche Funktionsaufruf führt (so etwas wie) ein Senden aus, wenn der Rang == root (hier 0) ist, und (so etwas wie) einen anderen Empfang. Ich habe den obigen Code aktualisiert, damit Sie sehen können, dass alle das gleiche Ergebnis erzielen.
Jonathan Dursi
5
@ David: Wenn Sie denken, dass Sie an einem Sendeereignis MPI_Bcastteilnehmen, ist dies möglicherweise sinnvoller.
Hugh Perkins
2

MPI_Bcast ist eine kollektive Operation und muss von allen Prozessen aufgerufen werden, um sie abzuschließen.

MPI_RecvBei der Verwendung müssen Sie nicht anrufen MPI_Bcast. Es gibt einen Beitrag, der für Sie hilfreich sein kann. Klicken Sie hier

Ich gehe meinen Weg
quelle