@@ -42,75 +42,102 @@ mca_coll_basic_gatherv_intra(const void *sbuf, int scount,
4242 void * rbuf , const int * rcounts , const int * disps ,
4343 struct ompi_datatype_t * rdtype , int root ,
4444 struct ompi_communicator_t * comm ,
45- mca_coll_base_module_t * module )
45+ mca_coll_base_module_t * module )
4646{
47- int i , rank , size , err ;
47+ int err , i , peer , rank , size ;
4848 char * ptmp ;
4949 ptrdiff_t lb , extent ;
5050 size_t rdsize ;
5151
5252 size = ompi_comm_size (comm );
5353 rank = ompi_comm_rank (comm );
5454
55- /* Everyone but root sends data and returns. Don't send anything
56- for sendcounts of 0 (even though MPI_Gatherv has a guard for 0
57- counts, this routine is used elsewhere, like the implementation
58- of allgatherv, so it's possible to get here with a scount of
59- 0) */
55+ if (root == rank ) {
56+ /* Root receives from everyone else */
57+ ompi_datatype_type_size (rdtype , & rdsize );
58+ if (OPAL_UNLIKELY (0 == rdsize )) {
59+ /* bozzo case */
60+ return MPI_SUCCESS ;
61+ }
6062
61- if (rank != root ) {
62- size_t sdsize ;
63- ompi_datatype_type_size (sdtype , & sdsize );
64- if (scount > 0 && sdsize > 0 ) {
65- return MCA_PML_CALL (send (sbuf , scount , sdtype , root ,
66- MCA_COLL_BASE_TAG_GATHERV ,
67- MCA_PML_BASE_SEND_STANDARD , comm ));
63+ err = ompi_datatype_get_extent (rdtype , & lb , & extent );
64+ if (OMPI_SUCCESS != err ) {
65+ return OMPI_ERROR ;
6866 }
69- return MPI_SUCCESS ;
70- }
7167
72- /* I am the root, loop receiving data. */
68+ if (MPI_IN_PLACE != sbuf && (0 < scount ) && (0 < rcounts [rank ])) {
69+ /* Directly copy self sbuf to rbuf */
70+ err = ompi_datatype_sndrcv (sbuf , scount , sdtype ,
71+ ((char * ) rbuf ) + (extent * disps [rank ]), rcounts [rank ],
72+ rdtype );
73+ if (MPI_SUCCESS != err ) {
74+ return err ;
75+ }
76+ }
7377
74- ompi_datatype_type_size (rdtype , & rdsize );
75- if (OPAL_UNLIKELY (0 == rdsize )) {
76- /* bozzo case */
77- return MPI_SUCCESS ;
78- }
78+ ompi_request_t * * reqs ;
79+ size_t nrecv = 0 , recv_iter = 0 ;
7980
80- err = ompi_datatype_get_extent (rdtype , & lb , & extent );
81- if (OMPI_SUCCESS != err ) {
82- return OMPI_ERROR ;
83- }
81+ for (i = 0 ; i < size ; ++ i ) {
82+ /* We directly copied the data from self */
83+ if (0 < rcounts [i ] && rank != i ) {
84+ ++ nrecv ;
85+ }
86+ }
8487
85- for (i = 0 ; i < size ; ++ i ) {
86- ptmp = ((char * ) rbuf ) + (extent * disps [i ]);
88+ if (0 == nrecv ) {
89+ /* Nothing to receive */
90+ return MPI_SUCCESS ;
91+ }
8792
88- if (i == rank ) {
89- /* simple optimization */
90- if (MPI_IN_PLACE != sbuf && (0 < scount ) && (0 < rcounts [i ])) {
91- err = ompi_datatype_sndrcv (sbuf , scount , sdtype ,
92- ptmp , rcounts [i ], rdtype );
93- }
94- } else {
93+ reqs = ompi_coll_base_comm_get_reqs (module -> base_data , nrecv );
94+
95+ for (i = 1 ; i < size ; ++ i ) {
96+ peer = (rank + i ) % size ;
97+ ptmp = ((char * ) rbuf ) + (extent * disps [peer ]);
9598 /* Only receive if there is something to receive */
96- if (rcounts [i ] > 0 ) {
97- err = MCA_PML_CALL (recv (ptmp , rcounts [i ], rdtype , i ,
98- MCA_COLL_BASE_TAG_GATHERV ,
99- comm , MPI_STATUS_IGNORE ));
99+ if (0 < rcounts [peer ]) {
100+ err = MCA_PML_CALL (irecv (ptmp , rcounts [peer ], rdtype , peer ,
101+ MCA_COLL_BASE_TAG_GATHERV , comm , & reqs [recv_iter ++ ]));
100102 }
101103 }
102104
103- if (MPI_SUCCESS != err ) {
104- return err ;
105+ assert (nrecv == recv_iter );
106+
107+ err = ompi_request_wait_all (nrecv , reqs , MPI_STATUSES_IGNORE );
108+
109+ if (MPI_ERR_IN_STATUS == err ) {
110+ for (int i = 0 ; i < nrecv ; i ++ ) {
111+ if (MPI_REQUEST_NULL == reqs [i ])
112+ continue ;
113+ if (MPI_ERR_PENDING == reqs [i ]-> req_status .MPI_ERROR )
114+ continue ;
115+ if (MPI_SUCCESS != reqs [i ]-> req_status .MPI_ERROR ) {
116+ err = reqs [i ]-> req_status .MPI_ERROR ;
117+ break ;
118+ }
119+ }
105120 }
121+
122+ ompi_coll_base_free_reqs (reqs , nrecv );
123+ return err ;
106124 }
107125
108- /* All done */
126+ /* Everyone but root sends data and returns. Don't send anything
127+ for sendcounts of 0 (even though MPI_Gatherv has a guard for 0
128+ counts, this routine is used elsewhere, like the implementation
129+ of allgatherv, so it's possible to get here with a scount of
130+ 0) */
109131
132+ size_t sdsize ;
133+ ompi_datatype_type_size (sdtype , & sdsize );
134+ if (scount > 0 && sdsize > 0 ) {
135+ return MCA_PML_CALL (send (sbuf , scount , sdtype , root , MCA_COLL_BASE_TAG_GATHERV ,
136+ MCA_PML_BASE_SEND_STANDARD , comm ));
137+ }
110138 return MPI_SUCCESS ;
111139}
112140
113-
114141/*
115142 * gatherv_inter
116143 *
0 commit comments