Deadlock mit MPI
Ich experimentiere mit MPI und Frage mich, ob dieser code kann einen deadlock verursachen.
MPI_Comm_rank (comm, &my_rank);
if (my_rank == 0) {
MPI_Send (sendbuf, count, MPI_INT, 1, tag, comm);
MPI_Recv (recvbuf, count, MPI_INT, 1, tag, comm, &status);
} else if (my_rank == 1) {
MPI_Send (sendbuf, count, MPI_INT, 0, tag, comm);
MPI_Recv (recvbuf, count, MPI_INT, 0, tag, comm, &status);
}
Du musst angemeldet sein, um einen Kommentar abzugeben.
MPI_Send
kann oder nicht blockieren kann. Es wird blockiert, bis der sender wieder verwenden können, die Absender-Puffer. Einige Implementierungen wird an den Aufrufer zurückgeben, wenn der Puffer wurde an einer unteren Kommunikationsschicht. Einige andere werden an den Aufrufer zurückgeben, wenn es einen passendenMPI_Recv()
am anderen Ende. So ist es bis zu Ihrem MPI-Implementierung, ob es sich bei diesem Programm wird deadlock oder nicht.Weil dieses Programm verhält sich anders bei verschiedenen MPI-Implementierungen, können Sie erwägen, nach dem umschreiben des es so es wird nicht möglich sein deadlocks:
Immer bewusst sein, dass für jeden
MPI_Send()
es muss ein pairingMPI_Recv()
beide "parallel" in der Zeit. Dies kann zum Beispiel der Ende in der Sackgasse, weil die pairing-send/recv-Aufrufe werden nicht ausgerichtet in der Zeit. Sie kreuzen einander:Diese Prozesse, auf die andere Weise, nicht das Ende in der Sackgasse, vorausgesetzt natürlich, dass es in der Tat zwei Prozesse, die Reihen mit 0 und 1 in die gleiche communicator-Domäne.
Den oben genannten festen Programm kann fehlschlagen, wenn die Größe des communicator
com
nicht erlauben, Rang 1 (nur 0). So, dieif-else
nicht nehmen, dieelse
route und somit kein Prozess, hören für dieMPI_Send()
und Rang 0 wird deadlock.Wenn Sie müssen verwenden Sie Ihre aktuelle Kommunikation layout, dann können Sie es vorziehen, verwenden Sie
MPI_Isend()
oderMPI_Issend()
statt für nichtblockierende sends, also die Vermeidung von deadlock.Den post von @mcleod_ideafix ist sehr gut. Ich will hinzufügen, ein paar mehr Dinge über nicht-blockierende MPI-Aufrufe.
Den meisten MPI-Implementierungen ist, dass Sie kopieren Sie die Daten aus dem user-buffer in einen anderen Ort. Könnte es einen internen Puffer, um die Umsetzung, es könnte etwas besser auf die richtige Art von Netzwerken. Wenn die Daten kopiert aus der Benutzer-Puffer und der Puffer kann wiederverwendet werden, indem die Anwendung, die
MPI_SEND
Aufruf zurückgegeben. Dies kann sein, bevor die passendeMPI_RECV
aufgerufen wird, oder es kann nicht. Je größer die Daten, die Sie senden, desto mehr wahrscheinlich, dass Ihre Nachricht wird blockiert, bis derMPI_RECV
Anruf.Der beste Weg, um dies zu vermeiden, ist die Verwendung nicht-blockierende Aufrufe
MPI_IRECV
undMPI_ISEND
. Auf diese Weise können Sie nach IhremMPI_IRECV
ersten, dann machen Sie Ihren Anruf zuMPI_ISEND
. Dies vermeidet zusätzliche Kopien, wenn die Nachrichten ankommen (weil der Puffer zu halten, ist bereits über dieMPI_IRECV
), das macht es schneller, und es vermeidet die deadlock-situation. So, jetzt würde der code wie folgt Aussehen:Als mcleod_ideafix erklärte Ihr code kann in eine Sackgasse.
Hier gehen Sie: Erklärung und zwei mögliche Problem-Lösungen, die einen durch Neuanordnen der Reihenfolge der Ausführung, eines nach dem asynchronen send-recv Aufrufe
Hier ist die Lösung mit async Aufrufe: