MPI está diseñado para funcionar con matrices de estructuras en lugar de con estructuras de matrices.
El MPI_Hindexed
que @suszterpatt propuso es un truco terrible. Solo le permitirá enviar un elemento del tipo de estructura y solo el elemento que se utilizó para definir el tipo de datos MPI. Para otras variables del mismo tipo de estructura, se garantiza que las compensaciones calculadas serán incorrectas. Además de , los tipos Hindexed usan uno y el mismo tipo de datos MPI para todos los elementos y, por lo tanto, no le permiten enviar tanto ints como dobles.
La cosa sabia que hacer es transformar su programa para utilizar matrices de estructuras:
typedef struct
{
int i;
double z;
} point;
typedef struct
{
point *A;
int nz;
} column;
Ahora usted puede crear un MPI estructurado tipo point_type
y utilizarlo para enviar nz
elementos de ese tipo dando column.A
como el dirección del buffer:
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, ...);
Esta primera crea un tipo de datos MPI point_struct
que describe la disposición de los miembros de la estructura, pero no tiene en cuenta ningún relleno en la linea d y, por lo tanto, no se puede usar para enviar de manera confiable una matriz de tales estructuras. Por lo tanto, se crea un segundo tipo de datos point_type
con la extensión correcta usando MPI_Type_create_resized
.
En el lado receptor que le mirar el mensaje con MPI_Probe
, extraer el número de elementos con MPI_Get_count
con un tipo de point_type
(que va directamente al campo nz
), asignar el campo A
y utilizarlo en MPI_Recv
para recibir el nz
elementos:
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);
Si ese cambio de código es posible si todavía se puede pasar por la etapa intermedia de la transformación de su estructura antes de enviarlo, un proceso generalmente se llaman (des) cálculo de referencias. En su caso hacer algo como esto (supongo que almacene el número de elementos de la matriz, tanto en Ai
y Ax
en el campo nz
):
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);
En el lado receptor debe hacer lo contrario: asignar suficiente una gran búfer que puede contener la estructura, recibir el mensaje en ella y luego hacer la transformación opuesta.
Una vez más, no necesita transmitir el valor real de nz
ya que se puede extraer fácilmente de la longitud del mensaje usando MPI_Get_count
.
¿Por qué querrías enviar punteros entre los procesos de MPI? No son portátiles en sistemas de memoria distribuida. – talonmies