From da41b147264c6eb7febc5be6cfb2380eab69ba70 Mon Sep 17 00:00:00 2001 From: degomme Date: Fri, 14 Jun 2013 00:56:09 +0200 Subject: [PATCH] forgot one file --- src/smpi/colls/allgatherv-mpich-rdb.c | 211 ++++++++++++++++++++++++++ 1 file changed, 211 insertions(+) create mode 100644 src/smpi/colls/allgatherv-mpich-rdb.c diff --git a/src/smpi/colls/allgatherv-mpich-rdb.c b/src/smpi/colls/allgatherv-mpich-rdb.c new file mode 100644 index 0000000000..3a65b3058e --- /dev/null +++ b/src/smpi/colls/allgatherv-mpich-rdb.c @@ -0,0 +1,211 @@ + /* Short or medium size message and power-of-two no. of processes. Use + * recursive doubling algorithm */ +#include "colls_private.h" +#define MPIR_ALLGATHERV_TAG 222 +int smpi_coll_tuned_allgatherv_mpich_rdb ( + void *sendbuf, + int sendcount, + MPI_Datatype sendtype, + void *recvbuf, + int *recvcounts, + int *displs, + MPI_Datatype recvtype, + MPI_Comm comm) +{ + int comm_size, rank, j, i; + MPI_Status status; + MPI_Aint recvtype_extent, recvtype_true_extent, recvtype_true_lb; + int curr_cnt, dst, total_count; + void *tmp_buf; + int mask, dst_tree_root, my_tree_root, is_homogeneous, position, + send_offset, recv_offset, last_recv_cnt=0, nprocs_completed, k, + offset, tmp_mask, tree_root; + + comm_size = smpi_comm_size(comm); + rank = smpi_comm_rank(comm); + + total_count = 0; + for (i=0; i> i; + dst_tree_root <<= i; + + my_tree_root = rank >> i; + my_tree_root <<= i; + + if (dst < comm_size) { + send_offset = 0; + for (j=0; j comm_size) { + nprocs_completed = comm_size - my_tree_root - mask; + /* nprocs_completed is the number of processes in this + subtree that have all the data. Send data to others + in a tree fashion. First find root of current tree + that is being divided into two. k is the number of + least-significant bits in this process's rank that + must be zeroed out to find the rank of the root */ + j = mask; + k = 0; + while (j) { + j >>= 1; + k++; + } + k--; + + tmp_mask = mask >> 1; + + while (tmp_mask) { + dst = rank ^ tmp_mask; + + tree_root = rank >> k; + tree_root <<= k; + + /* send only if this proc has data and destination + doesn't have data. at any step, multiple processes + can send if they have the data */ + if ((dst > rank) && + (rank < tree_root + nprocs_completed) + && (dst >= tree_root + nprocs_completed)) { + + offset = 0; + for (j=0; j<(my_tree_root+mask); j++) + offset += recvcounts[j]; + offset *= recvtype_extent; + + smpi_mpi_send(((char *)tmp_buf + offset), + last_recv_cnt, + recvtype, dst, + MPIR_ALLGATHERV_TAG, comm); + /* last_recv_cnt was set in the previous + receive. that's the amount of data to be + sent now. */ + } + /* recv only if this proc. doesn't have data and sender + has data */ + else if ((dst < rank) && + (dst < tree_root + nprocs_completed) && + (rank >= tree_root + nprocs_completed)) { + + offset = 0; + for (j=0; j<(my_tree_root+mask); j++) + offset += recvcounts[j]; + + smpi_mpi_recv(((char *)tmp_buf + offset * recvtype_extent), + total_count - offset, recvtype, + dst, MPIR_ALLGATHERV_TAG, + comm, &status); + /* for convenience, recv is posted for a + bigger amount than will be sent */ + last_recv_cnt=smpi_mpi_get_count(&status, recvtype); + curr_cnt += last_recv_cnt; + } + tmp_mask >>= 1; + k--; + } + } + /* --END EXPERIMENTAL-- */ + + mask <<= 1; + i++; + } + + /* copy data from tmp_buf to recvbuf */ + position = 0; + for (j=0; j