#include #include #include #include #include "distribution_methods/block_distribution.h" #include "CommDist.h" void prepare_redistribution(int qty, int myId, int numP, int numO, int is_children_group, int is_intercomm, char **recv, struct Counts *s_counts, struct Counts *r_counts); void sync_rma(char *send, char *recv, struct Counts r_counts, int tamBl, MPI_Comm comm, int red_method); void sync_rma_lock(char *recv, struct Counts r_counts, MPI_Win win); void sync_rma_lockall(char *recv, struct Counts r_counts, MPI_Win win); ////////////////////////// void send_async_arrays(struct Dist_data dist_data, char *array, int numP_child, struct Counts *counts, MPI_Request *comm_req); void recv_async_arrays(struct Dist_data dist_data, char *array, int numP_parents, struct Counts *counts, MPI_Request *comm_req); void send_async_point_arrays(struct Dist_data dist_data, char *array, int numP_child, struct Counts *counts, MPI_Request *comm_req); void recv_async_point_arrays(struct Dist_data dist_data, char *array, int numP_parents, struct Counts *counts, MPI_Request *comm_req); /* * Reserva memoria para un vector de hasta "qty" elementos. * Los "qty" elementos se disitribuyen entre los "numP" procesos * que llaman a esta funcion. */ void malloc_comm_array(char **array, int qty, int myId, int numP) { struct Dist_data dist_data; get_block_dist(qty, myId, numP, &dist_data); if( (*array = calloc(dist_data.tamBl, sizeof(char))) == NULL) { printf("Memory Error (Malloc Arrays(%d))\n", dist_data.tamBl); exit(1); } /* int i; for(i=0; icounts, counts->displs, MPI_CHAR, NULL, counts->zero_arr, counts->zero_arr, MPI_CHAR, dist_data.intercomm, comm_req); } /* * Envia a los hijos un vector que es redistribuido a los procesos * hijos. Antes de realizar la comunicacion, cada proceso padre calcula sobre que procesos * del otro grupo se transmiten elementos. * * El envio se realiza a partir de varias comunicaciones punto a punto. */ void send_async_point_arrays(struct Dist_data dist_data, char *array, int numP_child, struct Counts *counts, MPI_Request *comm_req) { int i; // PREPARAR ENVIO DEL VECTOR prepare_comm_alltoall(dist_data.myId, dist_data.numP, numP_child, dist_data.qty, counts); for(i=0; icounts[0] != 0) { MPI_Isend(array+counts->displs[i], counts->counts[i], MPI_CHAR, i, 99, dist_data.intercomm, &(comm_req[i])); } } //print_counts(dist_data, counts.counts, counts.displs, numP_child, "Padres"); } /* * Recibe de los padres un vector que es redistribuido a los procesos * de este grupo. Antes de realizar la comunicacion cada hijo calcula sobre que procesos * del otro grupo se transmiten elementos. * * La recepcion se realiza a partir de una comunicacion colectiva. */ void recv_async_arrays(struct Dist_data dist_data, char *array, int numP_parents, struct Counts *counts, MPI_Request *comm_req) { char *aux = malloc(1); // Ajustar los valores de recepcion prepare_comm_alltoall(dist_data.myId, dist_data.numP, numP_parents, dist_data.qty, counts); //print_counts(dist_data, counts->counts, counts->displs, numP_parents, 1, "Children"); /* COMUNICACION DE DATOS */ MPI_Ialltoallv(aux, counts->zero_arr, counts->zero_arr, MPI_CHAR, array, counts->counts, counts->displs, MPI_CHAR, dist_data.intercomm, comm_req); free(aux); } /* * Recibe de los padres un vector que es redistribuido a los procesos * de este grupo. Antes de realizar la comunicacion cada hijo calcula sobre que procesos * del otro grupo se transmiten elementos. * * La recepcion se realiza a partir de varias comunicaciones punto a punto. */ void recv_async_point_arrays(struct Dist_data dist_data, char *array, int numP_parents, struct Counts *counts, MPI_Request *comm_req) { int i; // Ajustar los valores de recepcion prepare_comm_alltoall(dist_data.myId, dist_data.numP, numP_parents, dist_data.qty, counts); for(i=0; icounts[0] != 0) { MPI_Irecv(array+counts->displs[i], counts->counts[i], MPI_CHAR, i, 99, dist_data.intercomm, &(comm_req[i])); //FIXME BUffer recv } } //print_counts(dist_data, counts.counts, counts.displs, numP_parents, "Hijos"); } /* * ======================================================================================== * ======================================================================================== * ================================DISTRIBUTION FUNCTIONS================================== * ======================================================================================== * ======================================================================================== */ /* * Performs a communication to redistribute an array in a block distribution. For each process calculates * how many elements sends/receives to other processes for the new group. * * - qty (IN): Sum of elements shared by all processes that will send data. * - myId (IN): Rank of the MPI process in the local communicator. For the parents is not the rank obtained from "comm". * - numP (IN): Size of the local group. If it is a children group, this parameter must correspond to using * "MPI_Comm_size(comm)". For the parents is not always the size obtained from "comm". * - numO (IN): Amount of processes in the remote group. For the parents is the target quantity of processes after the * resize, while for the children is the amount of parents. * - is_children_group (IN): Indicates wether this MPI rank is a children(TRUE) or a parent(FALSE). * - is_intercomm (IN): Indicates wether the used communicator is a intercomunicator(TRUE) or intracommunicator(FALSE). * - recv (OUT): Array where data will be written. A NULL value is allowed if the process is not going to receive data. * process receives data and is NULL, the behaviour is undefined. * - s_counts (OUT): Struct where is indicated how many elements sends this process to processes in the new group. * - r_counts (OUT): Struct where is indicated how many elements receives this process from other processes in the previous group. * */ void prepare_redistribution(int qty, int myId, int numP, int numO, int is_children_group, int is_intercomm, char **recv, struct Counts *s_counts, struct Counts *r_counts) { struct Dist_data dist_data; if(is_children_group) { mallocCounts(s_counts, numO); prepare_comm_alltoall(myId, numP, numO, qty, r_counts); // Obtener distribución para este hijo get_block_dist(qty, myId, numP, &dist_data); *recv = malloc(dist_data.tamBl * sizeof(char)); get_block_dist(qty, myId, numP, &dist_data); print_counts(dist_data, r_counts->counts, r_counts->displs, numO, 1, "Children C"); } else { get_block_dist(qty, myId, numP, &dist_data); prepare_comm_alltoall(myId, numP, numO, qty, s_counts); if(is_intercomm) { mallocCounts(r_counts, numO); } else { if(myId < numO) { prepare_comm_alltoall(myId, numO, numP, qty, r_counts); // Obtener distribución para este hijo get_block_dist(qty, myId, numO, &dist_data); *recv = malloc(dist_data.tamBl * sizeof(char)); } else { mallocCounts(r_counts, numP); } print_counts(dist_data, r_counts->counts, r_counts->displs, numP, 1, "Children P "); } print_counts(dist_data, s_counts->counts, s_counts->displs, numO, 1, "Parents "); } } /* * Función para obtener si entre las estrategias elegidas, se utiliza * la estrategia pasada como segundo argumento. * * Devuelve en "result" 1(Verdadero) si utiliza la estrategia, 0(Falso) en caso * contrario. */ int malleability_red_contains_strat(int comm_strategies, int strategy, int *result) { int value = comm_strategies % strategy ? 0 : 1; if(result != NULL) *result = value; return value; }