Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Merge branch 'master' of git+ssh://scm.gforge.inria.fr//gitroot/simgrid/simgrid
[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
157     return MPI_SUCCESS;
158
159  err_hndl:
160     if (NULL != tempbuf)
161         free(tempbuf);
162
163     XBT_DEBUG(  "%s:%4d\tError occurred %d, rank %2d",
164                  __FILE__, line, err, rank);
165     return err;
166 }
167
168 /*
169  * Linear functions are copied from the BASIC coll module
170  * they do not segment the message and are simple implementations
171  * but for some small number of nodes and/or small data sizes they 
172  * are just as fast as tuned/tree based segmenting operations 
173  * and as such may be selected by the decision functions
174  * These are copied into this module due to the way we select modules
175  * in V1. i.e. in V2 we will handle this differently and so will not
176  * have to duplicate code.
177  * JPG following the examples from other coll_tuned implementations. Dec06.
178  */
179
180 /* copied function (with appropriate renaming) starts here */
181 /*
182  *      scatter_intra
183  *
184  *      Function:       - basic scatter operation
185  *      Accepts:        - same arguments as MPI_Scatter()
186  *      Returns:        - MPI_SUCCESS or error code
187  */
188 int
189 smpi_coll_tuned_scatter_ompi_basic_linear(void *sbuf, int scount,
190                                            MPI_Datatype sdtype,
191                                            void *rbuf, int rcount,
192                                            MPI_Datatype rdtype,
193                                            int root,
194                                            MPI_Comm comm
195                                            )
196 {
197     int i, rank, size, err;
198     char *ptmp;
199     ptrdiff_t lb, incr;
200
201     /* Initialize */
202
203     rank = smpi_comm_rank(comm);
204     size = smpi_comm_size(comm);
205
206     /* If not root, receive data. */
207
208     if (rank != root) {
209         smpi_mpi_recv(rbuf, rcount, rdtype, root,
210                                 MCA_COLL_BASE_TAG_SCATTER,
211                                 comm, MPI_STATUS_IGNORE);
212         return MPI_SUCCESS;
213     }
214
215     /* I am the root, loop sending data. */
216
217     err = smpi_datatype_extent(sdtype, &lb, &incr);
218     if (MPI_SUCCESS != err) {
219         return MPI_ERR_OTHER;
220     }
221
222     incr *= scount;
223     for (i = 0, ptmp = (char *) sbuf; i < size; ++i, ptmp += incr) {
224
225         /* simple optimization */
226
227         if (i == rank) {
228             if (MPI_IN_PLACE != rbuf) {
229                 err =
230                     smpi_datatype_copy(ptmp, scount, sdtype, rbuf, rcount,
231                                     rdtype);
232             }
233         } else {
234             smpi_mpi_send(ptmp, scount, sdtype, i,
235                                     MCA_COLL_BASE_TAG_SCATTER,
236                                      comm);
237         }
238         if (MPI_SUCCESS != err) {
239             return err;
240         }
241     }
242
243     /* All done */
244
245     return MPI_SUCCESS;
246 }