Nombre y Apellidos:................................................................................................................... Examen Final PCA - 0910 -Q2 23 de Junio del 2010 Las notas del examen y de la práctica se publicarán antes del 2 de Julio a las 23:59. Para hacer la revisión tenéis que enviar un correo a [email protected] (examen) o a tu profesor de laboratorio para la práctica antes del 4 de Julio a las 23:49. Instrucciones: Suponed que estáis trabajando con el ordenador del laboratorio. 1. (1 punto) Indicad qué herramientas y detalla cuáles son los pasos que realizarías para saber en qué funciones se invierten o se producen o se ejecutan más: (1) Tiempo de CPU, (2) Fallos de cache (primer o segundo nivel), (3) Instrucciones de multiplicar/dividir y (4) elapsed time. 2. (1 punto) ¿En qué consiste la técnica de blocking y para qué sirve?. Pon un ejemplo en el que tenga sentido aplicar blocking. 3. (1.5 puntos) En el Core2 Duo que tenemos en los laboratorios, ¿qué tipo de ejecución de un programa podemos realizar: concurrente, en paralelo o ninguna de ellas? Razona tu respuesta. En caso de poderse ejecutar de forma concurrente y/o en paralelo, pon un ejemplo de código para cada tipo de ejecución (concurrente o en paralelo) que podamos aprovechar. 4. (0.75 puntos) Escribid un código en C para cada caso y utilizando bit hacks, que implemente: (1) el valor absoluto de una variable entera x de 32 bits , (2) el máximo de dos variables enteras x e y de 32 bits y (3) indique (resultado diferente de 0) si el valor, entre 1 y 32, de una variable entera x de 32 bits es primo. 5. (0.75 puntos) ¿Qué es más importante, la latencia de una instrucción o el "repetition rate"? Razona tu respuesta con ejemplos. 6. (5 puntos) Dado el siguiente código: #include <math.h> #include <stdio.h> #include <stdlib.h> typedef struct{ float f[16]; char un; char dos; float tres; } tipo_t; typedef struct { float f; char siuuuuuu; char boom[230610]; } tipo2_t ; void procesar (tipo_t *A, tipo2_t *B, char *already_done, int print_debug, int N_ATOMS) { int i,x; float tmp_calcul; for (i=0; i<N_ATOMS; i++) already_done[i]=0; for (i=5; i<N_ATOMS; i++) { x = rand()%N_ATOMS; tmp_calcul = 0.0; if (!already_done[x] && (x < N_ATOMS-3)) { already_done[x] = 1; tmp_calcul = (A[x].f[0] * A[x+1].f[1] * A[x+2].f[2] * A[x+3].f[3]); if (print_debug) printf("Value: %d tmp_calcul=%f\n", x, tmp_calcul); } B[i].f = B[i-4].f + tmp_calcul; B[i].f += B[i-5].f + sqrtf((float)tmp_calcul); } for (i=N_ATOMS-1; i>=3; i--) if (already_done[i]) B[i].f = B[i-1].f * B[i-3].f; } int main(int argc, char *argv[]) { int N_ATOMS; int print_debug; tipo_t * A; tipo2_t * B; char * already_done; N_ATOMS = atoi(argv[1]); print_debug = atoi(argv[2]); A = (tipo_t *) malloc(sizeof(tipo_t) * N_ATOMS); B = (tipo2_t *) malloc(sizeof(tipo2_t) * N_ATOMS); already_done = (char *) malloc(sizeof(char) * N_ATOMS); /* Inicializaciones de fichero y calculos ... */ procesar(A,B,already_done,print_debug,N_ATOMS); /* Mas procesos sobre A, B */ /* Imprime los resultados */ return 0; } (a) Optimizadlo (sin usar paralelización) escribiendo el código optimizado e indicando las técnicas de optimización usadas. Sabemos que el profiling nos da esta información: • La función procesar se lleva el 99% del tiempo de ejecución del programa. • Se invierten muchos ciclos en las operaciones de coma flotante, sobretodo en las de multiplicar y sqrtf. • No se está explotando suficientemente la localidad de datos. • La cantidad de saltos perjudica la localidad espacial de instrucciones del programa. En cambio, la tasa de fallos de predicción de saltos no es muy elevada.