int sc_allgather (void *sendbuf, int sendcount, sc_MPI_Datatype sendtype, void *recvbuf, int recvcount, sc_MPI_Datatype recvtype, sc_MPI_Comm mpicomm) { int mpiret; int mpisize; int mpirank; size_t datasize; #ifdef SC_DEBUG size_t datasize2; #endif SC_ASSERT (sendcount >= 0 && recvcount >= 0); /* *INDENT-OFF* HORRIBLE indent bug */ datasize = (size_t) sendcount * sc_mpi_sizeof (sendtype); #ifdef SC_DEBUG datasize2 = (size_t) recvcount * sc_mpi_sizeof (recvtype); #endif /* *INDENT-ON* */ SC_ASSERT (datasize == datasize2); mpiret = sc_MPI_Comm_size (mpicomm, &mpisize); SC_CHECK_MPI (mpiret); mpiret = sc_MPI_Comm_rank (mpicomm, &mpirank); SC_CHECK_MPI (mpiret); memcpy (((char *) recvbuf) + mpirank * datasize, sendbuf, datasize); sc_allgather_recursive (mpicomm, (char *) recvbuf, (int) datasize, mpisize, mpirank, mpirank); return sc_MPI_SUCCESS; }
static void sc_reduce_alltoall (MPI_Comm mpicomm, void *data, int count, MPI_Datatype datatype, int groupsize, int target, int maxlevel, int level, int branch, sc_reduce_t reduce_fn) { int i, l; int mpiret; int doall, allcount; int myrank, peer, peer2; int shift; char *alldata; size_t datasize; MPI_Request *request, *rrequest, *srequest; doall = 0; if (target == -1) { doall = 1; target = 0; } SC_ASSERT (0 <= target && target < groupsize); myrank = sc_search_bias (maxlevel, level, branch, target); SC_ASSERT (0 <= myrank && myrank < groupsize); SC_ASSERT (reduce_fn != NULL); /* *INDENT-OFF* HORRIBLE indent bug */ datasize = (size_t) count * sc_mpi_sizeof (datatype); /* *INDENT-ON* */ if (doall || target == myrank) { allcount = 1 << level; alldata = SC_ALLOC (char, allcount * datasize); request = SC_ALLOC (MPI_Request, 2 * allcount); rrequest = request; srequest = request + allcount; for (i = 0; i < allcount; ++i) { peer = sc_search_bias (maxlevel, level, i, target); /* communicate with existing peers */ if (peer == myrank) { memcpy (alldata + i * datasize, data, datasize); rrequest[i] = srequest[i] = MPI_REQUEST_NULL; } else { if (peer < groupsize) { mpiret = MPI_Irecv (alldata + i * datasize, datasize, MPI_BYTE, peer, SC_TAG_REDUCE, mpicomm, rrequest + i); SC_CHECK_MPI (mpiret); if (doall) { mpiret = MPI_Isend (data, datasize, MPI_BYTE, peer, SC_TAG_REDUCE, mpicomm, srequest + i); SC_CHECK_MPI (mpiret); } else { srequest[i] = MPI_REQUEST_NULL; /* unused */ } } else { /* ignore non-existing ranks greater or equal mpisize */ rrequest[i] = srequest[i] = MPI_REQUEST_NULL; } } } /* complete receive operations */ mpiret = MPI_Waitall (allcount, rrequest, MPI_STATUSES_IGNORE); SC_CHECK_MPI (mpiret); /* process received data in the same order as sc_reduce_recursive */ for (shift = 0, l = level - 1; l >= 0; ++shift, --l) { for (i = 0; i < 1 << l; ++i) { #ifdef SC_DEBUG peer = sc_search_bias (maxlevel, l + 1, 2 * i, target); #endif peer2 = sc_search_bias (maxlevel, l + 1, 2 * i + 1, target); SC_ASSERT (peer < peer2); if (peer2 < groupsize) { reduce_fn (alldata + ((2 * i + 1) << shift) * datasize, alldata + ((2 * i) << shift) * datasize, count, datatype); } } } memcpy (data, alldata, datasize); SC_FREE (alldata); /* alldata is not used in send buffers */ /* wait for sends only after computation is done */ if (doall) { mpiret = MPI_Waitall (allcount, srequest, MPI_STATUSES_IGNORE); SC_CHECK_MPI (mpiret); } SC_FREE (request); }