Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Add new entry in Release_Notes.
[simgrid.git] / src / smpi / colls / reduce / reduce-binomial.cpp
1 /* Copyright (c) 2013-2023. 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::smpi {
12 int reduce__binomial(const 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   MPI_Aint true_lb, true_extent;
23   if (count == 0)
24     return 0;
25   rank = comm->rank();
26   comm_size = comm->size();
27
28   extent = datatype->get_extent();
29
30   unsigned char* tmp_buf = smpi_get_tmp_sendbuffer(count * extent);
31   bool is_commutative    = (op == MPI_OP_NULL || op->is_commutative());
32   mask = 1;
33
34   int lroot;
35   if (is_commutative)
36         lroot   = root;
37   else
38         lroot   = 0;
39   relrank = (rank - lroot + comm_size) % comm_size;
40
41   datatype->extent(&true_lb, &true_extent);
42
43   /* adjust for potential negative lower bound in datatype */
44   tmp_buf = tmp_buf - true_lb;
45
46   /* If I'm not the root, then my recvbuf may not be valid, therefore
47      I have to allocate a temporary one */
48   if (rank != root) {
49       recvbuf = (void*)smpi_get_tmp_recvbuffer(count * std::max(extent, true_extent));
50       recvbuf = (void *)((char*)recvbuf - true_lb);
51   }
52    if ((rank != root) || (sendbuf != MPI_IN_PLACE)) {
53       Datatype::copy(sendbuf, count, datatype, recvbuf,count, datatype);
54   }
55
56   while (mask < comm_size) {
57     /* Receive */
58     if ((mask & relrank) == 0) {
59       source = (relrank | mask);
60       if (source < comm_size) {
61         source = (source + lroot) % comm_size;
62         Request::recv(tmp_buf, count, datatype, source, tag, comm, &status);
63
64         if (is_commutative) {
65           if(op!=MPI_OP_NULL) op->apply( tmp_buf, recvbuf, &count, datatype);
66         } else {
67           if(op!=MPI_OP_NULL) op->apply( recvbuf, tmp_buf, &count, datatype);
68           Datatype::copy(tmp_buf, count, datatype,recvbuf, count, datatype);
69         }
70       }
71     } else {
72       dst = ((relrank & (~mask)) + lroot) % comm_size;
73       Request::send(recvbuf, count, datatype, dst, tag, comm);
74       break;
75     }
76     mask <<= 1;
77   }
78
79   if (not is_commutative && (root != 0)) {
80     if (rank == 0){
81       Request::send(recvbuf, count, datatype, root,tag, comm);
82     }else if (rank == root){
83       Request::recv(recvbuf, count, datatype, 0, tag, comm, &status);
84     }
85   }
86
87   if (rank != root) {
88     smpi_free_tmp_buffer(static_cast<unsigned char*>(recvbuf));
89   }
90   smpi_free_tmp_buffer(tmp_buf);
91
92   return 0;
93 }
94 } // namespace simgrid::smpi