Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
avoid warning by checking index in the right order
[simgrid.git] / src / smpi / colls / reduce-mvapich-knomial.c
1 /* Copyright (c) 2013-2014. 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 //        int mv2_reduce_knomial_factor = 2;
44         
45         
46         
47 static int MPIR_Reduce_knomial_trace(int root, int reduce_knomial_factor,  
48         MPI_Comm comm, int *dst, int *expected_send_count,
49         int *expected_recv_count, int **src_array)
50 {
51     int mask=0x1, k, comm_size, src, rank, relative_rank, lroot=0;
52     int orig_mask=0x1; 
53     int recv_iter=0, send_iter=0;
54     int *knomial_reduce_src_array=NULL;
55     comm_size =  smpi_comm_size(comm);
56     rank = smpi_comm_rank(comm);
57
58     lroot = root;
59     relative_rank = (rank - lroot + comm_size) % comm_size;
60
61     /* First compute to whom we need to send data */ 
62     while (mask < comm_size) {
63         if (relative_rank % (reduce_knomial_factor*mask)) {
64             *dst = relative_rank/(reduce_knomial_factor*mask)*
65                 (reduce_knomial_factor*mask)+root;
66             if (*dst >= comm_size) {
67                 *dst -= comm_size;
68             }
69             send_iter++;
70             break;
71         }
72         mask *= reduce_knomial_factor;
73     }
74     mask /= reduce_knomial_factor;
75
76     /* Now compute how many children we have in the knomial-tree */ 
77     orig_mask = mask; 
78     while (mask > 0) {
79         for(k=1;k<reduce_knomial_factor;k++) {
80             if (relative_rank + mask*k < comm_size) {
81                 recv_iter++;
82             }
83         }
84         mask /= reduce_knomial_factor;
85     }
86
87     /* Finally, fill up the src array */ 
88     if(recv_iter > 0) { 
89         knomial_reduce_src_array = xbt_malloc(sizeof(int)*recv_iter); 
90     } 
91
92     mask = orig_mask; 
93     recv_iter=0; 
94     while (mask > 0) {
95         for(k=1;k<reduce_knomial_factor;k++) {
96             if (relative_rank + mask*k < comm_size) {
97                 src = rank + mask*k;
98                 if (src >= comm_size) {
99                     src -= comm_size;
100                 }
101                 knomial_reduce_src_array[recv_iter++] = src;
102             }
103         }
104         mask /= reduce_knomial_factor;
105     }
106
107     *expected_recv_count = recv_iter;
108     *expected_send_count = send_iter;
109     *src_array = knomial_reduce_src_array; 
110     return 0; 
111 }
112         
113 int smpi_coll_tuned_reduce_mvapich2_knomial (
114         void *sendbuf,
115         void *recvbuf,
116         int count,
117         MPI_Datatype datatype,
118         MPI_Op op,
119         int root,
120         MPI_Comm comm)
121 {
122     int mpi_errno = MPI_SUCCESS;
123     int rank, is_commutative;
124     int src, k;
125     MPI_Request send_request;
126     int index=0;
127     MPI_Aint true_lb, true_extent, extent;
128     MPI_Status status; 
129     int recv_iter=0, dst=-1, expected_send_count, expected_recv_count;
130     int *src_array=NULL;
131     void **tmp_buf=NULL;
132     MPI_Request *requests=NULL;
133
134
135     if (count == 0) return MPI_SUCCESS;
136
137     rank = smpi_comm_rank(comm);
138
139     /* Create a temporary buffer */
140
141     smpi_datatype_extent(datatype, &true_lb, &true_extent);
142     extent = smpi_datatype_get_extent(datatype);
143
144     is_commutative = smpi_op_is_commute(op);
145
146     if (rank != root) {
147         recvbuf=(void *)xbt_malloc(count*(MAX(extent,true_extent)));
148         recvbuf = (void *)((char*)recvbuf - true_lb);
149     }
150
151     if ((rank != root) || (sendbuf != MPI_IN_PLACE)) {
152         mpi_errno = smpi_datatype_copy(sendbuf, count, datatype, recvbuf,
153                 count, datatype);
154     }
155
156
157
158     MPIR_Reduce_knomial_trace(root, mv2_reduce_intra_knomial_factor, comm, 
159            &dst, &expected_send_count, &expected_recv_count, &src_array);
160
161     if(expected_recv_count > 0 ) {
162         tmp_buf  = xbt_malloc(sizeof(void *)*expected_recv_count);
163         requests = xbt_malloc(sizeof(MPI_Request)*expected_recv_count);
164         for(k=0; k < expected_recv_count; k++ ) {
165             tmp_buf[k] = xbt_malloc(count*(MAX(extent,true_extent)));
166             tmp_buf[k] = (void *)((char*)tmp_buf[k] - true_lb);
167         }
168
169         while(recv_iter  < expected_recv_count) {
170             src = src_array[expected_recv_count - (recv_iter+1)];
171
172             requests[recv_iter]=smpi_mpi_irecv (tmp_buf[recv_iter], count, datatype ,src,
173                     COLL_TAG_REDUCE, comm);
174             recv_iter++;
175
176         }
177
178         recv_iter=0;
179         while(recv_iter < expected_recv_count) {
180             index=smpi_mpi_waitany(expected_recv_count, requests,
181                     &status);
182             recv_iter++;
183
184             if (is_commutative) {
185               smpi_op_apply(op, tmp_buf[index], recvbuf, &count, &datatype);
186             }
187         }
188
189         for(k=0; k < expected_recv_count; k++ ) {
190             xbt_free(tmp_buf[k]);
191         }
192         xbt_free(tmp_buf);
193         xbt_free(requests);
194     }
195
196     if(src_array != NULL) { 
197         xbt_free(src_array);
198     } 
199
200     if(rank != root) {
201         send_request=smpi_mpi_isend(recvbuf,count, datatype, dst,
202                 COLL_TAG_REDUCE,comm);
203
204         smpi_mpi_waitall(1, &send_request, &status);
205     }
206
207     /* --END ERROR HANDLING-- */
208
209     return mpi_errno;
210 }