Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Merge branch 'toufic' of github.com:Takishipp/simgrid
[simgrid.git] / src / smpi / colls / reduce / reduce-mvapich-knomial.cpp
1 /* Copyright (c) 2013-2017. 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-2012 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  * Copyright (c) 2008      Sun Microsystems, Inc.  All rights reserved.
19  * Copyright (c) 2009      University of Houston. All rights reserved.
20  *
21  * Additional copyrights may follow
22  */
23
24 /*
25  *
26  *  (C) 2001 by Argonne National Laboratory.
27  *      See COPYRIGHT in top-level directory.
28  */
29 /* Copyright (c) 2001-2014, The Ohio State University. All rights
30  * reserved.
31  *
32  * This file is part of the MVAPICH2 software package developed by the
33  * team members of The Ohio State University's Network-Based Computing
34  * Laboratory (NBCL), headed by Professor Dhabaleswar K. (DK) Panda.
35  *
36  * For detailed copyright and licensing information, please refer to the
37  * copyright file COPYRIGHT in the top level MVAPICH2 directory.
38  *
39  */
40  
41 #include "../colls_private.h"
42 extern int mv2_reduce_intra_knomial_factor;
43 extern int mv2_reduce_inter_knomial_factor;
44
45 #define SMPI_DEFAULT_KNOMIAL_FACTOR 4
46
47 //        int mv2_reduce_knomial_factor = 2;
48         
49         
50         
51 static int MPIR_Reduce_knomial_trace(int root, int reduce_knomial_factor,  
52         MPI_Comm comm, int *dst, int *expected_send_count,
53         int *expected_recv_count, int **src_array)
54 {
55     int mask=0x1, k, comm_size, src, rank, relative_rank, lroot=0;
56     int orig_mask=0x1; 
57     int recv_iter=0, send_iter=0;
58     int *knomial_reduce_src_array=NULL;
59     comm_size =  comm->size();
60     rank = comm->rank();
61
62     lroot = root;
63     relative_rank = (rank - lroot + comm_size) % comm_size;
64
65     /* First compute to whom we need to send data */ 
66     while (mask < comm_size) {
67         if (relative_rank % (reduce_knomial_factor*mask)) {
68             *dst = relative_rank/(reduce_knomial_factor*mask)*
69                 (reduce_knomial_factor*mask)+root;
70             if (*dst >= comm_size) {
71                 *dst -= comm_size;
72             }
73             send_iter++;
74             break;
75         }
76         mask *= reduce_knomial_factor;
77     }
78     mask /= reduce_knomial_factor;
79
80     /* Now compute how many children we have in the knomial-tree */ 
81     orig_mask = mask; 
82     while (mask > 0) {
83         for(k=1;k<reduce_knomial_factor;k++) {
84             if (relative_rank + mask*k < comm_size) {
85                 recv_iter++;
86             }
87         }
88         mask /= reduce_knomial_factor;
89     }
90
91     /* Finally, fill up the src array */ 
92     if(recv_iter > 0) { 
93         knomial_reduce_src_array = static_cast<int*>(smpi_get_tmp_sendbuffer(sizeof(int)*recv_iter));
94     } 
95
96     mask = orig_mask; 
97     recv_iter=0; 
98     while (mask > 0) {
99         for(k=1;k<reduce_knomial_factor;k++) {
100             if (relative_rank + mask*k < comm_size) {
101                 src = rank + mask*k;
102                 if (src >= comm_size) {
103                     src -= comm_size;
104                 }
105                 knomial_reduce_src_array[recv_iter++] = src;
106             }
107         }
108         mask /= reduce_knomial_factor;
109     }
110
111     *expected_recv_count = recv_iter;
112     *expected_send_count = send_iter;
113     *src_array = knomial_reduce_src_array; 
114     return 0; 
115 }
116         
117 namespace simgrid{
118 namespace smpi{
119 int Coll_reduce_mvapich2_knomial::reduce (
120         void *sendbuf,
121         void *recvbuf,
122         int count,
123         MPI_Datatype datatype,
124         MPI_Op op,
125         int root,
126         MPI_Comm comm)
127 {
128     int mpi_errno = MPI_SUCCESS;
129     int rank, is_commutative;
130     int src, k;
131     MPI_Request send_request;
132     int index=0;
133     MPI_Aint true_lb, true_extent, extent;
134     MPI_Status status; 
135     int recv_iter=0, dst=-1, expected_send_count, expected_recv_count;
136     int *src_array=NULL;
137     void **tmp_buf=NULL;
138     MPI_Request *requests=NULL;
139
140
141     if (count == 0) return MPI_SUCCESS;
142
143     rank = comm->rank();
144
145     /* Create a temporary buffer */
146
147     datatype->extent(&true_lb, &true_extent);
148     extent = datatype->get_extent();
149
150     is_commutative =  (op==MPI_OP_NULL || op->is_commutative());
151
152     if (rank != root) {
153         recvbuf=(void *)smpi_get_tmp_recvbuffer(count*(MAX(extent,true_extent)));
154         recvbuf = (void *)((char*)recvbuf - true_lb);
155     }
156
157     if ((rank != root) || (sendbuf != MPI_IN_PLACE)) {
158         mpi_errno = Datatype::copy(sendbuf, count, datatype, recvbuf,
159                 count, datatype);
160     }
161
162
163     if(mv2_reduce_intra_knomial_factor<0)
164       {
165         mv2_reduce_intra_knomial_factor = SMPI_DEFAULT_KNOMIAL_FACTOR;
166       }
167     if(mv2_reduce_inter_knomial_factor<0)
168       {
169         mv2_reduce_inter_knomial_factor = SMPI_DEFAULT_KNOMIAL_FACTOR;
170       }
171
172
173     MPIR_Reduce_knomial_trace(root, mv2_reduce_intra_knomial_factor, comm, 
174            &dst, &expected_send_count, &expected_recv_count, &src_array);
175
176     if(expected_recv_count > 0 ) {
177         tmp_buf  = static_cast<void**>(xbt_malloc(sizeof(void *)*expected_recv_count));
178         requests = static_cast<MPI_Request*>(xbt_malloc(sizeof(MPI_Request)*expected_recv_count));
179         for(k=0; k < expected_recv_count; k++ ) {
180             tmp_buf[k] = smpi_get_tmp_sendbuffer(count*(MAX(extent,true_extent)));
181             tmp_buf[k] = (void *)((char*)tmp_buf[k] - true_lb);
182         }
183
184         while(recv_iter  < expected_recv_count) {
185             src = src_array[expected_recv_count - (recv_iter+1)];
186
187             requests[recv_iter]=Request::irecv (tmp_buf[recv_iter], count, datatype ,src,
188                     COLL_TAG_REDUCE, comm);
189             recv_iter++;
190
191         }
192
193         recv_iter=0;
194         while(recv_iter < expected_recv_count) {
195             index=Request::waitany(expected_recv_count, requests,
196                     &status);
197             recv_iter++;
198
199             if (is_commutative) {
200               if(op!=MPI_OP_NULL) op->apply( tmp_buf[index], recvbuf, &count, datatype);
201             }
202         }
203
204         for(k=0; k < expected_recv_count; k++ ) {
205             smpi_free_tmp_buffer(tmp_buf[k]);
206         }
207         xbt_free(tmp_buf);
208         xbt_free(requests);
209     }
210
211     if(src_array != NULL) { 
212         xbt_free(src_array);
213     } 
214
215     if(rank != root) {
216         send_request=Request::isend(recvbuf,count, datatype, dst,
217                 COLL_TAG_REDUCE,comm);
218
219         Request::waitall(1, &send_request, &status);
220
221         smpi_free_tmp_buffer((void *)((char*)recvbuf + true_lb));
222     }
223
224     /* --END ERROR HANDLING-- */
225
226     return mpi_errno;
227 }
228 }
229 }