/*! \file ep_gather.cpp \since 2 may 2016 \brief Definitions of MPI collective function: MPI_Gatherv, MPI_Allgatherv */ #include "ep_lib.hpp" #include #include "ep_declaration.hpp" #include "ep_mpi.hpp" using namespace std; namespace ep_lib { int MPI_Allgatherv(const void *sendbuf, int sendcount, MPI_Datatype sendtype, void *recvbuf, const int recvcounts[], const int displs[], MPI_Datatype recvtype, MPI_Comm comm) { if(!comm->is_ep && comm->mpi_comm) { return ::MPI_Allgatherv(sendbuf, sendcount, to_mpi_type(sendtype), recvbuf, recvcounts, displs, to_mpi_type(recvtype), to_mpi_comm(comm->mpi_comm)); } if(!comm->mpi_comm) return 0; assert(valid_type(sendtype) && valid_type(recvtype)); MPI_Datatype datatype = sendtype; int count = sendcount; ::MPI_Aint datasize, lb; ::MPI_Type_get_extent(to_mpi_type(datatype), &lb, &datasize); int ep_rank = comm->ep_comm_ptr->size_rank_info[0].first; int ep_rank_loc = comm->ep_comm_ptr->size_rank_info[1].first; int mpi_rank = comm->ep_comm_ptr->size_rank_info[2].first; int ep_size = comm->ep_comm_ptr->size_rank_info[0].second; int num_ep = comm->ep_comm_ptr->size_rank_info[1].second; int mpi_size = comm->ep_comm_ptr->size_rank_info[2].second; assert(sendcount == recvcounts[ep_rank]); bool is_master = ep_rank_loc==0; void* local_recvbuf; void* tmp_recvbuf; int recvbuf_size = 0; for(int i=0; ilocal_recvcounts(num_ep, 0); vectorlocal_displs(num_ep, 0); MPI_Gather_local(&sendcount, 1, MPI_INT, local_recvcounts.data(), 0, comm); for(int i=1; impi_recvcounts(mpi_size, 0); std::vectormpi_displs(mpi_size, 0); int local_sendcount = std::accumulate(local_recvcounts.begin(), local_recvcounts.end(), 0); ::MPI_Allgather(&local_sendcount, 1, to_mpi_type(MPI_INT), mpi_recvcounts.data(), 1, to_mpi_type(MPI_INT), to_mpi_comm(comm->mpi_comm)); for(int i=1; impi_comm)); // reorder int offset; for(int i=0; iep_rank_map->at(i).first; j++) if(comm->ep_rank_map->at(i).second == comm->ep_rank_map->at(j).second) { extra += recvcounts[j]; k++; } offset = mpi_displs[comm->ep_rank_map->at(i).second] + extra; memcpy(recvbuf+displs[i]*datasize, tmp_recvbuf+offset*datasize, recvcounts[i]*datasize); } } MPI_Bcast_local(recvbuf, recvbuf_size, datatype, 0, comm); if(is_master) { delete[] local_recvbuf; delete[] tmp_recvbuf; } } }