Logo AND Algorithmique Numérique Distribuée

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