Advertisement
Guest User

Untitled

a guest
Jan 18th, 2020
84
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 8.20 KB | None | 0 0
  1. /*
  2.    Línea de compilación: gcc main.c pgm.c -o main
  3.  
  4.    Ejemplo del uso de:
  5.  
  6.    pgmread
  7.    pgmwrite
  8.  
  9.    Las matrices que contienen a las imágenes son declaradas como uchar
  10.  
  11.    % % % % % % % %
  12.  
  13.    Ejemplo 1:
  14.  
  15.    unsigned char Original = (unsigned char )pgmread("entrada.pgm", &Largo, &Alto);
  16.    La imagen PGM se lee de la línea de comando (argv[1]). La función
  17.    pgmread regresa tres valores:
  18.  
  19.    1. la imagen leída       (Original)
  20.    2. el largo de la imagen (Largo)
  21.    3. el alto de la imagen  (Alto)
  22.  
  23.    % % % % % % % %
  24.  
  25.    Ejemplo 2:
  26.  
  27.    pgmwrite(Salida, "salida.pgm", Largo, Alto);
  28.    La imagen Salida es escrita al disco con el nombre de negativo.pgm, la
  29.    imagen resulta en formato PGM. La imagen se escribe desde el inicio (0,0)
  30.    hasta (Largo, Alto).
  31. */
  32.  
  33. #include <stdio.h>
  34. #include <stdlib.h>
  35. #include <string.h>
  36. #include "pgm.h"
  37. #include <mpi.h>
  38. #include <tgmath.h>
  39.  
  40. typedef struct
  41. {
  42.     int start;
  43.     int size;
  44. } asignacion;
  45.  
  46. // Asigna el trabajo que hará cada proceso
  47. //      Cada proceso tendra como MÍNIMO (tamaño del array / procesos) elementos de los que encargarse y además, puede tener 0 o 1 elemento más (nunca más de 1) del que encargarse.
  48. //      empieza en (tamaño / procesos) *procesoActual+min(tamaño%procesos, i)*** El mínimo lo usamos para saber el número de elementos adicionales que se han añadido a cada proceso antes del actual
  49. //      con un tamaño de: (tamaño / procesos) + 1 si (tamaño % procesos) es > procesoActual o +0 en caso contrario
  50. asignacion reparto(int size, int workers, int i)
  51. {
  52.     return (asignacion){
  53.         .start = (size / workers) * i + fmin(size % workers, i),
  54.         .size = (size / workers) + (size % workers > i ? 1 : 0)};
  55. }
  56.  
  57. void convolucion(unsigned char *Original, int *nucleo, unsigned char *Salida, int Columnas, int Filas, int nucleoFilas, int nucleoColumnas) {
  58.     int x, y;
  59.     int suma;
  60.     int k = 0; // Serán los pesos para calcular la media ponderada
  61.     int i, j;
  62.     int indiceX, indiceY;
  63.     int iniSalida, finSalida;
  64.  
  65.     for (int x = 0; x < Filas; x++) {
  66.         for (int y = 0; y < Columnas; y++) {
  67.             suma = 0;
  68.             k = 0;
  69.             for (int i0 = -nucleoFilas / 2; i0 < nucleoFilas / 2; i0++) {
  70.                 for (int j0 = -nucleoColumnas / 2; j0 < nucleoColumnas / 2; j0++) {
  71.                     int i = i0 + x;
  72.                     int j = j0 + y;
  73.                     if (i < 0)
  74.                         i = 0;
  75.                     else if (i > nucleoFilas / 2 - 1)
  76.                         i = nucleoFilas / 2 - 1;
  77.                     if (j < 0)
  78.                         j = 0;
  79.                     else if (j > nucleoColumnas / 2 - 1)
  80.                         j = nucleoColumnas / 2 - 1;
  81.                     suma += Original[i * Columnas + j] * nucleo[i * nucleoColumnas + j];
  82.                     k += nucleo[i * nucleoColumnas + j];
  83.                 }
  84.             }
  85.  
  86.             if (k == 0)
  87.                 Salida[x * Columnas + y] = suma;
  88.             else
  89.                 Salida[x * Columnas + y] = suma / k;
  90.         }
  91.     }
  92. }
  93.  
  94. /* * * * *          * * * * *          * * * * *          * * * * */
  95.  
  96. int main(int argc, char *argv[]) {
  97.     int Columnas, Filas;
  98.     int i, j;
  99.     int totalProc, proc;
  100.  
  101.     int desde, hasta;
  102.  
  103.     int nucleoFilas = 0;
  104.     int nucleoColumnas = 0; // Tamaño de la matriz de convolución
  105.  
  106.     MPI_Init(&argc, &argv);
  107.     MPI_Comm_size(MPI_COMM_WORLD, &totalProc);
  108.     MPI_Comm_rank(MPI_COMM_WORLD, &proc);
  109.  
  110.     unsigned char **Original;
  111.     unsigned char **Salida;
  112.     // Almacenará los resultados locales (tendrá un tamaño de filas/proceso*columnas)
  113.     unsigned char *OriginalAux;
  114.     unsigned char *SalidaAux;
  115.     unsigned char *Salida1d;
  116.     int *nucleo;
  117.     int indices[2];
  118.     int sizeElemen;
  119.  
  120.     if (proc == 0) {
  121.         if (argc != 3) {
  122.             printf("Introduzca las filas y columnas de la matriz de convolución\n");
  123.             fflush(stdout);
  124.         }
  125.  
  126.         //  Recogemos el tamaño de la matriz de convolución
  127.         nucleoFilas = atoi(argv[1]);
  128.         nucleoColumnas = atoi(argv[2]);
  129.  
  130.         //  Lectura de la imagen
  131.  
  132.         Original = pgmread("lena_original.pgm", &Columnas, &Filas);
  133.         Salida = (unsigned char **)GetMem2D(Filas, Columnas, sizeof(unsigned char));
  134.  
  135.         //  Creación de la matriz de convolución (Actualmente funciona para matrices impares)
  136.  
  137.         nucleo = malloc(sizeof(int) * nucleoFilas * nucleoColumnas);
  138.  
  139.         for (i = 0; i < nucleoFilas; i++)
  140.             for (j = 0; j < nucleoColumnas; j++)
  141.                 nucleo[i * nucleoColumnas + j] = -1;
  142.         nucleo[nucleoFilas / 2 * nucleoColumnas + nucleoColumnas / 2] = 1; // Colocamos el 1 en el centro
  143.  
  144.         // -----------------------------------------------------------------------------------------------
  145.     }
  146.  
  147.     //  Enviamos el nucleo a todos los procesos
  148.  
  149.     // Tamaño del nucleo
  150.     MPI_Bcast(&nucleoColumnas, 1, MPI_INT, 0, MPI_COMM_WORLD);
  151.     MPI_Bcast(&nucleoFilas, 1, MPI_INT, 0, MPI_COMM_WORLD);
  152.  
  153.     if (proc != 0)
  154.         nucleo = malloc(sizeof(int) * nucleoColumnas*nucleoFilas);
  155.  
  156.     // Recibimos el nucleo
  157.     MPI_Bcast(nucleo, nucleoColumnas*nucleoFilas, MPI_INT, 0, MPI_COMM_WORLD);
  158.  
  159.     //  Enviamos el numero de columnas que tiene la imagen a todos los procesos
  160.  
  161.     MPI_Bcast(&Columnas, 1, MPI_INT, 0, MPI_COMM_WORLD);
  162.     MPI_Bcast(&Filas, 1, MPI_INT, 0, MPI_COMM_WORLD);
  163.  
  164.     //  El resto de los procesos recive su parte de imagen
  165.  
  166.     if (proc == 0) {
  167.         //  Repartimos la imagen por filas
  168.  
  169.         asignacion a;
  170.         for (int i = totalProc - 1; i >= 0; i--)
  171.         {                                     // Repartimos para los procesos
  172.             a = reparto(Filas, totalProc, i); // Cogemos el reparto
  173.             desde = fmax(0, a.start - nucleoFilas / 2);
  174.             hasta = fmin(Filas, (a.start + a.size) + nucleoFilas / 2);
  175.             // printf("asignacion start=%d  fin=%d | size=%d | en rank=%d\n", a.start, a.start + a.size, a.size, i);
  176.             OriginalAux = malloc((hasta - desde) * Columnas * sizeof(unsigned char));
  177.  
  178.             // Recorremos las filas, cogiéndo un trozo más de imagen para que aplique la convolución correctamente.
  179.             for (int x = 0, fila = desde; fila < hasta; fila++, x++)
  180.             {
  181.                 for (int colum = 0; colum < Columnas; colum++)
  182.                 {                                                              // Recorremos todas las columnas
  183.                     OriginalAux[x * Columnas + colum] = Original[fila][colum]; // Pasamos el contenido de la matriz 2d a una matriz 1d
  184.                 }
  185.             }
  186.             // Asignamos los índices de lo que tiene que hacer cada proceso
  187.             indices[0] = a.start;          // Inicio
  188.             indices[1] = a.start + a.size; // Final
  189.             if (i != 0)
  190.             {
  191.                 // printf("rank[%d] --> desde %d | hasta %d\n",i, indices[0], indices[1]);
  192.                 MPI_Send(indices, 2, MPI_INT, i, 0, MPI_COMM_WORLD);                                        // Enviamos sus índices
  193.                 MPI_Send(OriginalAux, (hasta - desde) * Columnas, MPI_UNSIGNED_CHAR, i, 0, MPI_COMM_WORLD); // Enviamos la parte que tiene que hacer cada proceso
  194.             }
  195.         }
  196.     } else {
  197.  
  198.         //  Recivimos los indices de inicio y fin de los datos de cada proceso
  199.  
  200.         MPI_Recv(indices, 2, MPI_INT, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
  201.  
  202.         desde = fmax(0, indices[0] - nucleoFilas);
  203.         hasta = fmin(Filas, (indices[1]) + nucleoFilas);
  204.  
  205.         printf("proceso[%i] -> desde [%i] | hasta [%i]\n", proc, desde, hasta);
  206.  
  207.         OriginalAux = malloc((hasta - desde) * Columnas * sizeof(unsigned char));
  208.  
  209.         // Recivimos el vector con el trozo de imagen correspondiente
  210.         MPI_Recv(OriginalAux, (hasta - desde) * Columnas, MPI_UNSIGNED_CHAR, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
  211.         printf("Elemento aleatorio de OriginalAux[%i][%i]=%i\n", 2, 20, OriginalAux[2*(hasta-desde)+20]);
  212.     }
  213.     //printf("rank[%d] --> desde %d | hasta %d\n",proc, desde, hasta);
  214.  
  215.     // El número de elementos con los que debe trabajar cada proceso
  216.     sizeElemen = indices[1] - indices[0];
  217.     // Resultado de la convolución de cada proceso
  218.     SalidaAux = malloc(sizeElemen * Columnas * sizeof(unsigned char));
  219.  
  220.     convolucion(OriginalAux, nucleo, SalidaAux, Columnas, sizeElemen, nucleoFilas, nucleoColumnas);
  221.     printf("Valor obtenido con Gather: %i ", SalidaAux[1 * Columnas + 2]);
  222.  
  223.     Salida1d = malloc(Filas * Columnas * sizeof(unsigned char));
  224.  
  225.     MPI_Gather(SalidaAux, sizeElemen * Columnas, MPI_UNSIGNED_CHAR, Salida1d, sizeElemen * Columnas, MPI_UNSIGNED_CHAR, 0, MPI_COMM_WORLD);
  226.  
  227.     MPI_Barrier(MPI_COMM_WORLD);
  228.     if (proc == 0) {
  229.         printf("Valor obtenido con Gather: %i ", Salida1d[1 * Columnas + 2]);
  230.         for (int fila = 0; fila < Filas; fila++) {
  231.             for (int col = 0; col < Columnas; col++) {
  232.                 Salida[fila][col] = Salida1d[fila * Columnas + col];
  233.             }
  234.         }
  235.         pgmwrite(Salida, "lena_procesada.pgm", Filas, Columnas);
  236.     }
  237.  
  238.     MPI_Finalize();
  239.  
  240.     /*free(nucleo);
  241.   free(OriginalAux);
  242.   free(SalidaAux);
  243.   free(Salida1d);
  244.  
  245.   Free2D((void **)Original, Columnas);
  246.   Free2D((void **)Salida, Columnas);*/
  247. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement