MPI ist entworfen, um mit Arrays von Strukturen eher als mit Strukturen von Arrays zu arbeiten.
Die MPI_Hindexed
die @suszterpatt vorgeschlagen ist ein schrecklicher Hack. Sie können nur ein Element des Strukturtyps und nur das Element senden, mit dem der Datentyp MPI definiert wurde. Bei anderen Variablen des gleichen Strukturtyps ist meistens sichergestellt, dass die berechneten Offsets falsch sind. Neben Hindexed Typen verwenden ein und denselben MPI-Datentyp für alle Elemente und damit können Sie nicht sowohl Eingänge und Doppel senden.
Die kluge Sache zu tun ist, Ihr Programm zu verwandeln Arrays von Strukturen zu verwenden:
typedef struct
{
int i;
double z;
} point;
typedef struct
{
point *A;
int nz;
} column;
Jetzt können Sie eine MPI-strukturierter Typ point_type
und verwenden Sie es schaffen nz
Elemente dieses Typs senden column.A
als die Angabe Pufferadresse:
int lens[3];
MPI_Aint base, disps[2];
MPI_Datatype oldtypes[2], point_struct, point_type;
MPI_Get_address(&point, disps);
MPI_Get_address(&point.z, disps+1);
base = disps[0];
lens[0] = 1; disps[0] = MPI_Aint_diff(disps[0], base); oldtypes[0] = MPI_INT;
lens[1] = 1; disps[1] = MPI_Aint_diff(disps[1], base); oldtypes[1] = MPI_DOUBLE;
MPI_Type_create_struct(2, lens, disps, oldtypes, &point_struct);
MPI_Type_create_resized(point_struct, 0, sizeof(point), &point_type);
MPI_Type_commit(&point_type);
MPI_Send(column.A, column.nz, point_type, ...);
Diese erste erstellt eine MPI-Datentyp point_struct
, die das Layout der Strukturelemente beschreibt, sondern für jede Polsterung nicht berücksichtigt bei der en d und kann daher nicht verwendet werden, um ein Array solcher Strukturen zuverlässig zu senden. Daher wird ein zweiter Datentyp point_type
mit dem richtigen Umfang erstellt, indem MPI_Type_create_resized
verwendet wird.
Auf der Empfängerseite die Nachricht mit MPI_Probe
, extrahiert die Anzahl der Elemente mit MPI_Get_count
mit einer Art von point_type
(das geht direkt zu dem nz
Feld), zuteilen das A
Feld und es verwendet, in MPI_Recv
peek würde die erhalten nz
Elemente:
MPI_Status status;
MPI_Probe(source, tag, comm, &status);
MPI_Get_count(&status, point_type, &column.nz);
if (nz == MPI_UNDEFINED)
... non-integral message was received, do something
column.A = (point *)malloc(column.nz*sizeof(point));
MPI_Recv(column.A, column.nz, point_type, source, tag, comm, MPI_STATUS_IGNORE);
Wenn das Codeänderung ist nicht möglich, Sie immer noch Ihre Struktur durch den Zwischenschritt der Transformation vor dem Senden gehen können, ein Prozess in der Regel (un-) Marshalling genannt. In Ihrem Fall etwas tun (ich nehme an, dass Sie die Anzahl der Array-Elemente in beiden Ai
speichern und Ax
im nz
Feld):
point *temp = (point *)malloc(nz*sizeof(point));
for (int i = 0; i < column.nz; i++)
{
temp[i].i = column.Ai[i];
temp[i].z = column.Az[i];
}
MPI_Send(temp, nz, point_type, ...);
free(temp);
Auf der Empfängerseite Sie das Gegenteil tun müssen: zuteilen eine ausreichend große Puffer, der die Struktur halten kann, die Nachricht darin empfangen und dann die umgekehrte Umwandlung durchführen.
Erneut müssen Sie den tatsächlichen Wert nz
nicht übertragen, da er einfach aus der Länge der Nachricht mit MPI_Get_count
extrahiert werden kann.
Warum möchten Sie jemals Zeiger zwischen MPI-Prozessen senden? Sie sind in verteilten Speichersystemen nicht tragbar. – talonmies