Ich arbeite an einem Problem, das mithilfe einer einzelnen mpi_allgather-Operation oder einer mpi_scatter- und einer mpi_gather-Operation parallelisiert werden kann. Diese Operationen werden innerhalb einer while-Schleife aufgerufen, sodass sie häufig aufgerufen werden können.
In der Implementierung mit einem MPI_allgather-Schema sammle ich einen verteilten Vektor auf alle Prozesse zur Lösung doppelter Matrix. In der anderen Implementierung sammle ich den verteilten Vektor auf einem einzelnen Prozessor (dem Wurzelknoten), löse das lineare System auf diesem Prozessor und streue den Lösungsvektor zurück auf alle Prozesse.
Ich bin gespannt, ob die Kosten für eine Sammeloperation erheblich höher sind als die Kosten für Streu- und Sammeloperationen zusammen. Spielt die Länge der Nachricht eine wichtige Rolle für ihre Komplexität? Unterscheidet es sich zwischen den Implementierungen von mpi?
Bearbeiten:
quelle
MPI_Scatter
gefolgt vonMPI_Gather
liefert nicht die gleiche Kommunikationssemantik wieMPI_Allgather
. Möglicherweise liegt eine Redundanz vor, wenn Sie die Operation in irgendeiner Weise ausdrücken?MPI_Gather
gefolgt von einemMPI_Bcast
?Antworten:
Erstens hängt die genaue Antwort ab von: (1) Verwendung, dh Funktionseingabeargumenten, (2) Qualität und Details der MPI-Implementierung und (3) der von Ihnen verwendeten Hardware. Oft hängen (2) und (3) zusammen, z. B. wenn der Hardwareanbieter MPI für sein Netzwerk optimiert.
Im Allgemeinen ist das Zusammenführen von MPI-Kollektiven für kleinere Nachrichten besser, da die Startkosten nicht trivial sein können und die durch das Blockieren von Kollektiven verursachte Synchronisation minimiert werden sollte, wenn die Rechenzeit zwischen den Aufrufen variiert. Bei größeren Nachrichten sollte das Ziel darin bestehen, die Menge der gesendeten Daten zu minimieren.
Zum Beispiel sollte theoretisch
MPI_Reduce_scatter_block
besser sein alsMPI_Reduce
gefolgtMPI_Scatter
, obwohl das erstere oft in Bezug auf das letztere implementiert wird, so dass es keinen wirklichen Vorteil gibt. Bei den meisten MPI-Implementierungen besteht eine Korrelation zwischen Implementierungsqualität und Nutzungshäufigkeit, und Anbieter optimieren offensichtlich die Funktionen, für die dies im Maschinenvertrag erforderlich ist.Auf der anderen Seite, wenn man sich auf einem Blue Gene befindet, ist das
MPI_Reduce_scatter_block
VerwendenMPI_Allreduce
, das mehr Kommunikation alsMPI_Reduce
undMPI_Scatter
kombiniert macht, tatsächlich ziemlich viel schneller. Dies ist etwas, das ich kürzlich entdeckt habe und das einen interessanten Verstoß gegen das Prinzip der Leistungsselbstkonsistenz in MPI darstellt (dieses Prinzip wird ausführlicher in den "Selbstkonsistenten MPI-Leistungsrichtlinien" beschrieben ).Beachten Sie im speziellen Fall von Scatter + Gather versus Allgather, dass im ersten Fall alle Daten zu und von einem einzigen Prozess gehen müssen, was es zum Engpass macht, während im Allgather Daten sofort in alle Ränge hinein- und aus ihnen herausfließen können , weil alle Ränge einige Daten haben, die an alle anderen Ränge gesendet werden können. In einigen Netzwerken ist es jedoch nicht unbedingt eine gute Idee, Daten von allen Knoten gleichzeitig zu senden.
Der beste Weg, um diese Frage zu beantworten, besteht darin, die folgenden Schritte in Ihrem Code auszuführen und die Frage experimentell zu beantworten.
Eine noch bessere Option besteht darin, Ihren Code während der ersten beiden Iterationen experimentell messen zu lassen und dann für die verbleibenden Iterationen diejenige zu verwenden, die schneller ist:
quelle
Jeff hat absolut Recht, wenn es nur darum geht, zu messen - wir sind schließlich Wissenschaftler, und dies ist eine empirische Frage - und gibt ausgezeichnete Ratschläge zur Durchführung solcher Messungen. Lassen Sie mich jetzt eine gegenteilige (oder vielleicht ergänzende) Ansicht vertreten.
Es ist zu unterscheiden, ob ein weit verbreiteter Code geschrieben oder auf ein bestimmtes Ziel abgestimmt wird. Im Allgemeinen erstellen wir zuerst unseren Code, damit a) wir ihn auf einer Vielzahl von Plattformen verwenden können und b) der Code über Jahre hinweg wartbar und erweiterbar ist. Aber manchmal machen wir das andere - wir haben eine Zuweisung für ein Jahr auf einer großen Maschine, und wir rüsten auf einige erforderliche große Simulationen auf, und wir benötigen eine bestimmte Leistungsbasis, um das zu erreichen, was wir während dieser Zeit erledigen müssen der Zeitpunkt der gewährten Zuteilung.
Wenn wir Code schreiben, ist es viel wichtiger, ihn allgemein nutzbar und wartbar zu machen, als ein paar Prozent der Laufzeit auf einem bestimmten Computer zu sparen. In diesem Fall ist es fast immer richtig, die Routine zu verwenden, die am besten beschreibt, was Sie tun möchten - dies ist im Allgemeinen der spezifischste Anruf, den Sie tätigen können, um das zu tun, was Sie wollen. Wenn beispielsweise ein Straight Allgather oder Allgatherv das tut, was Sie wollen, sollten Sie dies verwenden, anstatt Ihre eigenen aus Scatter / Gatter-Operationen herauszurollen. Die Gründe sind:
Wenn Sie in diesem Fall feststellen, dass ein MPI-Kollektiv auf Ihrem Computer unangemessen langsam arbeitet, ist es am besten, einen Fehlerbericht beim MPI-Anbieter einzureichen. Sie möchten Ihre eigene Software nicht komplizieren, indem Sie versuchen, im Anwendungscode zu umgehen, was auf MPI-Bibliotheksebene ordnungsgemäß behoben werden sollte.
Allerdings . Wenn Sie sich im "Tuning" -Modus befinden - Sie haben einen funktionierenden Code, müssen Sie in kurzer Zeit (z. B. eine einjährige Zuweisung) auf sehr große Maßstäbe hochfahren und Ihren Code profilieren und herausgefunden haben, dass dieser bestimmte Teil Ihres Codes ein Engpass ist, dann ist es sinnvoll, mit der Durchführung dieser sehr spezifischen Einstellungen zu beginnen. Hoffentlich sind sie keine langfristigen Teile Ihres Codes - im Idealfall verbleiben diese Änderungen in einem projektspezifischen Zweig Ihres Repositorys - aber möglicherweise müssen Sie sie ausführen. In diesem Fall kann die Codierung von zwei verschiedenen Ansätzen, die durch Präprozessoranweisungen unterschieden werden, oder ein "Autotuning" -Ansatz für ein bestimmtes Kommunikationsmuster sehr sinnvoll sein.
Ich bin also nicht anderer Meinung als Jeff. Ich möchte nur einen Kontext hinzufügen, in dem es darum geht, wann Sie sich genug mit solchen relativen Leistungsfragen befassen sollten, um Ihren Code zu ändern, um damit umzugehen.
quelle