X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/blobdiff_plain/3d25ce2fc68666d4b674c4f710cde362aa584632..d53d00d608a60a6f05e77ea7b7cd5c4e544d7ab1:/src/smpi/colls/allgatherv-mpich-rdb.cpp diff --git a/src/smpi/colls/allgatherv-mpich-rdb.cpp b/src/smpi/colls/allgatherv-mpich-rdb.cpp new file mode 100644 index 0000000000..099297c646 --- /dev/null +++ b/src/smpi/colls/allgatherv-mpich-rdb.cpp @@ -0,0 +1,216 @@ +/* Copyright (c) 2013-2014. The SimGrid Team. + * All rights reserved. */ + +/* This program is free software; you can redistribute it and/or modify it + * under the terms of the license (GNU LGPL) which comes with this package. */ + + /* Short or medium size message and power-of-two no. of processes. Use + * recursive doubling algorithm */ +#include "colls_private.h" +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) +{ + unsigned int j, i; + MPI_Status status; + MPI_Aint recvtype_extent, recvtype_true_extent, recvtype_true_lb; + unsigned int curr_cnt, dst, total_count; + void *tmp_buf, *tmp_buf_rl; + unsigned int mask, dst_tree_root, my_tree_root, position, + send_offset, recv_offset, last_recv_cnt=0, nprocs_completed, k, + offset, tmp_mask, tree_root; + + unsigned int comm_size = smpi_comm_size(comm); + unsigned int 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, + COLL_TAG_ALLGATHERV, 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, COLL_TAG_ALLGATHERV, + 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