1 /*
2 * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
3 * University Research and Technology
4 * Corporation. All rights reserved.
5 * Copyright (c) 2004-2016 The University of Tennessee and The University
6 * of Tennessee Research Foundation. All rights
7 * reserved.
8 * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
9 * University of Stuttgart. All rights reserved.
10 * Copyright (c) 2004-2005 The Regents of the University of California.
11 * All rights reserved.
12 * Copyright (c) 2015 Research Organization for Information Science
13 * and Technology (RIST). All rights reserved.
14 * Copyright (c) 2017 IBM Corporation. All rights reserved.
15 * $COPYRIGHT$
16 *
17 * Additional copyrights may follow
18 *
19 * $HEADER$
20 */
21
22 #include "ompi_config.h"
23 #include "coll_basic.h"
24
25 #include "mpi.h"
26 #include "ompi/constants.h"
27 #include "ompi/datatype/ompi_datatype.h"
28 #include "ompi/mca/coll/coll.h"
29 #include "ompi/mca/coll/base/coll_tags.h"
30 #include "ompi/mca/pml/pml.h"
31 #include "coll_basic.h"
32
33
34 /*
35 * scatterv_intra
36 *
37 * Function: - scatterv operation
38 * Accepts: - same arguments as MPI_Scatterv()
39 * Returns: - MPI_SUCCESS or error code
40 */
41 int
42 mca_coll_basic_scatterv_intra(const void *sbuf, const int *scounts,
43 const int *disps, struct ompi_datatype_t *sdtype,
44 void *rbuf, int rcount,
45 struct ompi_datatype_t *rdtype, int root,
46 struct ompi_communicator_t *comm,
47 mca_coll_base_module_t *module)
48 {
49 int i, rank, size, err;
50 char *ptmp;
51 ptrdiff_t lb, extent;
52
53 /* Initialize */
54
55 rank = ompi_comm_rank(comm);
56 size = ompi_comm_size(comm);
57
58 /* If not root, receive data. */
59
60 if (rank != root) {
61 /* Only receive if there is something to receive */
62 if (rcount > 0) {
63 return MCA_PML_CALL(recv(rbuf, rcount, rdtype,
64 root, MCA_COLL_BASE_TAG_SCATTERV,
65 comm, MPI_STATUS_IGNORE));
66 }
67 return MPI_SUCCESS;
68 }
69
70 /* I am the root, loop sending data. */
71
72 err = ompi_datatype_get_extent(sdtype, &lb, &extent);
73 if (OMPI_SUCCESS != err) {
74 return OMPI_ERROR;
75 }
76
77 for (i = 0; i < size; ++i) {
78 ptmp = ((char *) sbuf) + (extent * disps[i]);
79
80 /* simple optimization */
81
82 if (i == rank) {
83 /* simple optimization or a local operation */
84 if (scounts[i] > 0 && MPI_IN_PLACE != rbuf) {
85 err = ompi_datatype_sndrcv(ptmp, scounts[i], sdtype, rbuf, rcount,
86 rdtype);
87 }
88 } else {
89 /* Only send if there is something to send */
90 if (scounts[i] > 0) {
91 err = MCA_PML_CALL(send(ptmp, scounts[i], sdtype, i,
92 MCA_COLL_BASE_TAG_SCATTERV,
93 MCA_PML_BASE_SEND_STANDARD, comm));
94 if (MPI_SUCCESS != err) {
95 return err;
96 }
97 }
98 }
99 }
100
101 /* All done */
102
103 return MPI_SUCCESS;
104 }
105
106
107 /*
108 * scatterv_inter
109 *
110 * Function: - scatterv operation
111 * Accepts: - same arguments as MPI_Scatterv()
112 * Returns: - MPI_SUCCESS or error code
113 */
114 int
115 mca_coll_basic_scatterv_inter(const void *sbuf, const int *scounts,
116 const int *disps, struct ompi_datatype_t *sdtype,
117 void *rbuf, int rcount,
118 struct ompi_datatype_t *rdtype, int root,
119 struct ompi_communicator_t *comm,
120 mca_coll_base_module_t *module)
121 {
122 int i, size, err;
123 char *ptmp;
124 ptrdiff_t lb, extent;
125 ompi_request_t **reqs;
126
127 /* Initialize */
128 size = ompi_comm_remote_size(comm);
129
130 /* If not root, receive data. Note that we will only get here if
131 * rcount > 0 or rank == root. */
132
133 if (MPI_PROC_NULL == root) {
134 /* do nothing */
135 err = OMPI_SUCCESS;
136 } else if (MPI_ROOT != root) {
137 /* If not root, receive data. */
138 err = MCA_PML_CALL(recv(rbuf, rcount, rdtype,
139 root, MCA_COLL_BASE_TAG_SCATTERV,
140 comm, MPI_STATUS_IGNORE));
141 } else {
142 /* I am the root, loop sending data. */
143 err = ompi_datatype_get_extent(sdtype, &lb, &extent);
144 if (OMPI_SUCCESS != err) {
145 return OMPI_ERROR;
146 }
147
148 reqs = ompi_coll_base_comm_get_reqs(module->base_data, size);
149 if( NULL == reqs ) { return OMPI_ERR_OUT_OF_RESOURCE; }
150
151 for (i = 0; i < size; ++i) {
152 ptmp = ((char *) sbuf) + (extent * disps[i]);
153 err = MCA_PML_CALL(isend(ptmp, scounts[i], sdtype, i,
154 MCA_COLL_BASE_TAG_SCATTERV,
155 MCA_PML_BASE_SEND_STANDARD, comm,
156 &(reqs[i])));
157 if (OMPI_SUCCESS != err) {
158 ompi_coll_base_free_reqs(reqs, i + 1);
159 return err;
160 }
161 }
162
163 err = ompi_request_wait_all(size, reqs, MPI_STATUSES_IGNORE);
164 if (OMPI_SUCCESS != err) {
165 ompi_coll_base_free_reqs(reqs, size);
166 }
167 }
168
169 /* All done */
170 return err;
171 }