|
Packit Service |
c5cf8c |
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
|
|
Packit Service |
c5cf8c |
/*
|
|
Packit Service |
c5cf8c |
* (C) 2017 by Argonne National Laboratory.
|
|
Packit Service |
c5cf8c |
* See COPYRIGHT in top-level directory.
|
|
Packit Service |
c5cf8c |
*/
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#include "mpiimpl.h"
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#undef FUNCNAME
|
|
Packit Service |
c5cf8c |
#define FUNCNAME MPIR_Ialltoallv_sched_intra_inplace
|
|
Packit Service |
c5cf8c |
#undef FCNAME
|
|
Packit Service |
c5cf8c |
#define FCNAME MPL_QUOTE(FUNCNAME)
|
|
Packit Service |
c5cf8c |
int MPIR_Ialltoallv_sched_intra_inplace(const void *sendbuf, const int sendcounts[],
|
|
Packit Service |
c5cf8c |
const int sdispls[], MPI_Datatype sendtype, void *recvbuf,
|
|
Packit Service |
c5cf8c |
const int recvcounts[], const int rdispls[],
|
|
Packit Service |
c5cf8c |
MPI_Datatype recvtype, MPIR_Comm * comm_ptr, MPIR_Sched_t s)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
int max_count;
|
|
Packit Service |
c5cf8c |
void *tmp_buf = NULL;
|
|
Packit Service |
c5cf8c |
int mpi_errno = MPI_SUCCESS;
|
|
Packit Service |
c5cf8c |
int comm_size;
|
|
Packit Service |
c5cf8c |
int i, j;
|
|
Packit Service |
c5cf8c |
MPI_Aint recv_extent;
|
|
Packit Service |
c5cf8c |
int dst, rank;
|
|
Packit Service |
c5cf8c |
MPIR_SCHED_CHKPMEM_DECL(1);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
comm_size = comm_ptr->local_size;
|
|
Packit Service |
c5cf8c |
rank = comm_ptr->rank;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Get extent and size of recvtype, don't look at sendtype for MPI_IN_PLACE */
|
|
Packit Service |
c5cf8c |
MPIR_Datatype_get_extent_macro(recvtype, recv_extent);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* The regular MPI_Alltoallv handles MPI_IN_PLACE using pairwise
|
|
Packit Service |
c5cf8c |
* sendrecv_replace calls. We don't have a sendrecv_replace, so just
|
|
Packit Service |
c5cf8c |
* malloc the maximum of the counts array entries and then perform the
|
|
Packit Service |
c5cf8c |
* pairwise exchanges manually with schedule barriers instead.
|
|
Packit Service |
c5cf8c |
*
|
|
Packit Service |
c5cf8c |
* Because of this approach all processes must agree on the global
|
|
Packit Service |
c5cf8c |
* schedule of "sendrecv_replace" operations to avoid deadlock.
|
|
Packit Service |
c5cf8c |
*
|
|
Packit Service |
c5cf8c |
* This keeps with the spirit of the MPI-2.2 standard, which is to
|
|
Packit Service |
c5cf8c |
* conserve memory when using MPI_IN_PLACE for these routines.
|
|
Packit Service |
c5cf8c |
* Something like MADRE would probably generate a more optimal
|
|
Packit Service |
c5cf8c |
* algorithm. */
|
|
Packit Service |
c5cf8c |
max_count = 0;
|
|
Packit Service |
c5cf8c |
for (i = 0; i < comm_size; ++i) {
|
|
Packit Service |
c5cf8c |
max_count = MPL_MAX(max_count, recvcounts[i]);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPIR_SCHED_CHKPMEM_MALLOC(tmp_buf, void *, max_count * recv_extent, mpi_errno,
|
|
Packit Service |
c5cf8c |
"Ialltoallv tmp_buf", MPL_MEM_BUFFER);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
for (i = 0; i < comm_size; ++i) {
|
|
Packit Service |
c5cf8c |
/* start inner loop at i to avoid re-exchanging data */
|
|
Packit Service |
c5cf8c |
for (j = i; j < comm_size; ++j) {
|
|
Packit Service |
c5cf8c |
if (rank == i && rank == j) {
|
|
Packit Service |
c5cf8c |
/* no need to "sendrecv_replace" for ourselves */
|
|
Packit Service |
c5cf8c |
} else if (rank == i || rank == j) {
|
|
Packit Service |
c5cf8c |
if (rank == i)
|
|
Packit Service |
c5cf8c |
dst = j;
|
|
Packit Service |
c5cf8c |
else
|
|
Packit Service |
c5cf8c |
dst = i;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
mpi_errno = MPIR_Sched_send(((char *) recvbuf + rdispls[dst] * recv_extent),
|
|
Packit Service |
c5cf8c |
recvcounts[dst], recvtype, dst, comm_ptr, s);
|
|
Packit Service |
c5cf8c |
if (mpi_errno)
|
|
Packit Service |
c5cf8c |
MPIR_ERR_POP(mpi_errno);
|
|
Packit Service |
c5cf8c |
mpi_errno = MPIR_Sched_recv(tmp_buf, recvcounts[dst], recvtype, dst, comm_ptr, s);
|
|
Packit Service |
c5cf8c |
if (mpi_errno)
|
|
Packit Service |
c5cf8c |
MPIR_ERR_POP(mpi_errno);
|
|
Packit Service |
c5cf8c |
MPIR_SCHED_BARRIER(s);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
mpi_errno = MPIR_Sched_copy(tmp_buf, recvcounts[dst], recvtype,
|
|
Packit Service |
c5cf8c |
((char *) recvbuf + rdispls[dst] * recv_extent),
|
|
Packit Service |
c5cf8c |
recvcounts[dst], recvtype, s);
|
|
Packit Service |
c5cf8c |
if (mpi_errno)
|
|
Packit Service |
c5cf8c |
MPIR_ERR_POP(mpi_errno);
|
|
Packit Service |
c5cf8c |
MPIR_SCHED_BARRIER(s);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPIR_SCHED_BARRIER(s);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPIR_SCHED_CHKPMEM_COMMIT(s);
|
|
Packit Service |
c5cf8c |
fn_exit:
|
|
Packit Service |
c5cf8c |
return mpi_errno;
|
|
Packit Service |
c5cf8c |
fn_fail:
|
|
Packit Service |
c5cf8c |
MPIR_SCHED_CHKPMEM_REAP(s);
|
|
Packit Service |
c5cf8c |
goto fn_exit;
|
|
Packit Service |
c5cf8c |
}
|