#include "easypap.h" #include #include // Les données disponibles sont les suivantes // Attention lors du lancement à bien signaler la taille pour que l'image générée soit correcte // Par exemple pour la dalle grd il faudra ajouter -s 1025 à votre ligne de lancement // Il y a également une valeur cst qui permet de générer une image relative aux flots d'accumulation. //static char* filename = "data/mnt/petit.txt"; // ce fichier correspond à l'exemple de la fiche ipynb 6x6 //static int cst = 100; static char* filename = "data/mnt/jeu_essai.txt"; // ce fichier correspond à un extrait 32 x 32 de la dalle grd static int cst = 100; //static char* filename = "data/mnt/grd_618360_6754408.txt"; // ce fichier correspond à la dalle grd complète 1025x1025 //static int cst = 10000; //static char* filename = "data/mnt/alpes.txt"; // ce fichier correspond aux données sur les alpes 1024x1024 //static int cst = 10000; static float no_value; static int no_dir_value = -9; static int nb_lignes; static int nb_cols; // Les tableaux pour constuire le terrain à partir du mnt et calculer les directions. // Attention terrain est défini avec 2 lignes supplémentaires pour permettre des ghosts static float* terrain; static int* direction; static int* accumulation; // Cette fonction permet de lire le fichier, d'initialiser nb_lignes, nb_cols et de construire terrain. void lecture_mnt(char* nom); // La fonction pour calculer les directions est déjà implémentée // Elle prend en paramètre un terrain (paramètre data) et elle renvoie les directions dans le tableau dir. // Attention data est de taille (n_l+2) x n_c afin de prendre en compte les ghosts. // Ce n'est pas nécessaire en séquentiel mais cette fonction sera disponible également pour votre parallélisation. // dir est de taille n_l x n_c void calcul_direction(float *data, int *dir, int n_l, int n_c); int f_bord1(float ref, float* tab, float no_value); int f_bord2(float ref, float* tab, float no_value); int f(float ref, float* tab, float no_value); // la fonction conversion est une proposition pour convertir les directions // en une couleur pour visualiser les directions calculées int conversion(int val); // la fonction conversion_acc est une proposition pour convertir les flots d'accumulation // en une couleur int conversion_acc(int val); void echange_ghosts(float* data, int n_l, int n_c); void echange_ghosts_int(int* data, int n_l, int n_c); //////////////////////////////////// // Les trois fonctions EasyPAP pour la partie séquentielle void mnt_init (void) { PRINT_DEBUG ('u', "Image size is %dx%d\n", DIM, DIM); PRINT_DEBUG ('u', "Block size is %dx%d\n", TILE_W, TILE_H); PRINT_DEBUG ('u', "Press to pause/unpause, to quit.\n"); } int mnt_do_tile_default (int x, int y, int width, int height) { for (int i = y; i < y + height; i++) for (int j = x; j < x + width; j++) cur_img (i, j) = conversion(direction[(i+1)*DIM+j]); return 0; } int mnt_do_tile_accumulation (int x, int y, int width, int height) { for (int i = y; i < y + height; i++) for (int j = x; j < x + width; j++) cur_img (i, j) = conversion_acc(accumulation[(i+1)*DIM+j]); return 0; } // Attention afin de ne pas avoir trop de cas particulier // La version séquentielle utilise les fonctions proposées // pour la version paralléle et donc travaille sur des matrices // qui ont deux lignes supplémentaires (comme si on gérait déjà des // ghosts. unsigned mnt_compute_seq(unsigned nb_iter) { for (unsigned it = 1; it <= nb_iter; it++) { lecture_mnt(filename); calcul_direction(terrain, direction + nb_cols, nb_lignes, nb_cols); // Pour les images : // si on utilise la version par défaut on aura l'image relative aux directions // si on utilise la version mnt_do_tile_accumulation (option -wt accumulation dans le run) // on aura l'image relative aux accumulations. do_tile(0, 0, DIM, DIM, 0); } return 0; } //////////////////////////////////// // Les trois fonctions EasyPAP pour la partie parallèle en mpi // dont les deux versions pour do_tile static int mpi_rank = -1; static int mpi_size = -1; static float *terrain_local; static int *dir_local; static int *acc_local; static int nb_lignes_local = -1; // Les deux fonctions suivantes ne sont utiles que pour générer une image // pour les utiliser il faut penser à l'option -wt dans la ligne de commande // pour indiquer la version utilisée : mpi ou mpi_acc int mnt_do_tile_mpi(int x, int y, int width, int height) { for (int i = y; i < y + height; i++) for (int j = x; j < x + width; j++) { cur_img(i, j) = conversion(dir_local[(i - y + 1) * nb_cols + (j - x)]); } return 0; } int mnt_do_tile_mpi_acc(int x, int y, int width, int height) { for (int i = y; i < y + height; i++) for (int j = x; j < x + width; j++) { cur_img(i, j) = conversion_acc(acc_local[(i - y + 1) * nb_cols + (j - x)]); } return 0; } void mnt_init_mpi(void) { easypap_check_mpi(); MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank); MPI_Comm_size(MPI_COMM_WORLD, &mpi_size); } unsigned mnt_compute_mpi(unsigned nb_iter) { for (unsigned it = 1; it <= nb_iter; it++) { if (mpi_rank == 0) lecture_mnt(filename); MPI_Bcast(&nb_lignes, 1, MPI_INT, 0, MPI_COMM_WORLD); MPI_Bcast(&nb_cols, 1, MPI_INT, 0, MPI_COMM_WORLD); MPI_Bcast(&no_value, 1, MPI_FLOAT, 0, MPI_COMM_WORLD); nb_lignes_local = nb_lignes / mpi_size; terrain_local = (float *) malloc((nb_lignes_local + 2) * nb_cols * sizeof(float)); if (mpi_rank == 0) for (int i = 0; i < nb_cols; i++) terrain_local[i] = no_value; if (mpi_rank == mpi_size - 1) for (int i = 0; i < nb_cols; i++) terrain_local[(nb_lignes_local + 1) * nb_cols + i] = no_value; MPI_Scatter(terrain + nb_cols, nb_lignes_local * nb_cols, MPI_FLOAT, terrain_local + nb_cols, nb_lignes_local * nb_cols, MPI_FLOAT, 0, MPI_COMM_WORLD); printf("j'ai fini\n"); echange_ghosts(terrain_local, nb_lignes_local, nb_cols); dir_local = (int *) malloc((nb_lignes_local + 2) * nb_cols * sizeof(int)); acc_local = (int *) malloc((nb_lignes_local + 2) * nb_cols * sizeof(int)); calcul_direction(terrain_local, dir_local + nb_cols, nb_lignes_local, nb_cols); // Première version pour la génération de l'image // avec l'option -wt mpi ou -wt mpi_acc pour respectivement la direction et les flots d'accumulation do_tile(0, mpi_rank * nb_lignes_local, nb_cols, nb_lignes_local, mpi_rank); MPI_Gather(image + mpi_rank * nb_lignes_local * DIM, nb_lignes_local * DIM, MPI_INT, image, nb_lignes_local * DIM, MPI_INT, 0, MPI_COMM_WORLD); } return 0; } ///////////////////////////////////////////////////////////////// void lecture_mnt(char *nom) { FILE *f = fopen(nom, "r"); if (f != NULL) { int tmp; if (fscanf(f, "%d", &tmp) == 1); nb_lignes = tmp; if (fscanf(f, "%d", &tmp) == 1); nb_cols = tmp; if (fscanf(f, "%d", &tmp) == 1); if (fscanf(f, "%d", &tmp) == 1); if (fscanf(f, "%d", &tmp) == 1); if (fscanf(f, "%f", &no_value) == 1); terrain = (float *) calloc((2 + nb_lignes) * nb_cols, sizeof(float)); direction = (int *) malloc((2 + nb_lignes) * nb_cols * sizeof(float)); accumulation = (int *) malloc((2 + nb_lignes) * nb_cols * sizeof(float)); for (int j = 0; j < nb_cols; j++) { terrain[j] = no_value; terrain[(nb_lignes + 1) * nb_cols + j] = no_value; } for (int i = 0; i < nb_lignes; i++) for (int j = 0; j < nb_cols; j++) if (fscanf(f, "%f", &(terrain[(i + 1) * nb_cols + j])) == 1); } for (int j = 0; j < nb_cols; j++) { terrain[j] = no_value; terrain[(nb_lignes + 1) * nb_cols + j] = no_value; } } int f_bord1(float ref, float *tab, float no_value) { float min = ref; int code = 0; for (int i = 0; i < 5; i++) if (tab[i] != no_value) { if (tab[i] < min) { min = tab[i]; code = i + 1; } } return code; } int f_bord2(float ref, float *tab, float no_value) { float min = ref; int code = -1; for (int i = 0; i < 5; i++) if (tab[i] != no_value) { if (tab[i] < min) { min = tab[i]; code = i; } } if (code == -1) return 0; else if (code == 4) return 1; else return code + 5; } int f(float ref, float *tab, float no_value) { float min = ref; int code = 0; for (int i = 0; i < 8; i++) if (tab[i] != no_value) { if (tab[i] < min) { min = tab[i]; code = i + 1; } } return code; } void calcul_direction(float *data, int *dir, int n_l, int n_c) { int x, y; int x1, y1; int x2, y2; float tab[8]; float tab_bord[5]; for (int i = 0; i < n_l; i++) { x = i + 1; x1 = x - 1; x2 = x + 1; for (int j = 0; j < n_c; j++) { y = j; y1 = y - 1; y2 = y + 1; float val = data[x * n_c + y]; if (val != no_value) { if (j == 0) { tab_bord[0] = data[x1 * n_c + y]; tab_bord[1] = data[x1 * n_c + y2]; tab_bord[2] = data[x * n_c + y2]; tab_bord[3] = data[x2 * n_c + y2]; tab_bord[4] = data[x2 * n_c + y]; dir[i * n_c + j] = f_bord1(val, tab_bord, no_value); } else if (j == (n_c - 1)) { tab_bord[0] = data[x2 * n_c + y]; tab_bord[1] = data[x2 * n_c + y1]; tab_bord[2] = data[x * n_c + y1]; tab_bord[3] = data[x1 * n_c + y1]; tab_bord[4] = data[x1 * n_c + y]; dir[i * n_c + j] = f_bord2(val, tab_bord, no_value); } else { tab[0] = data[x1 * n_c + y]; tab[1] = data[x1 * n_c + y2]; tab[2] = data[x * n_c + y2]; tab[3] = data[x2 * n_c + y2]; tab[4] = data[x2 * n_c + y]; tab[5] = data[x2 * n_c + y1]; tab[6] = data[x * n_c + y1]; tab[7] = data[x1 * n_c + y1]; dir[i * n_c + j] = f(val, tab, no_value); } } else { dir[i * n_c + j] = no_dir_value; } } } } // La fonction pour les ghosts void echange_ghosts(float* data, int n_l, int n_c){ MPI_Request request_send; MPI_Request request_recv; if (mpi_rank!=mpi_size-1) MPI_Isend(data+n_c*n_l,n_c,MPI_FLOAT,mpi_rank+1,10,MPI_COMM_WORLD,&request_send); if (mpi_rank!=0) { MPI_Irecv(data, n_c, MPI_FLOAT, mpi_rank - 1, 10, MPI_COMM_WORLD, &request_recv); MPI_Wait(&request_recv,MPI_STATUS_IGNORE); } if (mpi_rank!=0) { MPI_Isend(data + n_c, n_c, MPI_FLOAT, mpi_rank - 1, 10, MPI_COMM_WORLD, &request_send); } if (mpi_rank!=mpi_size-1) { MPI_Irecv(data+n_c*(n_l+1), n_c, MPI_FLOAT, mpi_rank+1, 10, MPI_COMM_WORLD, &request_recv); MPI_Wait(&request_recv,MPI_STATUS_IGNORE); } } void echange_ghosts_int(int* data, int n_l, int n_c){ MPI_Request request_send; MPI_Request request_recv; if (mpi_rank!=mpi_size-1) MPI_Isend(data+n_c*n_l,n_c,MPI_INT,mpi_rank+1,10,MPI_COMM_WORLD,&request_send); if (mpi_rank!=0) { MPI_Irecv(data, n_c, MPI_INT, mpi_rank - 1, 10, MPI_COMM_WORLD, &request_recv); MPI_Wait(&request_recv,MPI_STATUS_IGNORE); } if (mpi_rank!=0) { MPI_Isend(data + n_c, n_c, MPI_INT, mpi_rank - 1, 10, MPI_COMM_WORLD, &request_send); } if (mpi_rank!=mpi_size-1) { MPI_Irecv(data+n_c*(n_l+1), n_c, MPI_INT, mpi_rank+1, 10, MPI_COMM_WORLD, &request_recv); MPI_Wait(&request_recv,MPI_STATUS_IGNORE); } } // Cette fonction permet juste de convertir le code des directions par des couleurs. int conversion(int val) { int color = rgba(255,255,255,255); switch (val) { case 0: color = rgba(255,255,255,255); break; case 1: color = rgba(255,0,0,255); break; case 2: color = rgba(255,127,0,255); break; case 3: color = rgba(255,255,0,255); break; case 4: color = rgba(127,255,0,255); break; case 5: color = rgba(0,127,0,255); break; case 6: color = rgba(0,0,255,255); break; case 7: color = rgba(0,255,255,255); break; case 8: color = rgba(0,0,0,255); break; default: color = rgba(255,255,255,255); } return color; } int conversion_acc(int val) { int color; if (val==-1) color = rgba(0,0,0,255); else { float test = ((float)val * 255.0) / (float)(nb_cols*nb_lignes); if ((int)(test)*cst >255) color = rgba(255,0,0,255); else color = rgba((int)(test*cst),0,0,255); } return color; }