OpenMPI: MPI_Pack y MPI_Unpack

varuk

Buenas.

Sé que este tema es más rebuscado que las cuestiones normales que se hacen por aquí, pero si veo que no hay respuestas intentaré hacerlas por stackoverflow.

El caso es que tengo un código que quiero ejecutar lanzando dos procesos: proceso 0 y proceso 1. Lo que hace el código es mulplicar la matriz A por la B y dejar el resultado en la C. La peculiaridad es que si hay dos procesos, en este caso, la multiplicación se hace por partes. Es decir, en ese caso cada proceso, 0 y 1, cogería la mitad de la matriz A y multiplicaría por la correspondiente parte de B.

Para ello, el proceso 0 envía a los demás procesos, el 1, la mitad de la matriz A y la B (empaqueta ambas matrices en un MPI_Pack) y las envía con MPI_Send en el "bufferAB"(son matrices aunque están puestas como vectores). Digamos que el proceso

Luego, el proceso 1 recoge ese "pack" y lo almacena en el bufferAB con el MPI_Unpack:


double * bufferAB;
int  TAM_BUFFER = (n*n) + (n*n/np);
int posicion = 0;

if(nodo!=0)
{
    a=(double *) malloc(sizeof(double)*n*n/np);
    b=(double *) malloc(sizeof(double)*n*n);
    c=(double *) malloc(sizeof(double)*n*n/np);


}
if (nodo == 0) {
    
    for (i = 1; i < np; i++){
       
    posicion = 0;
    bufferAB = (double *) malloc(sizeof(double) * TAM_BUFFER);
        MPI_Pack(&a[i * lda * fa / np], fa / np * ca, MPI_DOUBLE, bufferAB, TAM_BUFFER*sizeof(double), &posicion, MPI_COMM_WORLD);
        MPI_Pack(b, fb * cb, MPI_DOUBLE, bufferAB, TAM_BUFFER*sizeof(double), &posicion, MPI_COMM_WORLD);
        MPI_Send(bufferAB, TAM_BUFFER, MPI_PACKED, i, 20, MPI_COMM_WORLD);
    free(bufferAB);
    }
  
} else {
   
bufferAB = (double *) malloc(sizeof(double) * TAM_BUFFER);
    MPI_Recv(bufferAB,TAM_BUFFER, MPI_PACKED,0,20,MPI_COMM_WORLD, MPI_STATUS_IGNORE);
posicion = 0;
    MPI_Unpack(bufferAB, TAM_BUFFER*sizeof(double), &posicion, a, fa / np * ca, MPI_DOUBLE, MPI_COMM_WORLD); 
    MPI_Unpack(bufferAB, TAM_BUFFER*sizeof(double), &posicion, b, fb*cb, MPI_DOUBLE, MPI_COMM_WORLD);
    
}

Cuando cada proceso termina, entonces manda su matriz resultante, C, al proceso 0, quien va almacenando en su matriz C el resto de partes para ser el resultado final.

mms(a, fa / np, ca, lda, b, fb, cb, ldb, c, fc / np, cc, ldc);
    
if (nodo == 0){ for (i = 1; i < np; i++) MPI_Recv(&c[i * ldc * fc / np],fc / np * cc, MPI_DOUBLE, i, 30, MPI_COMM_WORLD, MPI_STATUS_IGNORE); } else{ MPI_Send(c, fc / np * cc, MPI_DOUBLE, 0, 30, MPI_COMM_WORLD); } if(nodo!=0) { free(a); free(b); free(c); free(bufferAB); }

El tema es que algo estoy haciendo mal con el pack/unpack de MPI porque me sale mal y si, por ejemplo, le meto una matriz de 2x2 entonces me sale mal (sale siempre 0) la parte que calcula el proceso 1 y sale bien la parte que calcula el proceso 0...

No sé si alguien que haya manejado OpenMPI podría echarme un cable y decirme si, en lo que respecta al MPI_Pack y MPI_Unpack está bien o no.

Gracias : )

soulsville

llevo un par de años sin tocar MPI, pero le echo un ojo y a ver si te puedo ayudar.

¿qué tipo de matrices son? ¿simétricas?

1 respuesta
varuk

#2 Se generan solas... les pasas el número de filas y ya se generan tres matrices y ya está. Ese código es la función a la que se llama. Es lo único que toco yo, lo otro está bien. De hecho ese código cuando lo ejecutas con 1 proceso da bien, pero al entrar más procesos, 2 en este caso, ya pasa lo que digo.

1 respuesta
soulsville

#3 creo que el error viene de que no estás direccionando las matrices correctamente al realizar el unpack. Prueba y me dices.

MPI_Unpack(bufferAB, TAM_BUFFERsizeof(double), &posicion, &a, fa / np * ca, MPI_DOUBLE, MPI_COMM_WORLD);
MPI_Unpack(bufferAB, TAM_BUFFER
sizeof(double), &posicion, &b, fb*cb, MPI_DOUBLE, MPI_COMM_WORLD)

1 respuesta
varuk

#4 No eso no es. Lo que tu dices es pasarle la dirección de memoria pero hay que pasarle la primera posición de a y b. Bueno, o como "a" y "b" o si es como tu dices sería "&a[0]" y &b[0]"

Si lo pones como tú dices produce fallo de ejecución:

*** Process received signal ***
Signal: Segmentation fault (11)
Signal code: Address not mapped (1)

El caso es que le he puesto dos "FOR" al código. Uno junto antes de enviar el bufferAB , antes del send, y tiene sus 8 valores correctos, y otro después del MPI_recv... y ahí ya está vacio. Es como si no hiciera bien el SEND y el RECV...

Alguna tonteria se me escapa.

Usuarios habituales

  • varuk
  • soulsville