2
2
* Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana
3
3
* University Research and Technology
4
4
* 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
6
6
* of Tennessee Research Foundation. All rights
7
7
* reserved.
8
8
* Copyright (c) 2004-2008 High Performance Computing Center Stuttgart,
12
12
* Copyright (c) 2010-2012 Oracle and/or its affiliates. All rights reserved.
13
13
* Copyright (c) 2015 Research Organization for Information Science
14
14
* and Technology (RIST). All rights reserved.
15
+ * Copyright (c) 2017 IBM Corporation. All rights reserved.
15
16
* $COPYRIGHT$
16
17
*
17
18
* Additional copyrights may follow
@@ -48,10 +49,10 @@ int MPI_Sendrecv_replace(void * buf, int count, MPI_Datatype datatype,
48
49
int rc = MPI_SUCCESS ;
49
50
50
51
MEMCHECKER (
51
- memchecker_datatype (datatype );
52
- memchecker_call (& opal_memchecker_base_isdefined , buf , count , datatype );
53
- memchecker_comm (comm );
54
- );
52
+ memchecker_datatype (datatype );
53
+ memchecker_call (& opal_memchecker_base_isdefined , buf , count , datatype );
54
+ memchecker_comm (comm );
55
+ );
55
56
56
57
if ( MPI_PARAM_CHECK ) {
57
58
rc = MPI_SUCCESS ;
@@ -74,66 +75,66 @@ int MPI_Sendrecv_replace(void * buf, int count, MPI_Datatype datatype,
74
75
75
76
/* simple case */
76
77
if ( source == MPI_PROC_NULL || dest == MPI_PROC_NULL || count == 0 ) {
77
- rc = PMPI_Sendrecv (buf ,count ,datatype ,dest ,sendtag ,buf ,count ,datatype ,source ,recvtag ,comm ,status );
78
+ rc = PMPI_Sendrecv (buf , count , datatype , dest , sendtag , buf , count , datatype , source , recvtag , comm , status );
78
79
79
80
return rc ;
80
- } else {
81
-
82
- opal_convertor_t convertor ;
83
- struct iovec iov ;
84
- unsigned char recv_data [2048 ];
85
- size_t packed_size , max_data ;
86
- uint32_t iov_count ;
87
- ompi_status_public_t recv_status ;
88
- ompi_proc_t * proc = ompi_comm_peer_lookup (comm ,source );
89
- if (proc == NULL ) {
90
- rc = MPI_ERR_RANK ;
91
- OMPI_ERRHANDLER_RETURN (rc , comm , rc , FUNC_NAME );
92
- }
93
-
94
- /* initialize convertor to unpack recv buffer */
95
- OBJ_CONSTRUCT (& convertor , opal_convertor_t );
96
- opal_convertor_copy_and_prepare_for_recv ( proc -> super .proc_convertor , & (datatype -> super ),
97
- count , buf , 0 , & convertor );
98
-
99
- /* setup a buffer for recv */
100
- opal_convertor_get_packed_size ( & convertor , & packed_size );
101
- if ( packed_size > sizeof (recv_data ) ) {
102
- rc = PMPI_Alloc_mem (packed_size , MPI_INFO_NULL , & iov .iov_base );
103
- if (OMPI_SUCCESS != rc ) {
104
- OMPI_ERRHANDLER_RETURN (OMPI_ERR_OUT_OF_RESOURCE , comm , MPI_ERR_BUFFER , FUNC_NAME );
105
- }
106
- } else {
107
- iov .iov_base = (caddr_t )recv_data ;
108
- }
109
-
110
- /* recv into temporary buffer */
111
- rc = PMPI_Sendrecv ( buf , count , datatype , dest , sendtag , iov .iov_base , packed_size ,
112
- MPI_BYTE , source , recvtag , comm , & recv_status );
113
- if (rc != MPI_SUCCESS ) {
114
- if (packed_size > sizeof (recv_data ))
115
- PMPI_Free_mem (iov .iov_base );
116
- OBJ_DESTRUCT (& convertor );
117
- OMPI_ERRHANDLER_RETURN (rc , comm , rc , FUNC_NAME );
118
- }
119
-
120
- /* unpack into users buffer */
121
- iov .iov_len = recv_status ._ucount ;
122
- iov_count = 1 ;
123
- max_data = recv_status ._ucount ;
124
- opal_convertor_unpack (& convertor , & iov , & iov_count , & max_data );
81
+ }
125
82
126
- /* return status to user */
127
- if (status != MPI_STATUS_IGNORE ) {
128
- * status = recv_status ;
129
- }
83
+ /**
84
+ * If we look for an optimal solution, then we should receive the data into a temporary buffer
85
+ * and once the send completes we would unpack back into the original buffer. However, if the
86
+ * sender is unknown, this approach can only be implementing by receiving with the recv datatype
87
+ * (potentially non-contiguous) and thus the allocated memory will be larger than the size of the
88
+ * datatype. A simpler, but potentially less efficient approach is to work on the data we have
89
+ * control of, aka the sent data, and pack it into a contiguous buffer before posting the receive.
90
+ * Once the send completes, we free it.
91
+ */
92
+ opal_convertor_t convertor ;
93
+ unsigned char packed_data [2048 ];
94
+ struct iovec iov = { .iov_base = packed_data , .iov_len = sizeof (packed_data ) };
95
+ size_t packed_size , max_data ;
96
+ uint32_t iov_count ;
97
+ ompi_status_public_t recv_status ;
98
+ ompi_proc_t * proc = ompi_comm_peer_lookup (comm , dest );
99
+ if (proc == NULL ) {
100
+ rc = MPI_ERR_RANK ;
101
+ OMPI_ERRHANDLER_RETURN (rc , comm , rc , FUNC_NAME );
102
+ }
130
103
131
- /* release resources */
132
- if (packed_size > sizeof (recv_data )) {
133
- PMPI_Free_mem (iov .iov_base );
104
+ /* initialize convertor to unpack recv buffer */
105
+ OBJ_CONSTRUCT (& convertor , opal_convertor_t );
106
+ opal_convertor_copy_and_prepare_for_send ( proc -> super .proc_convertor , & (datatype -> super ),
107
+ count , buf , 0 , & convertor );
108
+
109
+ /* setup a buffer for recv */
110
+ opal_convertor_get_packed_size ( & convertor , & packed_size );
111
+ if ( packed_size > sizeof (packed_data ) ) {
112
+ rc = PMPI_Alloc_mem (packed_size , MPI_INFO_NULL , & iov .iov_base );
113
+ if (OMPI_SUCCESS != rc ) {
114
+ rc = OMPI_ERR_OUT_OF_RESOURCE ;
115
+ goto cleanup_and_return ;
134
116
}
135
- OBJ_DESTRUCT (& convertor );
117
+ iov .iov_len = packed_size ;
118
+ }
119
+ max_data = packed_size ;
120
+ iov_count = 1 ;
121
+ rc = opal_convertor_pack (& convertor , & iov , & iov_count , & max_data );
122
+
123
+ /* recv into temporary buffer */
124
+ rc = PMPI_Sendrecv ( iov .iov_base , packed_size , MPI_PACKED , dest , sendtag , buf , count ,
125
+ datatype , source , recvtag , comm , & recv_status );
126
+
127
+ cleanup_and_return :
128
+ /* return status to user */
129
+ if (status != MPI_STATUS_IGNORE ) {
130
+ * status = recv_status ;
131
+ }
136
132
137
- return MPI_SUCCESS ;
133
+ /* release resources */
134
+ if (packed_size > sizeof (packed_data )) {
135
+ PMPI_Free_mem (iov .iov_base );
138
136
}
137
+ OBJ_DESTRUCT (& convertor );
138
+
139
+ OMPI_ERRHANDLER_RETURN (rc , comm , rc , FUNC_NAME );
139
140
}
0 commit comments