Logo AND Algorithmique Numérique Distribuée

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