int MPI_Ssend_init(void *buf, int count, MPI_Datatype type, int dest, int tag, MPI_Comm comm, MPI_Request *request) { int rc; if ( MPI_PARAM_CHECK ) { rc = MPI_SUCCESS; OMPI_ERR_INIT_FINALIZE(FUNC_NAME); if (ompi_comm_invalid(comm)) { return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_COMM, FUNC_NAME); } else if (count < 0) { rc = MPI_ERR_COUNT; } else if (type == MPI_DATATYPE_NULL) { rc = MPI_ERR_TYPE; } else if (tag < 0 || tag > mca_pml.pml_max_tag) { rc = MPI_ERR_TAG; } else if (ompi_comm_peer_invalid(comm, dest) && (MPI_PROC_NULL != dest)) { rc = MPI_ERR_RANK; } else if (request == NULL) { rc = MPI_ERR_REQUEST; } OMPI_ERRHANDLER_CHECK(rc, comm, rc, FUNC_NAME); } if (MPI_PROC_NULL == dest) { *request = OBJ_NEW(ompi_request_t); /* Other fields were initialized by the constructor for ompi_request_t */ (*request)->req_type = OMPI_REQUEST_NOOP; (*request)->req_status = ompi_request_empty.req_status; (*request)->req_complete = true; (*request)->req_state = OMPI_REQUEST_INACTIVE; (*request)->req_persistent = true; (*request)->req_free = ompi_request_persistent_proc_null_free; return MPI_SUCCESS; } rc = MCA_PML_CALL(isend_init(buf,count,type,dest,tag, MCA_PML_BASE_SEND_SYNCHRONOUS,comm,request)); OMPI_ERRHANDLER_RETURN(rc, comm, rc, FUNC_NAME); }
/* * Linear functions are copied from the basic coll module. For * some small number of nodes and/or small data sizes they are just as * fast as tuned/tree based segmenting operations and as such may be * selected by the decision functions. These are copied into this module * due to the way we select modules in V1. i.e. in V2 we will handle this * differently and so will not have to duplicate code. * GEF Oct05 after asking Jeff. */ int ompi_coll_tuned_alltoallv_intra_basic_linear(void *sbuf, int *scounts, int *sdisps, struct ompi_datatype_t *sdtype, void *rbuf, int *rcounts, int *rdisps, struct ompi_datatype_t *rdtype, struct ompi_communicator_t *comm, mca_coll_base_module_t *module) { int i, size, rank, err; char *psnd, *prcv; int nreqs; ptrdiff_t sext, rext; MPI_Request *preq; mca_coll_tuned_module_t *tuned_module = (mca_coll_tuned_module_t*) module; mca_coll_tuned_comm_t *data = tuned_module->tuned_data; size = ompi_comm_size(comm); rank = ompi_comm_rank(comm); OPAL_OUTPUT((ompi_coll_tuned_stream, "coll:tuned:alltoallv_intra_basic_linear rank %d", rank)); ompi_ddt_type_extent(sdtype, &sext); ompi_ddt_type_extent(rdtype, &rext); /* Simple optimization - handle send to self first */ psnd = ((char *) sbuf) + (sdisps[rank] * sext); prcv = ((char *) rbuf) + (rdisps[rank] * rext); if (0 != scounts[rank]) { err = ompi_ddt_sndrcv(psnd, scounts[rank], sdtype, prcv, rcounts[rank], rdtype); if (MPI_SUCCESS != err) { return err; } } /* If only one process, we're done. */ if (1 == size) { return MPI_SUCCESS; } /* Now, initiate all send/recv to/from others. */ nreqs = 0; preq = data->mcct_reqs; /* Post all receives first */ for (i = 0; i < size; ++i) { if (i == rank || 0 == rcounts[i]) { continue; } prcv = ((char *) rbuf) + (rdisps[i] * rext); err = MCA_PML_CALL(irecv_init(prcv, rcounts[i], rdtype, i, MCA_COLL_BASE_TAG_ALLTOALLV, comm, preq++)); ++nreqs; if (MPI_SUCCESS != err) { ompi_coll_tuned_free_reqs(data->mcct_reqs, nreqs); return err; } } /* Now post all sends */ for (i = 0; i < size; ++i) { if (i == rank || 0 == scounts[i]) { continue; } psnd = ((char *) sbuf) + (sdisps[i] * sext); err = MCA_PML_CALL(isend_init(psnd, scounts[i], sdtype, i, MCA_COLL_BASE_TAG_ALLTOALLV, MCA_PML_BASE_SEND_STANDARD, comm, preq++)); ++nreqs; if (MPI_SUCCESS != err) { ompi_coll_tuned_free_reqs(data->mcct_reqs, nreqs); return err; } } /* Start your engines. This will never return an error. */ MCA_PML_CALL(start(nreqs, data->mcct_reqs)); /* Wait for them all. If there's an error, note that we don't care * what the error was -- just that there *was* an error. The PML * will finish all requests, even if one or more of them fail. * i.e., by the end of this call, all the requests are free-able. * So free them anyway -- even if there was an error, and return the * error after we free everything. */ err = ompi_request_wait_all(nreqs, data->mcct_reqs, MPI_STATUSES_IGNORE); /* Free the requests. */ ompi_coll_tuned_free_reqs(data->mcct_reqs, nreqs); return err; }
int ompi_coll_tuned_alltoall_intra_basic_linear(void *sbuf, int scount, struct ompi_datatype_t *sdtype, void* rbuf, int rcount, struct ompi_datatype_t *rdtype, struct ompi_communicator_t *comm) { int i; int rank; int size; int err; int nreqs; char *psnd; char *prcv; MPI_Aint lb; MPI_Aint sndinc; MPI_Aint rcvinc; ompi_request_t **req; ompi_request_t **sreq; ompi_request_t **rreq; /* Initialize. */ size = ompi_comm_size(comm); rank = ompi_comm_rank(comm); OPAL_OUTPUT((ompi_coll_tuned_stream,"ompi_coll_tuned_alltoall_intra_basic_linear rank %d", rank)); err = ompi_ddt_get_extent(sdtype, &lb, &sndinc); if (OMPI_SUCCESS != err) { return err; } sndinc *= scount; err = ompi_ddt_get_extent(rdtype, &lb, &rcvinc); if (OMPI_SUCCESS != err) { return err; } rcvinc *= rcount; /* simple optimization */ psnd = ((char *) sbuf) + (rank * sndinc); prcv = ((char *) rbuf) + (rank * rcvinc); err = ompi_ddt_sndrcv(psnd, scount, sdtype, prcv, rcount, rdtype); if (MPI_SUCCESS != err) { return err; } /* If only one process, we're done. */ if (1 == size) { return MPI_SUCCESS; } /* Initiate all send/recv to/from others. */ req = rreq = comm->c_coll_basic_data->mcct_reqs; sreq = rreq + size - 1; prcv = (char *) rbuf; psnd = (char *) sbuf; /* Post all receives first -- a simple optimization */ for (nreqs = 0, i = (rank + 1) % size; i != rank; i = (i + 1) % size, ++rreq, ++nreqs) { err = MCA_PML_CALL(irecv_init (prcv + (i * rcvinc), rcount, rdtype, i, MCA_COLL_BASE_TAG_ALLTOALL, comm, rreq)); if (MPI_SUCCESS != err) { ompi_coll_tuned_free_reqs(req, rreq - req); return err; } } /* Now post all sends in reverse order - We would like to minimize the search time through message queue when messages actually arrive in the order in which they were posted. */ for (nreqs = 0, i = (rank + size - 1) % size; i != rank; i = (i + size - 1) % size, ++sreq, ++nreqs) { err = MCA_PML_CALL(isend_init (psnd + (i * sndinc), scount, sdtype, i, MCA_COLL_BASE_TAG_ALLTOALL, MCA_PML_BASE_SEND_STANDARD, comm, sreq)); if (MPI_SUCCESS != err) { ompi_coll_tuned_free_reqs(req, sreq - req); return err; } } nreqs = (size - 1) * 2; /* Start your engines. This will never return an error. */ MCA_PML_CALL(start(nreqs, req)); /* Wait for them all. If there's an error, note that we don't * care what the error was -- just that there *was* an error. The * PML will finish all requests, even if one or more of them fail. * i.e., by the end of this call, all the requests are free-able. * So free them anyway -- even if there was an error, and return * the error after we free everything. */ err = ompi_request_wait_all(nreqs, req, MPI_STATUSES_IGNORE); /* Free the reqs */ ompi_coll_tuned_free_reqs(req, nreqs); /* All done */ return err; }
/** * Linear functions are copied from the basic coll module. For * some small number of nodes and/or small data sizes they are just as * fast as base/tree based segmenting operations and as such may be * selected by the decision functions. These are copied into this module * due to the way we select modules in V1. i.e. in V2 we will handle this * differently and so will not have to duplicate code. */ int ompi_coll_base_alltoallv_intra_basic_linear(const void *sbuf, const int *scounts, const int *sdisps, struct ompi_datatype_t *sdtype, void *rbuf, const int *rcounts, const int *rdisps, struct ompi_datatype_t *rdtype, struct ompi_communicator_t *comm, mca_coll_base_module_t *module) { int i, size, rank, err, nreqs; char *psnd, *prcv; ptrdiff_t sext, rext; ompi_request_t **preq, **reqs; mca_coll_base_module_t *base_module = (mca_coll_base_module_t*) module; mca_coll_base_comm_t *data = base_module->base_data; if (MPI_IN_PLACE == sbuf) { return mca_coll_base_alltoallv_intra_basic_inplace (rbuf, rcounts, rdisps, rdtype, comm, module); } size = ompi_comm_size(comm); rank = ompi_comm_rank(comm); OPAL_OUTPUT((ompi_coll_base_framework.framework_output, "coll:base:alltoallv_intra_basic_linear rank %d", rank)); ompi_datatype_type_extent(sdtype, &sext); ompi_datatype_type_extent(rdtype, &rext); /* Simple optimization - handle send to self first */ psnd = ((char *) sbuf) + (ptrdiff_t)sdisps[rank] * sext; prcv = ((char *) rbuf) + (ptrdiff_t)rdisps[rank] * rext; if (0 != scounts[rank]) { err = ompi_datatype_sndrcv(psnd, scounts[rank], sdtype, prcv, rcounts[rank], rdtype); if (MPI_SUCCESS != err) { return err; } } /* If only one process, we're done. */ if (1 == size) { return MPI_SUCCESS; } /* Now, initiate all send/recv to/from others. */ nreqs = 0; reqs = preq = coll_base_comm_get_reqs(data, 2 * size); if( NULL == reqs ) { err = OMPI_ERR_OUT_OF_RESOURCE; goto err_hndl; } /* Post all receives first */ for (i = 0; i < size; ++i) { if (i == rank || 0 == rcounts[i]) { continue; } ++nreqs; prcv = ((char *) rbuf) + (ptrdiff_t)rdisps[i] * rext; err = MCA_PML_CALL(irecv_init(prcv, rcounts[i], rdtype, i, MCA_COLL_BASE_TAG_ALLTOALLV, comm, preq++)); if (MPI_SUCCESS != err) { goto err_hndl; } } /* Now post all sends */ for (i = 0; i < size; ++i) { if (i == rank || 0 == scounts[i]) { continue; } ++nreqs; psnd = ((char *) sbuf) + (ptrdiff_t)sdisps[i] * sext; err = MCA_PML_CALL(isend_init(psnd, scounts[i], sdtype, i, MCA_COLL_BASE_TAG_ALLTOALLV, MCA_PML_BASE_SEND_STANDARD, comm, preq++)); if (MPI_SUCCESS != err) { goto err_hndl; } } /* Start your engines. This will never return an error. */ MCA_PML_CALL(start(nreqs, reqs)); /* Wait for them all. If there's an error, note that we don't care * what the error was -- just that there *was* an error. The PML * will finish all requests, even if one or more of them fail. * i.e., by the end of this call, all the requests are free-able. * So free them anyway -- even if there was an error, and return the * error after we free everything. */ err = ompi_request_wait_all(nreqs, reqs, MPI_STATUSES_IGNORE); err_hndl: /* Free the requests in all cases as they are persistent */ ompi_coll_base_free_reqs(reqs, nreqs); return err; }
/* * bcast_lin_intra * * Function: - broadcast using O(N) algorithm * Accepts: - same arguments as MPI_Bcast() * Returns: - MPI_SUCCESS or error code */ int mca_coll_basic_bcast_lin_intra(void *buff, int count, struct ompi_datatype_t *datatype, int root, struct ompi_communicator_t *comm, mca_coll_base_module_t *module) { int i; int size; int rank; int err; ompi_request_t **preq; mca_coll_basic_module_t *basic_module = (mca_coll_basic_module_t*) module; ompi_request_t **reqs = basic_module->mccb_reqs; size = ompi_comm_size(comm); rank = ompi_comm_rank(comm); /* Non-root receive the data. */ if (rank != root) { return MCA_PML_CALL(recv(buff, count, datatype, root, MCA_COLL_BASE_TAG_BCAST, comm, MPI_STATUS_IGNORE)); } /* Root sends data to all others. */ for (i = 0, preq = reqs; i < size; ++i) { if (i == rank) { continue; } err = MCA_PML_CALL(isend_init(buff, count, datatype, i, MCA_COLL_BASE_TAG_BCAST, MCA_PML_BASE_SEND_STANDARD, comm, preq++)); if (MPI_SUCCESS != err) { return err; } } --i; /* Start your engines. This will never return an error. */ MCA_PML_CALL(start(i, reqs)); /* Wait for them all. If there's an error, note that we don't * care what the error was -- just that there *was* an error. The * PML will finish all requests, even if one or more of them fail. * i.e., by the end of this call, all the requests are free-able. * So free them anyway -- even if there was an error, and return * the error after we free everything. */ err = ompi_request_wait_all(i, reqs, MPI_STATUSES_IGNORE); /* Free the reqs */ mca_coll_basic_free_reqs(reqs, i); /* All done */ return err; }
/* * bcast_log_intra * * Function: - broadcast using O(log(N)) algorithm * Accepts: - same arguments as MPI_Bcast() * Returns: - MPI_SUCCESS or error code */ int mca_coll_basic_bcast_log_intra(void *buff, int count, struct ompi_datatype_t *datatype, int root, struct ompi_communicator_t *comm, mca_coll_base_module_t *module) { int i; int size; int rank; int vrank; int peer; int dim; int hibit; int mask; int err; int nreqs; ompi_request_t **preq; mca_coll_basic_module_t *basic_module = (mca_coll_basic_module_t*) module; ompi_request_t **reqs = basic_module->mccb_reqs; size = ompi_comm_size(comm); rank = ompi_comm_rank(comm); vrank = (rank + size - root) % size; dim = comm->c_cube_dim; hibit = opal_hibit(vrank, dim); --dim; /* Receive data from parent in the tree. */ if (vrank > 0) { peer = ((vrank & ~(1 << hibit)) + root) % size; err = MCA_PML_CALL(recv(buff, count, datatype, peer, MCA_COLL_BASE_TAG_BCAST, comm, MPI_STATUS_IGNORE)); if (MPI_SUCCESS != err) { return err; } } /* Send data to the children. */ err = MPI_SUCCESS; preq = reqs; nreqs = 0; for (i = hibit + 1, mask = 1 << i; i <= dim; ++i, mask <<= 1) { peer = vrank | mask; if (peer < size) { peer = (peer + root) % size; ++nreqs; err = MCA_PML_CALL(isend_init(buff, count, datatype, peer, MCA_COLL_BASE_TAG_BCAST, MCA_PML_BASE_SEND_STANDARD, comm, preq++)); if (MPI_SUCCESS != err) { mca_coll_basic_free_reqs(reqs, nreqs); return err; } } } /* Start and wait on all requests. */ if (nreqs > 0) { /* Start your engines. This will never return an error. */ MCA_PML_CALL(start(nreqs, reqs)); /* Wait for them all. If there's an error, note that we don't * care what the error was -- just that there *was* an error. * The PML will finish all requests, even if one or more of them * fail. i.e., by the end of this call, all the requests are * free-able. So free them anyway -- even if there was an * error, and return the error after we free everything. */ err = ompi_request_wait_all(nreqs, reqs, MPI_STATUSES_IGNORE); /* Free the reqs */ mca_coll_basic_free_reqs(reqs, nreqs); } /* All done */ return err; }
/* * alltoallw_inter * * Function: - MPI_Alltoallw * Accepts: - same as MPI_Alltoallw() * Returns: - MPI_SUCCESS or an MPI error code */ int mca_coll_basic_alltoallw_inter(void *sbuf, int *scounts, int *sdisps, struct ompi_datatype_t **sdtypes, void *rbuf, int *rcounts, int *rdisps, struct ompi_datatype_t **rdtypes, struct ompi_communicator_t *comm, mca_coll_base_module_t *module) { int i; int size; int err; char *psnd; char *prcv; int nreqs; MPI_Request *preq; mca_coll_basic_module_t *basic_module = (mca_coll_basic_module_t*) module; /* Initialize. */ size = ompi_comm_remote_size(comm); /* Initiate all send/recv to/from others. */ nreqs = size * 2; preq = basic_module->mccb_reqs; /* Post all receives first -- a simple optimization */ for (i = 0; i < size; ++i) { prcv = ((char *) rbuf) + rdisps[i]; err = MCA_PML_CALL(irecv_init(prcv, rcounts[i], rdtypes[i], i, MCA_COLL_BASE_TAG_ALLTOALLW, comm, preq++)); if (OMPI_SUCCESS != err) { mca_coll_basic_free_reqs(basic_module->mccb_reqs, nreqs); return err; } } /* Now post all sends */ for (i = 0; i < size; ++i) { psnd = ((char *) sbuf) + sdisps[i]; err = MCA_PML_CALL(isend_init(psnd, scounts[i], sdtypes[i], i, MCA_COLL_BASE_TAG_ALLTOALLW, MCA_PML_BASE_SEND_STANDARD, comm, preq++)); if (OMPI_SUCCESS != err) { mca_coll_basic_free_reqs(basic_module->mccb_reqs, nreqs); return err; } } /* Start your engines. This will never return an error. */ MCA_PML_CALL(start(nreqs, basic_module->mccb_reqs)); /* Wait for them all. If there's an error, note that we don't care * what the error was -- just that there *was* an error. The PML * will finish all requests, even if one or more of them fail. * i.e., by the end of this call, all the requests are free-able. * So free them anyway -- even if there was an error, and return the * error after we free everything. */ err = ompi_request_wait_all(nreqs, basic_module->mccb_reqs, MPI_STATUSES_IGNORE); /* Free the requests. */ mca_coll_basic_free_reqs(basic_module->mccb_reqs, nreqs); /* All done */ return err; }
int ompi_coll_base_alltoall_intra_basic_linear(const void *sbuf, int scount, struct ompi_datatype_t *sdtype, void* rbuf, int rcount, struct ompi_datatype_t *rdtype, struct ompi_communicator_t *comm, mca_coll_base_module_t *module) { int i, rank, size, err, line; int nreqs = 0; char *psnd, *prcv; MPI_Aint lb, sndinc, rcvinc; ompi_request_t **req, **sreq, **rreq; mca_coll_base_module_t *base_module = (mca_coll_base_module_t*) module; mca_coll_base_comm_t *data = base_module->base_data; if (MPI_IN_PLACE == sbuf) { return mca_coll_base_alltoall_intra_basic_inplace (rbuf, rcount, rdtype, comm, module); } /* Initialize. */ size = ompi_comm_size(comm); rank = ompi_comm_rank(comm); OPAL_OUTPUT((ompi_coll_base_framework.framework_output, "ompi_coll_base_alltoall_intra_basic_linear rank %d", rank)); err = ompi_datatype_get_extent(sdtype, &lb, &sndinc); if (OMPI_SUCCESS != err) { return err; } sndinc *= scount; err = ompi_datatype_get_extent(rdtype, &lb, &rcvinc); if (OMPI_SUCCESS != err) { return err; } rcvinc *= rcount; /* simple optimization */ psnd = ((char *) sbuf) + (ptrdiff_t)rank * sndinc; prcv = ((char *) rbuf) + (ptrdiff_t)rank * rcvinc; err = ompi_datatype_sndrcv(psnd, scount, sdtype, prcv, rcount, rdtype); if (MPI_SUCCESS != err) { return err; } /* If only one process, we're done. */ if (1 == size) { return MPI_SUCCESS; } /* Initiate all send/recv to/from others. */ req = rreq = coll_base_comm_get_reqs(data, (size - 1) * 2); if (NULL == req) { err = OMPI_ERR_OUT_OF_RESOURCE; line = __LINE__; goto err_hndl; } prcv = (char *) rbuf; psnd = (char *) sbuf; /* Post all receives first -- a simple optimization */ for (nreqs = 0, i = (rank + 1) % size; i != rank; i = (i + 1) % size, ++rreq) { nreqs++; err = MCA_PML_CALL(irecv_init (prcv + (ptrdiff_t)i * rcvinc, rcount, rdtype, i, MCA_COLL_BASE_TAG_ALLTOALL, comm, rreq)); if (MPI_SUCCESS != err) { line = __LINE__; goto err_hndl; } } /* Now post all sends in reverse order - We would like to minimize the search time through message queue when messages actually arrive in the order in which they were posted. */ sreq = rreq; for (i = (rank + size - 1) % size; i != rank; i = (i + size - 1) % size, ++sreq) { nreqs++; err = MCA_PML_CALL(isend_init (psnd + (ptrdiff_t)i * sndinc, scount, sdtype, i, MCA_COLL_BASE_TAG_ALLTOALL, MCA_PML_BASE_SEND_STANDARD, comm, sreq)); if (MPI_SUCCESS != err) { line = __LINE__; goto err_hndl; } } /* Start your engines. This will never return an error. */ MCA_PML_CALL(start(nreqs, req)); /* Wait for them all. If there's an error, note that we don't * care what the error was -- just that there *was* an error. The * PML will finish all requests, even if one or more of them fail. * i.e., by the end of this call, all the requests are free-able. * So free them anyway -- even if there was an error, and return * the error after we free everything. */ err = ompi_request_wait_all(nreqs, req, MPI_STATUSES_IGNORE); if (MPI_SUCCESS != err) { line = __LINE__; goto err_hndl; } err_hndl: if( MPI_SUCCESS != err ) { OPAL_OUTPUT( (ompi_coll_base_framework.framework_output,"%s:%4d\tError occurred %d, rank %2d", __FILE__, line, err, rank) ); (void)line; // silence compiler warning } /* Free the reqs in all cases as they are persistent requests */ ompi_coll_base_free_reqs(req, nreqs); /* All done */ return err; }
/* * alltoall_intra * * Function: - MPI_Alltoall * Accepts: - same as MPI_Alltoall() * Returns: - MPI_SUCCESS or an MPI error code */ int mca_coll_basic_alltoall_intra(void *sbuf, int scount, struct ompi_datatype_t *sdtype, void *rbuf, int rcount, struct ompi_datatype_t *rdtype, struct ompi_communicator_t *comm, mca_coll_base_module_t *module) { int i; int rank; int size; int err; int nreqs; char *psnd; char *prcv; MPI_Aint lb; MPI_Aint sndinc; MPI_Aint rcvinc; ompi_request_t **req; ompi_request_t **sreq; ompi_request_t **rreq; mca_coll_basic_module_t *basic_module = (mca_coll_basic_module_t*) module; /* Initialize. */ size = ompi_comm_size(comm); rank = ompi_comm_rank(comm); err = ompi_datatype_get_extent(sdtype, &lb, &sndinc); if (OMPI_SUCCESS != err) { return err; } sndinc *= scount; err = ompi_datatype_get_extent(rdtype, &lb, &rcvinc); if (OMPI_SUCCESS != err) { return err; } rcvinc *= rcount; /* simple optimization */ psnd = ((char *) sbuf) + (rank * sndinc); prcv = ((char *) rbuf) + (rank * rcvinc); err = ompi_datatype_sndrcv(psnd, scount, sdtype, prcv, rcount, rdtype); if (MPI_SUCCESS != err) { return err; } /* If only one process, we're done. */ if (1 == size) { return MPI_SUCCESS; } /* Initiate all send/recv to/from others. */ req = rreq = basic_module->mccb_reqs; sreq = rreq + size - 1; prcv = (char *) rbuf; psnd = (char *) sbuf; /* Post all receives first -- a simple optimization */ for (nreqs = 0, i = (rank + 1) % size; i != rank; i = (i + 1) % size, ++rreq, ++nreqs) { err = MCA_PML_CALL(irecv_init (prcv + (i * rcvinc), rcount, rdtype, i, MCA_COLL_BASE_TAG_ALLTOALL, comm, rreq)); if (MPI_SUCCESS != err) { mca_coll_basic_free_reqs(req, nreqs); return err; } } /* Now post all sends */ for (nreqs = 0, i = (rank + 1) % size; i != rank; i = (i + 1) % size, ++sreq, ++nreqs) { err = MCA_PML_CALL(isend_init (psnd + (i * sndinc), scount, sdtype, i, MCA_COLL_BASE_TAG_ALLTOALL, MCA_PML_BASE_SEND_STANDARD, comm, sreq)); if (MPI_SUCCESS != err) { mca_coll_basic_free_reqs(req, nreqs); return err; } } nreqs = (size - 1) * 2; /* Start your engines. This will never return an error. */ MCA_PML_CALL(start(nreqs, req)); /* Wait for them all. If there's an error, note that we don't * care what the error was -- just that there *was* an error. The * PML will finish all requests, even if one or more of them fail. * i.e., by the end of this call, all the requests are free-able. * So free them anyway -- even if there was an error, and return * the error after we free everything. */ err = ompi_request_wait_all(nreqs, req, MPI_STATUSES_IGNORE); /* Free the reqs */ mca_coll_basic_free_reqs(req, nreqs); /* All done */ return err; }
/* * alltoallw_intra * * Function: - MPI_Alltoallw * Accepts: - same as MPI_Alltoallw() * Returns: - MPI_SUCCESS or an MPI error code */ int mca_coll_basic_alltoallw_intra(const void *sbuf, const int *scounts, const int *sdisps, struct ompi_datatype_t * const *sdtypes, void *rbuf, const int *rcounts, const int *rdisps, struct ompi_datatype_t * const *rdtypes, struct ompi_communicator_t *comm, mca_coll_base_module_t *module) { int i; int size; int rank; int err; char *psnd; char *prcv; int nreqs; MPI_Request *preq, *reqs; /* Initialize. */ if (MPI_IN_PLACE == sbuf) { return mca_coll_basic_alltoallw_intra_inplace (rbuf, rcounts, rdisps, rdtypes, comm, module); } size = ompi_comm_size(comm); rank = ompi_comm_rank(comm); /* simple optimization */ psnd = ((char *) sbuf) + sdisps[rank]; prcv = ((char *) rbuf) + rdisps[rank]; err = ompi_datatype_sndrcv(psnd, scounts[rank], sdtypes[rank], prcv, rcounts[rank], rdtypes[rank]); if (MPI_SUCCESS != err) { return err; } /* If only one process, we're done. */ if (1 == size) { return MPI_SUCCESS; } /* Initiate all send/recv to/from others. */ nreqs = 0; reqs = preq = coll_base_comm_get_reqs(module->base_data, 2 * size); /* Post all receives first -- a simple optimization */ for (i = 0; i < size; ++i) { size_t msg_size; ompi_datatype_type_size(rdtypes[i], &msg_size); msg_size *= rcounts[i]; if (i == rank || 0 == msg_size) continue; prcv = ((char *) rbuf) + rdisps[i]; err = MCA_PML_CALL(irecv_init(prcv, rcounts[i], rdtypes[i], i, MCA_COLL_BASE_TAG_ALLTOALLW, comm, preq++)); ++nreqs; if (MPI_SUCCESS != err) { ompi_coll_base_free_reqs(reqs, nreqs); return err; } } /* Now post all sends */ for (i = 0; i < size; ++i) { size_t msg_size; ompi_datatype_type_size(sdtypes[i], &msg_size); msg_size *= scounts[i]; if (i == rank || 0 == msg_size) continue; psnd = ((char *) sbuf) + sdisps[i]; err = MCA_PML_CALL(isend_init(psnd, scounts[i], sdtypes[i], i, MCA_COLL_BASE_TAG_ALLTOALLW, MCA_PML_BASE_SEND_STANDARD, comm, preq++)); ++nreqs; if (MPI_SUCCESS != err) { ompi_coll_base_free_reqs(reqs, nreqs); return err; } } /* Start your engines. This will never return an error. */ MCA_PML_CALL(start(nreqs, reqs)); /* Wait for them all. If there's an error, note that we don't care * what the error was -- just that there *was* an error. The PML * will finish all requests, even if one or more of them fail. * i.e., by the end of this call, all the requests are free-able. * So free them anyway -- even if there was an error, and return the * error after we free everything. */ err = ompi_request_wait_all(nreqs, reqs, MPI_STATUSES_IGNORE); /* Free the requests in all cases as they are persistent */ ompi_coll_base_free_reqs(reqs, nreqs); /* All done */ return err; }