Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Update copyright lines with new year.
[simgrid.git] / src / smpi / colls / scatter / scatter-ompi.cpp
1 /* Copyright (c) 2013-2020. The SimGrid Team.
2  * All rights reserved.                                                     */
3
4 /* This program is free software; you can redistribute it and/or modify it
5  * under the terms of the license (GNU LGPL) which comes with this package. */
6
7 /*
8  * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
9  *                         University Research and Technology
10  *                         Corporation.  All rights reserved.
11  * Copyright (c) 2004-2006 The University of Tennessee and The University
12  *                         of Tennessee Research Foundation.  All rights
13  *                         reserved.
14  * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
15  *                         University of Stuttgart.  All rights reserved.
16  * Copyright (c) 2004-2005 The Regents of the University of California.
17  *                         All rights reserved.
18  *
19  * Additional copyrights may follow
20  */
21
22 #include "../coll_tuned_topo.hpp"
23 #include "../colls_private.hpp"
24
25 namespace simgrid{
26 namespace smpi{
27
28 int scatter__ompi_binomial(const void* sbuf, int scount, MPI_Datatype sdtype, void* rbuf, int rcount,
29                            MPI_Datatype rdtype, int root, MPI_Comm comm)
30 {
31     int line = -1;
32     int i;
33     int rank;
34     int vrank;
35     int size;
36     int total_send = 0;
37     unsigned char* ptmp    = nullptr;
38     unsigned char* tempbuf = nullptr;
39     const unsigned char* cptmp; // const ptmp
40     int err;
41     ompi_coll_tree_t* bmtree;
42     MPI_Status status;
43     MPI_Aint sextent, slb, strue_lb, strue_extent;
44     MPI_Aint rextent, rlb, rtrue_lb, rtrue_extent;
45
46     size = comm->size();
47     rank = comm->rank();
48
49     XBT_DEBUG(
50                  "Coll_scatter_ompi_binomial::scatter rank %d", rank);
51
52     /* create the binomial tree */
53
54 //    COLL_TUNED_UPDATE_IN_ORDER_BMTREE( comm, tuned_module, root );
55     bmtree =  ompi_coll_tuned_topo_build_in_order_bmtree( comm, root);//ompi_ data->cached_in_order_bmtree;
56
57     sdtype->extent(&slb, &sextent);
58     sdtype->extent(&strue_lb, &strue_extent);
59     rdtype->extent(&rlb, &rextent);
60     rdtype->extent(&rtrue_lb, &rtrue_extent);
61
62     vrank = (rank - root + size) % size;
63
64     if (rank == root) {
65       if (0 == root) {
66         /* root on 0, just use the send buffer */
67         ptmp  = nullptr; // unused
68         cptmp = static_cast<const unsigned char*>(sbuf);
69         if (rbuf != MPI_IN_PLACE) {
70           /* local copy to rbuf */
71           err = Datatype::copy(sbuf, scount, sdtype, rbuf, rcount, rdtype);
72           if (MPI_SUCCESS != err) {
73             line = __LINE__;
74             goto err_hndl;
75           }
76         }
77       } else {
78         /* root is not on 0, allocate temp buffer for send */
79         tempbuf = smpi_get_tmp_sendbuffer(strue_extent + (scount * size - 1) * sextent);
80         if (nullptr == tempbuf) {
81           err  = MPI_ERR_OTHER;
82           line = __LINE__;
83           goto err_hndl;
84         }
85
86         ptmp  = tempbuf - slb;
87         cptmp = ptmp;
88
89         /* and rotate data so they will eventually in the right place */
90         err = Datatype::copy((char*)sbuf + sextent * root * scount, scount * (size - root), sdtype, ptmp,
91                              scount * (size - root), sdtype);
92         if (MPI_SUCCESS != err) {
93           line = __LINE__;
94           goto err_hndl;
95         }
96
97         err = Datatype::copy((char*)sbuf, scount * root, sdtype, ptmp + sextent * scount * (size - root), scount * root,
98                              sdtype);
99         if (MPI_SUCCESS != err) {
100           line = __LINE__;
101           goto err_hndl;
102         }
103
104         if (rbuf != MPI_IN_PLACE) {
105           /* local copy to rbuf */
106           err = Datatype::copy(ptmp, scount, sdtype, rbuf, rcount, rdtype);
107           if (MPI_SUCCESS != err) {
108             line = __LINE__;
109             goto err_hndl;
110           }
111         }
112       }
113       total_send = scount;
114     } else if (not(vrank % 2)) {
115       /* non-root, non-leaf nodes, allocate temp buffer for recv
116        * the most we need is rcount*size/2 */
117       tempbuf = smpi_get_tmp_recvbuffer(rtrue_extent + (rcount * size - 1) * rextent);
118       if (nullptr == tempbuf) {
119         err  = MPI_ERR_OTHER;
120         line = __LINE__;
121         goto err_hndl;
122       }
123
124       ptmp  = tempbuf - rlb;
125       cptmp = ptmp;
126
127       sdtype     = rdtype;
128       scount     = rcount;
129       sextent    = rextent;
130       total_send = scount;
131     } else {
132       /* leaf nodes, just use rbuf */
133       ptmp  = static_cast<unsigned char*>(rbuf);
134       cptmp = ptmp;
135     }
136
137     if (not(vrank % 2)) {
138       if (rank != root) {
139         /* recv from parent on non-root */
140         Request::recv(ptmp, rcount * size, rdtype, bmtree->tree_prev, COLL_TAG_SCATTER, comm, &status);
141         /* local copy to rbuf */
142         Datatype::copy(ptmp, scount, sdtype, rbuf, rcount, rdtype);
143       }
144       /* send to children on all non-leaf */
145       for (i = 0; i < bmtree->tree_nextsize; i++) {
146         int mycount = 0, vkid;
147         /* figure out how much data I have to send to this child */
148         vkid    = (bmtree->tree_next[i] - root + size) % size;
149         mycount = vkid - vrank;
150         if (mycount > (size - vkid))
151           mycount = size - vkid;
152         mycount *= scount;
153
154         Request::send(cptmp + total_send * sextent, mycount, sdtype, bmtree->tree_next[i], COLL_TAG_SCATTER, comm);
155
156         total_send += mycount;
157       }
158
159     } else {
160       /* recv from parent on leaf nodes */
161       Request::recv(ptmp, rcount, rdtype, bmtree->tree_prev, COLL_TAG_SCATTER, comm, &status);
162     }
163
164     smpi_free_tmp_buffer(tempbuf);
165     // not FIXME : store the tree, as done in ompi, instead of calculating it each time ?
166     ompi_coll_tuned_topo_destroy_tree(&bmtree);
167
168     return MPI_SUCCESS;
169
170  err_hndl:
171     smpi_free_tmp_buffer(tempbuf);
172
173     XBT_DEBUG("%s:%4d\tError occurred %d, rank %2d", __FILE__, line, err, rank);
174     return err;
175 }
176
177 /*
178  * Linear functions are copied from the BASIC coll module
179  * they do not segment the message and are simple implementations
180  * but for some small number of nodes and/or small data sizes they
181  * are just as fast as tuned/tree based segmenting operations
182  * and as such may be selected by the decision functions
183  * These are copied into this module due to the way we select modules
184  * in V1. i.e. in V2 we will handle this differently and so will not
185  * have to duplicate code.
186  * JPG following the examples from other coll_tuned implementations. Dec06.
187  */
188
189 /* copied function (with appropriate renaming) starts here */
190 /*
191  *  scatter_intra
192  *
193  *  Function:  - basic scatter operation
194  *  Accepts:  - same arguments as MPI_Scatter()
195  *  Returns:  - MPI_SUCCESS or error code
196  */
197 int scatter__ompi_basic_linear(const void* sbuf, int scount, MPI_Datatype sdtype, void* rbuf, int rcount,
198                                MPI_Datatype rdtype, int root, MPI_Comm comm)
199 {
200     int i, rank, size, err;
201     char *ptmp;
202     ptrdiff_t lb, incr;
203
204     /* Initialize */
205
206     rank = comm->rank();
207     size = comm->size();
208
209     /* If not root, receive data. */
210
211     if (rank != root) {
212         Request::recv(rbuf, rcount, rdtype, root,
213                                 COLL_TAG_SCATTER,
214                                 comm, MPI_STATUS_IGNORE);
215         return MPI_SUCCESS;
216     }
217
218     /* I am the root, loop sending data. */
219
220     err = sdtype->extent(&lb, &incr);
221     if (MPI_SUCCESS != err) {
222         return MPI_ERR_OTHER;
223     }
224
225     incr *= scount;
226     for (i = 0, ptmp = (char *) sbuf; i < size; ++i, ptmp += incr) {
227
228         /* simple optimization */
229
230         if (i == rank) {
231             if (MPI_IN_PLACE != rbuf) {
232                 err =
233                     Datatype::copy(ptmp, scount, sdtype, rbuf, rcount,
234                                     rdtype);
235             }
236         } else {
237             Request::send(ptmp, scount, sdtype, i,
238                                     COLL_TAG_SCATTER,
239                                      comm);
240         }
241         if (MPI_SUCCESS != err) {
242             return err;
243         }
244     }
245
246     /* All done */
247
248     return MPI_SUCCESS;
249 }
250
251 }
252 }