Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
ok, I stop trying to please sonar.
[simgrid.git] / src / smpi / colls / reduce / reduce-binomial.cpp
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 #include "../colls_private.h"
8
9 //#include <star-reduction.c>
10 namespace simgrid{
11 namespace smpi{
12 int Coll_reduce_binomial::reduce(void *sendbuf, void *recvbuf, int count,
13                                     MPI_Datatype datatype, MPI_Op op, int root,
14                                     MPI_Comm comm)
15 {
16   MPI_Status status;
17   int comm_size, rank;
18   int mask, relrank, source;
19   int dst;
20   int tag = COLL_TAG_REDUCE;
21   MPI_Aint extent;
22   void *tmp_buf;
23   MPI_Aint true_lb, true_extent;
24   if (count == 0)
25     return 0;
26   rank = comm->rank();
27   comm_size = comm->size();
28
29   extent = datatype->get_extent();
30
31   tmp_buf = (void *) smpi_get_tmp_sendbuffer(count * extent);
32   int is_commutative =  (op==MPI_OP_NULL || op->is_commutative());
33   mask = 1;
34   
35   int lroot;
36   if (is_commutative) 
37         lroot   = root;
38   else
39         lroot   = 0;
40   relrank = (rank - lroot + comm_size) % comm_size;
41
42   datatype->extent(&true_lb, &true_extent);
43
44   /* adjust for potential negative lower bound in datatype */
45   tmp_buf = (void *)((char*)tmp_buf - true_lb);
46     
47   /* If I'm not the root, then my recvbuf may not be valid, therefore
48      I have to allocate a temporary one */
49   if (rank != root) {
50       recvbuf = (void *) smpi_get_tmp_recvbuffer(count*(MAX(extent,true_extent)));
51       recvbuf = (void *)((char*)recvbuf - true_lb);
52   }
53    if ((rank != root) || (sendbuf != MPI_IN_PLACE)) {
54       Datatype::copy(sendbuf, count, datatype, recvbuf,count, datatype);
55   }
56
57   while (mask < comm_size) {
58     /* Receive */
59     if ((mask & relrank) == 0) {
60       source = (relrank | mask);
61       if (source < comm_size) {
62         source = (source + lroot) % comm_size;
63         Request::recv(tmp_buf, count, datatype, source, tag, comm, &status);
64         
65         if (is_commutative) {
66           if(op!=MPI_OP_NULL) op->apply( tmp_buf, recvbuf, &count, datatype);
67         } else {
68           if(op!=MPI_OP_NULL) op->apply( recvbuf, tmp_buf, &count, datatype);
69           Datatype::copy(tmp_buf, count, datatype,recvbuf, count, datatype);
70         }
71       }
72     } else {
73       dst = ((relrank & (~mask)) + lroot) % comm_size;
74       Request::send(recvbuf, count, datatype, dst, tag, comm);
75       break;
76     }
77     mask <<= 1;
78   }
79
80   if (!is_commutative && (root != 0)){
81     if (rank == 0){
82       Request::send(recvbuf, count, datatype, root,tag, comm);
83     }else if (rank == root){
84       Request::recv(recvbuf, count, datatype, 0, tag, comm, &status);
85     }
86   }
87
88   if (rank != root) {
89           smpi_free_tmp_buffer(recvbuf);
90   }
91   smpi_free_tmp_buffer(tmp_buf);
92
93   return 0;
94 }
95 }
96 }