#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 comm_type); 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); void getIds_intercomm(struct Dist_data dist_data, int numP_other, int **idS); /* * 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, 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 "); } } /* * Obtiene para un proceso de un grupo a que rango procesos de * otro grupo tiene que enviar o recibir datos. * * Devuelve el primer identificador y el último (Excluido) con el que * comunicarse. */ void getIds_intercomm(struct Dist_data dist_data, int numP_other, int **idS) { int idI, idE; int tamOther = dist_data.qty / numP_other; int remOther = dist_data.qty % numP_other; // Indica el punto de corte del grupo de procesos externo que // divide entre los procesos que tienen // un tamaño tamOther + 1 y un tamaño tamOther int middle = (tamOther + 1) * remOther; // Calcular idI teniendo en cuenta si se comunica con un // proceso con tamano tamOther o tamOther+1 if(middle > dist_data.ini) { // First subgroup (tamOther+1) idI = dist_data.ini / (tamOther + 1); } else { // Second subgroup (tamOther) idI = ((dist_data.ini - middle) / tamOther) + remOther; } // Calcular idR teniendo en cuenta si se comunica con un // proceso con tamano tamOther o tamOther+1 if(middle >= dist_data.fin) { // First subgroup (tamOther +1) idE = dist_data.fin / (tamOther + 1); idE = (dist_data.fin % (tamOther + 1) > 0 && idE+1 <= numP_other) ? idE+1 : idE; } else { // Second subgroup (tamOther) idE = ((dist_data.fin - middle) / tamOther) + remOther; idE = ((dist_data.fin - middle) % tamOther > 0 && idE+1 <= numP_other) ? idE+1 : idE; } *idS = malloc(2 * sizeof(int)); (*idS)[0] = idI; (*idS)[1] = idE; }