void grafico2(int vector_temp[7]) { oled_clearScreen(OLED_COLOR_WHITE); oled_putString(6,2,"Temp Semanales", OLED_COLOR_BLACK,OLED_COLOR_WHITE); escala(); barra_uno(vector_temp[0]); barra_dos(vector_temp[1]); barra_tres(vector_temp[2]); barra_cuatro(vector_temp[3]); barra_cinco(vector_temp[4]); barra_seis(vector_temp[5]); barra_siete(vector_temp[6]); }
/* * (Resolución de un sistema de ecuaciones por un método iterativo) * Dadas una matriz de iteración M de nxn y dos vectores x,v de nx1, calcular: * Repetir num_iteraciones veces: * x <- M * x + v * Al final, se tendrá en x una aproximación a la solución del sistema. * Se desea visualizar su 1-norma. * (La 1-norma de un vector es la suma de los valores absolutos de sus elementos) */ int main(int argc, char *argv[]) { int num_iter = NITER, semilla = 0, n = N, n2, ncolus, ncoluscalculo, tama; char opcion; double t; int yo, num_procs, proc; double *M, *Mloc, *x, *xloc1, *xloc2, *v, norma, aux; int i, j, iter; MPI_Init(&argc, &argv); MPI_Comm_rank(MPI_COMM_WORLD, &yo); MPI_Comm_size(MPI_COMM_WORLD, &num_procs); while (argc > 1) { argc--; argv++; if (argv[0][0] != '-') { opcion = '?'; } else { opcion = *++argv[0]; if (opcion != '\0' && *++argv[0] == '\0' && argc > 1) { argc--; argv++; } } switch (opcion) { case 's': semilla = atoi(argv[0]); break; case 'n': n = atoi(argv[0]); if (n < 0) n = N; break; case 'i': num_iter = atoi(argv[0]); if (num_iter < 0) num_iter = NITER; break; default: fprintf(stderr, "Uso: mxv2 [-s semilla] [-n tamanyo] [-i iteraciones]\n"); return 1; } } /* Calculamos n2, un tamaño múltiplo de num_procs en el que quepa n */ ncolus = n / num_procs; if (num_procs * ncolus < n) ncolus++; n2 = num_procs * ncolus; /* Todos los procesos almacenarán unas columnas de M (Mloc), las mismas filas * de x de la iteración anterior (xloc1) y toda x recién calculada (xloc2) * (cada uno tiene una parte de la x, la global se obtiene sumando todas) */ if (yo == 0) /* El proceso 0 almacenará toda la M, toda la x y toda la v */ tama = n * n2 + n2 + n; else tama = 0; tama += n * ncolus + ncolus + n; /* Mloc, xloc1, xloc2 */ M = malloc(tama*sizeof(double)); if (M == NULL) { fprintf(stderr, "ERROR: Falta memoria\n"); return 1; } tama = n * ncolus; if (yo == 0) { x = M + n * n2; v = x + n2; Mloc = v + n; } else { Mloc = M; } xloc1 = Mloc + tama; xloc2 = xloc1 + ncolus; if (yo == 0) { srand(semilla); inventa(n, n, M); inventa(n, 1, v); inventa(n, 1, x); /* Ya que es inventado, hacer que el sistema sea convergente * (la norma de la matriz de iteración M debe ser menor que 1) */ escala(n, n, M, 0.9 / uno_norma(n, n, M)); } t = MPI_Wtime(); /* COMUNICACIONES */ /* Repartir la M por columnas y la x por filas (ncolus a cada proceso) */ if (yo == 0) { /* Para el 0, no enviamos sino que copiamos */ for (j = 0; j < ncolus; j++) { for (i = 0; i < n; i++) Mloc(i, j) = M(i, j); xloc1[j] = x[j]; } /* Para el resto, enviamos */ for (proc = 1; proc < num_procs; proc++) { MPI_Send(&M[proc*tama], tama, MPI_DOUBLE, proc, 13, MPI_COMM_WORLD); MPI_Send(&x[proc*ncolus], ncolus, MPI_DOUBLE, proc, 25, MPI_COMM_WORLD); } } else { MPI_Recv(Mloc, tama, MPI_DOUBLE, 0, 13, MPI_COMM_WORLD, MPI_STATUS_IGNORE); MPI_Recv(xloc1, ncolus, MPI_DOUBLE, 0, 25, MPI_COMM_WORLD, MPI_STATUS_IGNORE); } ncoluscalculo = n - yo * ncolus; if (ncoluscalculo > ncolus) ncoluscalculo = ncolus; for (iter = 1; iter <= num_iter; iter++) { /* Calcular Mloc*xloc1 en xloc2 */ for (i = 0; i < n; i++) { aux = 0; for (j = 0; j < ncoluscalculo; j++) aux += Mloc(i, j) * xloc1[j]; xloc2[i] = aux; } /* COMUNICACIONES */ /* Terminar el cálculo de la x: calcular la suma de todas las xloc2 * y añadirle la v, dejando el resultado en el procesador 0. * Y luego repartirlo entre los procesadores, para la siguiente iteración */ if (yo == 0) { /* La xloc2 que tiene el 0 no hay que recibirla sino operar con ella */ for (i = 0; i < n; i++) x[i] = xloc2[i] + v[i]; /* El resto de xloc2 hay que recibirla de los otros procesos * e ir añadiéndola a la x. Reusamos xloc2 como buffer de recepción */ for (proc = 1; proc < num_procs; proc++) { MPI_Recv(xloc2, n, MPI_DOUBLE, proc, 49, MPI_COMM_WORLD, MPI_STATUS_IGNORE); for (i = 0; i < n; i++) x[i] += xloc2[i]; } /* Para el 0, no enviamos sino que copiamos */ for (j = 0; j < ncolus; j++) xloc1[j] = x[j]; /* Para el resto, enviamos */ for (proc = 1; proc < num_procs; proc++) MPI_Send(&x[proc*ncolus], ncolus, MPI_DOUBLE, proc, 53, MPI_COMM_WORLD); } else { /* Enviar xloc2, recibir xloc1 */ MPI_Send(xloc2, n, MPI_DOUBLE, 0, 49, MPI_COMM_WORLD); MPI_Recv(xloc1, ncolus, MPI_DOUBLE, 0, 53, MPI_COMM_WORLD, MPI_STATUS_IGNORE); } } /* fin del bucle iter */ #define ABS(a) ((a) >= 0 ? (a) : -(a)) /* Calcular la 1-norma de la parte de x que tiene cada uno (xloc1) */ norma = 0; for (i = 0; i < ncoluscalculo; i++) norma += ABS(xloc1[i]); /* COMUNICACIONES */ /* Calcular la 1-norma de toda la x a partir de la 1-norma de cada fragmento. * Esto es calcular la suma de todas dejándola en el proceso 0. */ if (yo == 0) { for (proc = 1; proc < num_procs; proc++) { MPI_Recv(&aux, 1, MPI_DOUBLE, proc, 65, MPI_COMM_WORLD, MPI_STATUS_IGNORE); norma += aux; } } else { MPI_Send(&norma, 1, MPI_DOUBLE, 0, 65, MPI_COMM_WORLD); } t = MPI_Wtime() - t; if (yo == 0) { printf("1-norma (%d iteraciones): %.10g\n", num_iter, norma); printf("Tiempo con %d procesos: %.2f\n", num_procs, t); } free(M); MPI_Finalize(); return 0; }