Logo AND Algorithmique Numérique Distribuée

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