#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 check_requests(struct Counts s_counts, struct Counts r_counts, MPI_Request **requests, size_t *request_qty); void sync_point2point(char *send, char *recv, int is_intercomm, int myId, struct Counts s_counts, struct Counts r_counts, MPI_Comm comm); 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 async_point2point(char *send, char *recv, struct Counts s_counts, struct Counts r_counts, MPI_Comm comm, MPI_Request *requests); void perform_manual_communication(char *send, char *recv, int myId, struct Counts s_counts, struct Counts r_counts); /* * 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; i numO ? numP : numO; } if(is_children_group) { if(is_intercomm) { mallocCounts(s_counts, numO); } else { // Merge method needs an array equal to the number of processes mallocCounts(s_counts, array_size); mallocCounts(r_counts, array_size); init_struct = 0; } prepare_comm_alltoall(myId, numP, numO, qty, init_struct, 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, 0, "Children C "); } else { //get_block_dist(qty, myId, numP, &dist_data); if(is_intercomm) { mallocCounts(r_counts, numO); prepare_comm_alltoall(myId, numP, numO, qty, init_struct, s_counts); } else { mallocCounts(s_counts, array_size); mallocCounts(r_counts, array_size); init_struct = 0; prepare_comm_alltoall(myId, numP, numO, qty, init_struct, s_counts); if(myId < numO) { prepare_comm_alltoall(myId, numO, numP, qty, init_struct, r_counts); // Obtener distribución para este hijo get_block_dist(qty, myId, numO, &dist_data); *recv = malloc(dist_data.tamBl * sizeof(char)); } //print_counts(dist_data, r_counts->counts, r_counts->displs, array_size, 0, "Children P "); } //print_counts(dist_data, s_counts->counts, s_counts->displs, numO, 0, "Parents "); } } /* * Ensures that the array of request of a process has an amount of elements equal to the amount of communication * functions the process will perform. In case the array is not initialized or does not have enough space it is * allocated/reallocated to the minimum amount of space needed. * * - s_counts (IN): Struct where is indicated how many elements sends this process to processes in the new group. * - r_counts (IN): Struct where is indicated how many elements receives this process from other processes in the previous group. * - requests (OUT): Pointer to array of requests to be used to determine if the communication has ended. If the pointer * is null or not enough space has been reserved the pointer is allocated/reallocated. * - request_qty (OUT): Quantity of requests to be used. If the value is smaller than the amount of communication * functions to perform, it is modified to the minimum value. */ void check_requests(struct Counts s_counts, struct Counts r_counts, MPI_Request **requests, size_t *request_qty) { size_t i, sum; MPI_Request *aux; sum = (size_t) s_counts.idE - s_counts.idI; sum += (size_t) r_counts.idE - r_counts.idI; if (*requests != NULL && sum <= *request_qty) return; // Expected amount of requests // FIXME Si es la estrategia Ibarrier como se tiene en cuenta en el total?? if (*requests == NULL) { *requests = (MPI_Request *) malloc(sum * sizeof(MPI_Request)); } else { // Array exists, but is too small aux = (MPI_Request *) realloc(*requests, sum * sizeof(MPI_Request)); *requests = aux; } if (*requests == NULL) { fprintf(stderr, "Fatal error - It was not possible to allocate/reallocate memory for the MPI_Requests before the redistribution\n"); MPI_Abort(MPI_COMM_WORLD, 1); } for(i=0; i < sum; i++) { (*requests)[i] = MPI_REQUEST_NULL; } *request_qty = sum; } /* * Special case to perform a manual copy of data when a process has to send data to itself. Only used * when the MPI communication is not able to hand this situation. An example is when using point to point * communications and the process has to perform a Send and Recv to itself * - send (IN): Array with the data to send. This value can not be NULL. * - recv (OUT): Array where data will be written. This value can not be NULL. * - myId (IN): Rank of the MPI process in the local communicator. For the parents is not the rank obtained from "comm". * - s_counts (IN): Struct where is indicated how many elements sends this process to processes in the new group. * - r_counts (IN): Struct where is indicated how many elements receives this process from other processes in the previous group. */ void perform_manual_communication(char *send, char *recv, int myId, struct Counts s_counts, struct Counts r_counts) { int i; for(i=0; i