Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <stdlib.h>
- #include <omp.h>
- #include <mpi.h>
- #include <time.h>
- #include <math.h>
- #define MIN(x, y) (((x) < (y)) ? (x) : (y))
- double sampleTime()
- {
- struct timespec tv;
- clock_gettime(CLOCK_MONOTONIC, &tv);
- return ((double)tv.tv_sec + ((double)tv.tv_nsec) / 1000000000.0);
- }
- int main(int argc, char *argv[])
- {
- float t = 0.0;
- FILE *fp;
- int x = 0, y = 0, i = 0, j = 0,
- cantProcesosAncho = 0, cantProcesosAlto = 0,
- posi = 0, posj = 0,
- alto = 0, ancho = 0,
- restoFilas = 0, restoColumnas = 0;
- int lado, repete, rank, size,
- rankVecinoSup = -1, rankVecinoInf = -1, rankVecinoIzq = -1, rankVecinoDer = -1;
- float **matrizLocal, **matrizCopia, **punteroAux;
- if (argc < 3)
- {
- printf("ingrese 2 argumentos - tamanio de la matriz y cantidad de pasos\n");
- exit(-1);
- }
- lado = atoi(argv[1]);
- repete = atoi(argv[2]);
- MPI_Init(&argc, &argv);
- MPI_Comm_rank(MPI_COMM_WORLD, &rank);
- MPI_Comm_size(MPI_COMM_WORLD, &size);
- MPI_Request requestVecinoSup;
- MPI_Request requestVecinoInf;
- MPI_Request requestVecinoDer;
- MPI_Request requestVecinoIzq;
- MPI_Request request;
- MPI_Status status;
- MPI_Status status1;
- MPI_Status status2;
- MPI_Status status3;
- // ------------------------------------------------------------------- CALCULO DE DISTRIBUCIÖN -------------------------------------------------------------------------------- //
- float raizSize = 0;
- raizSize = sqrt(size);
- for (i = 1; i <= raizSize; i++)
- {
- if (size % i == 0)
- {
- cantProcesosAncho = i;
- }
- }
- /* El resultado siguiente siempre es entero ya que cantProcesos ancho es un divisor de size */
- cantProcesosAlto = size / cantProcesosAncho;
- int nroProc = 0;
- int mapaProcesos[cantProcesosAlto][cantProcesosAncho];
- // si cantProcesosAncho == 1 , entonces la distribucion sera por filas, sino sera una cuadricula de n x m
- if (cantProcesosAncho > 1)
- { //defino mi mapa de procesos solo utilizado para distribucion matricial
- for (i = 0; i < cantProcesosAlto; i++)
- {
- for (j = 0; j < cantProcesosAncho; j++)
- {
- mapaProcesos[i][j] = nroProc;
- if (rank == nroProc)
- {
- posi = i;
- posj = j;
- }
- nroProc++;
- }
- }
- if (posi > 0)
- { //chequeo que el proceso no este en la 1er fila del mapaProcesos
- rankVecinoSup = rank - cantProcesosAncho;
- }
- if ((posi + 1) < cantProcesosAlto)
- { //chequeo que el proceso no este en la ultima fila del mapaProcesos
- rankVecinoInf = rank + cantProcesosAncho;
- }
- if (posj > 0)
- { //chequeo que el proceso no este en la 1er columna del mapaProcesos
- rankVecinoIzq = rank - 1;
- }
- if ((posj + 1) < cantProcesosAncho)
- { //chequeo que el proceso no este en la ultima columna del mapaProcesos
- rankVecinoDer = rank + 1;
- }
- }
- else
- { //Asigno los valores de los ranks vecinos para distribucion lista
- if (rank > 0) // chequeamos que no sea en el proceso rank = 0
- {
- rankVecinoSup = rank - 1;
- }
- if (rank < (size - 1)) // chequeamos que no sea el proceso rank = size -1
- {
- rankVecinoInf = rank + 1;
- }
- }
- // -------------------------------------------------------------- FIN CALCULO DE DISTRIBUCIÖN ------------------------------------------------------------------------------ //
- // ------------------------------------------------------------------- ASIGNACION DE MEMORIA ------------------------------------------------------------------------------- //
- alto = (lado / cantProcesosAlto);
- restoFilas = lado % cantProcesosAlto;
- if (cantProcesosAncho == 1)
- { //Defino variables para saber cuanta memoria reservar
- ancho = lado;
- if (rank < restoFilas)
- { //Estiro el alto en caso de que hayan sobrado filas, para abarcar esas filas sobrantes
- alto = alto + 1;
- }
- }
- else
- { // Reservo espacio en forma de submatrices
- ancho = lado / cantProcesosAncho;
- restoColumnas = lado % cantProcesosAncho;
- //estiro las filas o columnas que sean menores al numero de filas y columnas sobrantes.
- if (posj < restoColumnas)
- {
- ancho = ancho + 1;
- }
- if (posi < restoFilas)
- {
- alto = alto + 1;
- }
- }
- // reservo 2 arreglos para los datos de las columnas de los vecinos
- float columnaVecinoIzq[alto], columnaVecinoDer[alto],
- filaVecinoSup[ancho], filaVecinoInf[ancho];
- matrizLocal = malloc(alto * sizeof(float *));
- matrizCopia = malloc(alto * sizeof(float *));
- matrizLocal[0] = malloc(sizeof(float) * ancho * alto);
- matrizCopia[0] = malloc(sizeof(float) * ancho * alto);
- for (i = 1; i < alto; i++)
- {
- matrizLocal[i] = matrizLocal[0] + ancho * i;
- matrizCopia[i] = matrizCopia[0] + ancho * i;
- }
- // -------------------------------------------------------------- FIN ASIGNACION DE MEMORIA ------------------------------------------------------------------------------ //
- for (x = 0; x < alto; x++)
- {
- for (y = 0; y < ancho; y++)
- {
- matrizLocal[x][y] = 0.0;
- matrizCopia[x][y] = 0.0; //Inicializamos la matriz copia con ceros
- }
- }
- int columnaGlobal = 0, filaGlobal = 0;
- /*inicializo el fragmento de la matriz que le corresponda a cada proceso*/
- // Si la distribucion es por filas
- if (cantProcesosAncho == 1)
- {
- // printf("Filas\n");
- //Determinamos en que fila de la matriz global comienza nuestra porcion local de la matriz
- filaGlobal = (rank * alto) + MIN(restoFilas, rank);
- // printf("alto, %d, ancho, %d\n", alto, ancho);
- // printf("filaglobal %d \n", filaGlobal);
- for (x = 0; x < alto; x++)
- {
- for (y = 0; y < ancho; y++)
- {
- matrizLocal[x][y] = x * (x + filaGlobal) * (lado - (x + filaGlobal) - 1) * y * (lado - y - 1);
- }
- }
- }
- //Si la distribucion es por submatrices
- else
- {
- // printf("SubMatrices\n");
- filaGlobal = (posi * alto) + MIN(restoFilas, posi);
- columnaGlobal = (posj * ancho) + MIN(restoColumnas, posj);
- // printf("rank:%d filaGlobal:%d columnaGlobal:%d\n", rank, filaGlobal, columnaGlobal);
- // printf("rank:%d posi:%d posj:%d\n", rank, posi, posj);
- /* Verificado, Esta bien! Algunos valores de bordes tienen valores distintos de 0 xq lados
- piso durante la ejecucion de pasos al parecer.*/
- for (x = 0; x < alto; x++)
- {
- for (y = 0; y < ancho; y++)
- {
- matrizLocal[x][y] = (x + filaGlobal) * (lado - (x + filaGlobal) - 1) * (y + columnaGlobal) * (lado - (y + columnaGlobal) - 1);
- }
- }
- }
- // --------------------------------------------------------------------FIN INICIALIZACION ----------------------------------------------------------------------------------- //
- if (rank == 0)
- {
- t = sampleTime();
- }
- // -----------------------------------------------------------------------CALCULO -------------------------------------------------------------------------------------------- //
- //Si la distribución es matricial declaro el tipo de dato para los buffers
- MPI_Datatype buffer;
- MPI_Type_vector(alto, 1, ancho, MPI_FLOAT, &buffer);
- MPI_Type_commit(&buffer);
- /*MPI_Type_commit( ) separates the datatypes you really want to save and use from the
- intermediate ones that are scaffolded on the way to some very complex datatype.*/
- for (i = 0; i < repete; i++)
- {
- if (rankVecinoSup != -1)
- { // Enviamos la fila superior al vecino sup.
- MPI_Isend(&matrizLocal[0][0], ancho, MPI_FLOAT, rankVecinoSup, 0, MPI_COMM_WORLD, &request);
- MPI_Irecv(filaVecinoSup, ancho, MPI_FLOAT, rankVecinoSup, 1, MPI_COMM_WORLD, &requestVecinoInf);
- }
- if (rankVecinoInf != -1)
- { // Enviamos la fila superior al vecino sup.
- MPI_Isend(&matrizLocal[alto - 1][0], ancho, MPI_FLOAT, rankVecinoInf, 1, MPI_COMM_WORLD, &request);
- MPI_Irecv(filaVecinoInf, ancho, MPI_FLOAT, rankVecinoInf, 0, MPI_COMM_WORLD, &requestVecinoSup);
- }
- if (rankVecinoIzq != -1)
- { // Enviamos la columna izquierda al vecino izquierdo.
- MPI_Isend(&matrizLocal[0][0], 1, buffer, rankVecinoIzq, 2, MPI_COMM_WORLD, &request);
- MPI_Irecv(columnaVecinoIzq, alto, MPI_FLOAT, rankVecinoIzq, 3, MPI_COMM_WORLD, &requestVecinoDer);
- }
- if (rankVecinoDer != -1)
- {
- MPI_Isend(&matrizLocal[0][ancho - 1], 1, buffer, rankVecinoDer, 3, MPI_COMM_WORLD, &request);
- MPI_Irecv(columnaVecinoDer, alto, MPI_FLOAT, rankVecinoDer, 2, MPI_COMM_WORLD, &requestVecinoIzq);
- }
- //Calculo los elementos del centro, los que no tienen interacciones con los vecinos
- for (x = 1; x < (alto - 1); x++)
- {
- for (y = 1; y < (ancho - 1); y++)
- {
- matrizCopia[x][y] = (matrizLocal[x][y]) +
- (0.1 * (matrizLocal[x + 1][y] + matrizLocal[x - 1][y] - (2 * matrizLocal[x][y]))) +
- (0.1 * (matrizLocal[x][y + 1] + matrizLocal[x][y - 1] - (2 * matrizLocal[x][y])));
- }
- }
- // printf("rank:%d top:%d bot:%d izq:%d der:%d\n",rank, rankVecinoSup,rankVecinoInf,rankVecinoIzq,rankVecinoDer);
- //Con ese print me aseguré de que todos los procesos tienen correctamente asignados sus vecinos y -1 cuando no tienen
- //Por lo tanto el error esta al enviar mensajes. Xq algunos bordes no se computan.
- // printf("%d%d%d%d",sizeof(columnaVecinoIzq),sizeof(columnaVecinoDer),sizeof(filaVecinoSup),sizeof(filaVecinoInf));
- //--------------------------------------Bordes-------------------------------------
- if (rankVecinoSup != -1)
- {
- MPI_Wait(&requestVecinoInf, &status);
- for (y = 1; y < ancho - 1; y++)
- {
- matrizCopia[0][y] = (matrizLocal[0][y]) +
- (0.1 * (filaVecinoSup[y] + matrizLocal[1][y] - (2 * matrizLocal[0][y]))) +
- (0.1 * (matrizLocal[0][y + 1] + matrizLocal[0][y - 1] - (2 * matrizLocal[0][y])));
- }
- }
- if (rankVecinoInf != -1)
- {
- MPI_Wait(&requestVecinoSup, &status);
- for (y = 1; y < ancho - 1; y++)
- {
- matrizCopia[alto - 1][y] = (matrizLocal[alto - 1][y]) +
- (0.1 * (matrizLocal[alto - 2][y] + filaVecinoInf[y] - (2 * matrizLocal[alto - 1][y]))) +
- (0.1 * (matrizLocal[alto - 1][y + 1] + matrizLocal[alto - 1][y - 1] - (2 * matrizLocal[alto - 1][y])));
- }
- }
- if (rankVecinoIzq != -1)
- {
- MPI_Wait(&requestVecinoDer, &status);
- for (x = 1; x < alto - 1; x++)
- {
- matrizCopia[x][0] = (matrizLocal[x][0]) +
- (0.1 * (matrizLocal[x + 1][0] + matrizLocal[x - 1][0] - (2 * matrizLocal[x][0]))) +
- (0.1 * (matrizLocal[x][1] + columnaVecinoIzq[x] - (2 * matrizLocal[x][0])));
- }
- }
- if (rankVecinoDer != -1)
- {
- MPI_Wait(&requestVecinoIzq, &status);
- for (x = 1; x < alto - 1; x++)
- {
- matrizCopia[x][ancho - 1] = (matrizLocal[x][ancho - 1]) +
- (0.1 * (matrizLocal[x + 1][ancho - 1] + matrizLocal[x - 1][ancho - 1] - (2 * matrizLocal[x][ancho - 1]))) +
- (0.1 * (columnaVecinoDer[x] + matrizLocal[x][ancho - 2] - (2 * matrizLocal[x][ancho - 1])));
- }
- }
- //------------------------------Esquinas-------------------------------
- if (rankVecinoSup != -1)
- {
- // CALCULAMOS LA ESQUINA SUPERIOR IZQUIERDA DE LA SUBMATRIZ
- if (rankVecinoIzq != -1)
- {
- matrizCopia[0][0] = matrizLocal[0][0] +
- (0.1 * (matrizLocal[0][1] + columnaVecinoIzq[0] - (2 * matrizLocal[0][0]))) +
- (0.1 * (filaVecinoSup[0] + matrizLocal[1][0] - (2 * matrizLocal[0][0])));
- }
- // CALCULAMOS LA ESQUINA SUPERIOR DERECHA DE LA SUBMATRIZ
- if (rankVecinoDer != -1)
- {
- matrizCopia[0][ancho - 1] = matrizLocal[0][ancho - 1] +
- (0.1 * (columnaVecinoDer[0] + matrizLocal[0][ancho - 2] - (2 * matrizLocal[0][ancho - 1]))) +
- (0.1 * (filaVecinoSup[0] + matrizLocal[1][ancho - 1] - (2 * matrizLocal[0][ancho - 1])));
- }
- }
- if (rankVecinoInf != -1)
- {
- // CALCULAMOS LA ESQUINA INFERIOR IZQUIERDA DE LA SUBMATRIZ
- if (rankVecinoIzq != -1)
- {
- matrizCopia[alto - 1][0] = matrizLocal[alto - 1][0] +
- (0.1 * (matrizLocal[alto - 1][1] + columnaVecinoIzq[alto - 1] - (2 * matrizLocal[alto - 1][0]))) +
- (0.1 * (matrizLocal[alto - 2][0] + filaVecinoInf[0] - (2 * matrizLocal[alto - 1][0])));
- }
- // CALCULAMOS LA ESQUINA INFERIOR DERECHA DE LA SUBMATRIZ
- if (rankVecinoDer != -1)
- {
- matrizCopia[alto - 1][ancho - 1] = matrizLocal[alto - 1][ancho - 1] +
- (0.1 * (columnaVecinoDer[alto - 1] + matrizLocal[alto - 1][ancho - 2] - (2 * matrizLocal[alto - 1][ancho - 1]))) +
- (0.1 * (matrizLocal[alto - 2][ancho - 1] + filaVecinoInf[ancho - 1] - (2 * matrizLocal[alto - 1][ancho - 1])));
- }
- }
- MPI_Barrier(MPI_COMM_WORLD);
- //Intercambio de matrices
- punteroAux = matrizLocal;
- matrizLocal = matrizCopia;
- matrizCopia = punteroAux;
- }
- // -----------------------------------------------------------------------FIN______CALCULO ------------------------------------------------------------------------------------ //
- if (rank == 0)
- {
- float TiempoTotal = sampleTime() - t;
- printf("tiempo transcurrido: %f segundos\n", TiempoTotal);
- }
- // Imprimo en el archivo
- char nombre[30];
- sprintf(nombre, "subgrid_%d_%d.out", posi, posj);
- fp = fopen(nombre, "w+");
- for (x = 0; x < alto; x++)
- {
- for (y = 0; y < ancho; y++)
- {
- fprintf(fp, "%8.3f ", matrizLocal[x][y]);
- }
- fprintf(fp, "\n");
- }
- fprintf(fp, "\n");
- fclose(fp);
- MPI_Finalize();
- return 0;
- }
Add Comment
Please, Sign In to add comment