22 * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana
33 * University Research and Technology
44 * Corporation. All rights reserved.
5- * Copyright (c) 2004-2010 The University of Tennessee and The University
5+ * Copyright (c) 2004-2017 The University of Tennessee and The University
66 * of Tennessee Research Foundation. All rights
77 * reserved.
88 * Copyright (c) 2004-2008 High Performance Computing Center Stuttgart,
@@ -48,10 +48,10 @@ int MPI_Sendrecv_replace(void * buf, int count, MPI_Datatype datatype,
4848 int rc = MPI_SUCCESS ;
4949
5050 MEMCHECKER (
51- memchecker_datatype (datatype );
52- memchecker_call (& opal_memchecker_base_isdefined , buf , count , datatype );
53- memchecker_comm (comm );
54- );
51+ memchecker_datatype (datatype );
52+ memchecker_call (& opal_memchecker_base_isdefined , buf , count , datatype );
53+ memchecker_comm (comm );
54+ );
5555
5656 if ( MPI_PARAM_CHECK ) {
5757 rc = MPI_SUCCESS ;
@@ -76,68 +76,67 @@ int MPI_Sendrecv_replace(void * buf, int count, MPI_Datatype datatype,
7676
7777 /* simple case */
7878 if ( source == MPI_PROC_NULL || dest == MPI_PROC_NULL || count == 0 ) {
79- rc = PMPI_Sendrecv (buf ,count ,datatype ,dest ,sendtag ,buf ,count ,datatype ,source ,recvtag ,comm ,status );
79+ rc = PMPI_Sendrecv (buf , count , datatype , dest , sendtag , buf , count , datatype , source , recvtag , comm , status );
8080
8181 OPAL_CR_EXIT_LIBRARY ();
8282 return rc ;
83- } else {
84-
85- opal_convertor_t convertor ;
86- struct iovec iov ;
87- unsigned char recv_data [2048 ];
88- size_t packed_size , max_data ;
89- uint32_t iov_count ;
90- ompi_status_public_t recv_status ;
91- ompi_proc_t * proc = ompi_comm_peer_lookup (comm ,source );
92- if (proc == NULL ) {
93- rc = MPI_ERR_RANK ;
94- OMPI_ERRHANDLER_RETURN (rc , comm , rc , FUNC_NAME );
95- }
96-
97- /* initialize convertor to unpack recv buffer */
98- OBJ_CONSTRUCT (& convertor , opal_convertor_t );
99- opal_convertor_copy_and_prepare_for_recv ( proc -> super .proc_convertor , & (datatype -> super ),
100- count , buf , 0 , & convertor );
101-
102- /* setup a buffer for recv */
103- opal_convertor_get_packed_size ( & convertor , & packed_size );
104- if ( packed_size > sizeof (recv_data ) ) {
105- rc = PMPI_Alloc_mem (packed_size , MPI_INFO_NULL , & iov .iov_base );
106- if (OMPI_SUCCESS != rc ) {
107- OMPI_ERRHANDLER_RETURN (OMPI_ERR_OUT_OF_RESOURCE , comm , MPI_ERR_BUFFER , FUNC_NAME );
108- }
109- } else {
110- iov .iov_base = (caddr_t )recv_data ;
111- }
112-
113- /* recv into temporary buffer */
114- rc = PMPI_Sendrecv ( buf , count , datatype , dest , sendtag , iov .iov_base , packed_size ,
115- MPI_BYTE , source , recvtag , comm , & recv_status );
116- if (rc != MPI_SUCCESS ) {
117- if (packed_size > sizeof (recv_data ))
118- PMPI_Free_mem (iov .iov_base );
119- OBJ_DESTRUCT (& convertor );
120- OMPI_ERRHANDLER_RETURN (rc , comm , rc , FUNC_NAME );
121- }
122-
123- /* unpack into users buffer */
124- iov .iov_len = recv_status ._ucount ;
125- iov_count = 1 ;
126- max_data = recv_status ._ucount ;
127- opal_convertor_unpack (& convertor , & iov , & iov_count , & max_data );
83+ }
12884
129- /* return status to user */
130- if (status != MPI_STATUS_IGNORE ) {
131- * status = recv_status ;
132- }
85+ /**
86+ * If we look for an optimal solution, then we should receive the data into a temporary buffer
87+ * and once the send completes we would unpack back into the original buffer. However, if the
88+ * sender is unknown, this approach can only be implementing by receiving with the recv datatype
89+ * (potentially non-contiguous) and thus the allocated memory will be larger than the size of the
90+ * datatype. A simpler, but potentially less efficient approach is to work on the data we have
91+ * control of, aka the sent data, and pack it into a contiguous buffer before posting the receive.
92+ * Once the send completes, we free it.
93+ */
94+ opal_convertor_t convertor ;
95+ unsigned char packed_data [2048 ];
96+ struct iovec iov = { .iov_base = packed_data , .iov_len = sizeof (packed_data ) };
97+ size_t packed_size , max_data ;
98+ uint32_t iov_count ;
99+ ompi_status_public_t recv_status ;
100+ ompi_proc_t * proc = ompi_comm_peer_lookup (comm , dest );
101+ if (proc == NULL ) {
102+ rc = MPI_ERR_RANK ;
103+ OMPI_ERRHANDLER_RETURN (rc , comm , rc , FUNC_NAME );
104+ }
133105
134- /* release resources */
135- if (packed_size > sizeof (recv_data )) {
136- PMPI_Free_mem (iov .iov_base );
106+ /* initialize convertor to unpack recv buffer */
107+ OBJ_CONSTRUCT (& convertor , opal_convertor_t );
108+ opal_convertor_copy_and_prepare_for_send ( proc -> super .proc_convertor , & (datatype -> super ),
109+ count , buf , 0 , & convertor );
110+
111+ /* setup a buffer for recv */
112+ opal_convertor_get_packed_size ( & convertor , & packed_size );
113+ if ( packed_size > sizeof (packed_data ) ) {
114+ rc = PMPI_Alloc_mem (packed_size , MPI_INFO_NULL , & iov .iov_base );
115+ if (OMPI_SUCCESS != rc ) {
116+ rc = OMPI_ERR_OUT_OF_RESOURCE ;
117+ goto cleanup_and_return ;
137118 }
138- OBJ_DESTRUCT (& convertor );
119+ }
120+ max_data = packed_size ;
121+ iov_count = 1 ;
122+ rc = opal_convertor_pack (& convertor , & iov , & iov_count , & max_data );
123+
124+ /* recv into temporary buffer */
125+ rc = PMPI_Sendrecv ( iov .iov_base , packed_size , MPI_PACKED , dest , sendtag , buf , count ,
126+ datatype , source , recvtag , comm , & recv_status );
127+
128+ cleanup_and_return :
129+ /* return status to user */
130+ if (status != MPI_STATUS_IGNORE ) {
131+ * status = recv_status ;
132+ }
139133
140- OPAL_CR_EXIT_LIBRARY ();
141- return MPI_SUCCESS ;
134+ /* release resources */
135+ if (packed_size > sizeof (packed_data )) {
136+ PMPI_Free_mem (iov .iov_base );
142137 }
138+ OBJ_DESTRUCT (& convertor );
139+
140+ OPAL_CR_EXIT_LIBRARY ();
141+ OMPI_ERRHANDLER_RETURN (rc , comm , rc , FUNC_NAME );
143142}
0 commit comments