Nombre y Apellidos:................................................................................................................... Segundo Control de PAR- 1112 -Q1 21 de Diciembre de 2011 1. (4.0 puntos) MPI: Dado el siguiente código: /* Función que inicializa los N*N elementos de u */ void init_matrix(u); /* Función que procesa las N columnas (N elementos) de la fila que se le pasa, y * obtiene un resultado que devuelve con return */ double process(double *u); void main() { int i,j; double result; double *u; /* Malloc de los N*N elementos de la matriz u */ u = malloc(N*N*sizeof(double *)); init_matrix(u); for (i=0;i<N;i++) result+=process(&u[i*N]); printf("%f\n",result); } Realiza una implementación con MPI, Master/Worker, donde cada worker reciba cada vez una fila a procesar. El proceso master imprimirá el resultado por pantalla. Podéis suponer que tenéis estos tags: • docomp: para los mensajes enviados por el master conteniendo la fila a procesar por el worker. • compdone: para los mensajes enviados por los workers al master con el cálculo del resultado de procesar la fila con la función process. • shutdown: para los mensajes enviados por el master al los workers para indicarles que tienen que finalizar. En este caso, el mensaje es un puntero a NULL con 0 bytes de envío. Nota: La cabecera de la función MPI_Probe es int MPI_Probe(int source, int tag, MPI_Comm comm, MPI_Status *status). 2. (3 puntos) OMP: Dada las siguientes cabeceras de funciones y el código secuencial del quicksort: /* Ordena con quicksort el vector v de n elementos */ void quicksort_base(int * v, int n); /* Devuelve el índice del pivote en el vector */ int find_pivot(int *v, int n); void quicksort(int *v, int n) { int index; if (n<N_BASE) { quicksort_base(v,n); } else { index = find_pivot(v,n); quicksort(v,index); quicksort(&v[index], n-index); } return; } void main() { .... quicksort(v,N); ... } Implementa un quicksort paralelo para memoria compartida con OpenMP utilizando la estrategia Divide & Conquer. Esta implementación debería tener en consideración los overheads de creación de tareas. 3. (1.0 punto) Indica tres formas en las que cada procesador puede comunicar el boundary superior de un vecino, y que él tiene, y recibir su boundary superior, y que otro procesador tiene, con tal de que no se produzca un deadlock entre todos los procesadores. 4. (2.0 puntos) Dado el siguiente código: /* Función que inicializa los N*N elementos de u */ void init_matrix(u); /* Dado dos elementos de tipo double realiza un cálculo complejo y devuelve el resultado */ double compute(double u, double z); void main() { int i,j; double result=0.0; double *u, *z; /* Malloc de los N*N elementos de la matriz u y z*/ u = malloc(N*N*sizeof(double *)); z = malloc(N*N*sizeof(double *)); init_matrix(u); init_matrix(z); for (i=0;i<N;i++) for (j=i+1; j<N; i++) result+=compute(u[i*N+j],z[i*N+j]); printf("%f\n",result); } Y suponiendo que realizamos una paralelización con MPI del código usando Geometric Decomposition de tipo block, que el malloc y la inicialización de las matrices u y z se hace en paralelo en cada uno de los P procesadores, y que el resultado lo escribirá por pantalla el master, contesta a las siguientes preguntas: • (1.0 punto) Realiza el modelo de ejecución (cómputo y comunicación) de la estrategia de paralelización indicada, teniendo en cuenta que la inicialización de cada elemento de la matriz es ti , y que la función compute tiene un coste de tc . Suponed que la inicialización se hace sólo de los datos que son procesados y que estáis en una red de interconexión de tipo ring. • (0.5 puntos) Calcula el desbalanceo de trabajo entre el proceso 0 y el proceso P − 1. • (0.5 puntos) ¿Qué tipo de distribución de trabajo realizarías para reducir el desbalanceo? Razona tu respuesta