Ein Bild sagt mehr als tausend Worte, so dass hier mehrere ASCII-Art-Bilder sind:
rank send buf recv buf
---- -------- --------
0 a,b,c MPI_Allgather a,b,c,A,B,C,#,@,%
1 A,B,C ----------------> a,b,c,A,B,C,#,@,%
2 #,@,% a,b,c,A,B,C,#,@,%
Dies ist nur der reguläre MPI_Gather
, nur in diesem Fall werden alle Prozesse der Datenabschnitte, dh die Operation erhalten ist wurzellos.
rank send buf recv buf
---- -------- --------
0 a,b,c MPI_Alltoall a,A,#
1 A,B,C ----------------> b,B,@
2 #,@,% c,C,%
(a more elaborate case with two elements per process)
rank send buf recv buf
---- -------- --------
0 a,b,c,d,e,f MPI_Alltoall a,b,A,B,#,@
1 A,B,C,D,E,F ----------------> c,d,C,D,%,$
2 #,@,%,$,&,* e,f,E,F,&,*
(sieht besser aus, wenn jedes Element durch den Rang gefärbt wird, die es aber ... sendet)
MPI_Alltoall
Werke als kombinierte MPI_Scatter
und MPI_Gather
- der Sendepuffer in jedem Prozess aufgeteilt wie in MPI_Scatter
und dann wird jede Spalte von Chunks durch den jeweiligen Prozess gesammelt, dessen Rang mit der Nummer der Chunk-Spalte übereinstimmt. MPI_Alltoall
kann auch als eine globale Transpositionsoperation betrachtet werden, die auf Datenbrocken wirkt.
Gibt es einen Fall, wenn die beiden Operationen austauschbar sind?Um richtig diese Frage zu beantworten, muss man einfach die Größe der Daten im Sendepuffer analysiert und die Daten im Empfangspuffer:
operation send buf size recv buf size
--------- ------------- -------------
MPI_Allgather sendcnt n_procs * sendcnt
MPI_Alltoall n_procs * sendcnt n_procs * sendcnt
Die Empfangspuffergröße tatsächlich n_procs * recvcnt
, aber MPI legt fest, dass die Zahl der gesendeten Basiselemente sollte gleich der Anzahl der empfangenen Basiselemente sein. Wenn also der gleiche MPI-Datentyp in Sende- und Empfangsteilen von MPI_All...
verwendet wird, muss recvcnt
gleich sendcnt
sein.
Es ist sofort offensichtlich, dass für die gleiche Größe der empfangenen Daten die Menge der von jedem Prozess gesendeten Daten unterschiedlich ist. Damit beide Operationen gleich sind, ist eine Bedingung, dass die Größe der gesendeten Puffer in beiden Fällen gleich ist, dh n_procs * sendcnt == sendcnt
, was nur möglich ist, wenn n_procs == 1
, dh wenn es nur einen Prozess gibt, oder sendcnt == 0
, dh keine Daten wird überhaupt gesendet. Daher gibt es keinen praktisch durchführbaren Fall, in dem beide Vorgänge wirklich austauschbar sind. Aber man kann MPI_Allgather
mit MPI_Alltoall
simulieren, indem man n_procs
mal die gleichen Daten im Sendepuffer wiederholt (wie bereits von Tyler Gill notiert). Hier ist die Wirkung von MPI_Allgather
mit einem Element senden Puffer:
rank send buf recv buf
---- -------- --------
0 a MPI_Allgather a,A,#
1 A ----------------> a,A,#
2 # a,A,#
Und hier das gleiche umgesetzt mit MPI_Alltoall
:
rank send buf recv buf
---- -------- --------
0 a,a,a MPI_Alltoall a,A,#
1 A,A,A ----------------> a,A,#
2 #,#,# a,A,#
Die Rückseite ist nicht möglich - man nicht die Wirkung von MPI_Alltoall
mit MPI_Allgather
simulieren im allgemeinen Fall.
Haben Sie den MPI-Standard gelesen, bevor Sie diese Frage gestellt haben? Es gibt sehr klare Erklärungen und sogar grafische Darstellungen vieler Kollektive. – Jeff