Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Add new entry in Release_Notes.
[simgrid.git] / src / smpi / colls / allreduce / allreduce-lr.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
9 /* IMPLEMENTED BY PITCH PATARASUK
10    Non-topology-specific all-reduce operation designed bandwidth optimally
11    Bug fixing by Xin Yuan, 04/04/2008
12 */
13
14 /* ** NOTE **
15    Use -DMPICH2_REDUCTION if this code does not compile.
16    MPICH1 code also work on MPICH2 on our cluster and the performance are similar.
17    This code assume commutative and associative reduce operator (MPI_SUM, MPI_MAX, etc).
18 */
19
20 //#include <star-reduction.c>
21 namespace simgrid::smpi {
22 int allreduce__lr(const void *sbuf, void *rbuf, int rcount,
23                   MPI_Datatype dtype, MPI_Op op, MPI_Comm comm)
24 {
25   int tag = COLL_TAG_ALLREDUCE;
26   MPI_Status status;
27   int rank, i, size, count;
28   int send_offset, recv_offset;
29   int remainder, remainder_flag, remainder_offset;
30
31   rank = comm->rank();
32   size = comm->size();
33
34   /* make it compatible with all data type */
35   MPI_Aint extent;
36   extent = dtype->get_extent();
37
38   if (rcount < size) {
39     XBT_INFO("MPI_allreduce_lr: communication size smaller than number of process, use default MPI_allreduce.");
40     allreduce__redbcast(sbuf, rbuf, rcount, dtype, op, comm);
41     return MPI_SUCCESS;
42   }
43
44   /* when communication size is not divisible by number of process:
45      call the native implementation for the remain chunk at the end of the operation */
46   if (rcount % size != 0) {
47     remainder = rcount % size;
48     remainder_flag = 1;
49     remainder_offset = (rcount / size) * size * extent;
50   } else {
51     remainder = remainder_flag = remainder_offset = 0;
52   }
53
54   /* size of each point-to-point communication is equal to the size of the whole message
55      divided by number of processes
56    */
57   count = rcount / size;
58
59   /* our ALL-REDUCE implementation
60      1. copy (partial of)send_buf to recv_buf
61      2. use logical ring reduce-scatter
62      3. use logical ring all-gather
63    */
64
65   // copy partial data
66   send_offset = ((rank - 1 + size) % size) * count * extent;
67   recv_offset = ((rank - 1 + size) % size) * count * extent;
68   Request::sendrecv((char *) sbuf + send_offset, count, dtype, rank, tag - 1,
69                (char *) rbuf + recv_offset, count, dtype, rank, tag - 1, comm,
70                &status);
71
72   // reduce-scatter
73   for (i = 0; i < (size - 1); i++) {
74     send_offset = ((rank - 1 - i + 2 * size) % size) * count * extent;
75     recv_offset = ((rank - 2 - i + 2 * size) % size) * count * extent;
76     //    recv_offset = ((rank-i+2*size)%size)*count*extent;
77     Request::sendrecv((char *) rbuf + send_offset, count, dtype, ((rank + 1) % size),
78                  tag + i, (char *) rbuf + recv_offset, count, dtype,
79                  ((rank + size - 1) % size), tag + i, comm, &status);
80
81     // compute result to rbuf+recv_offset
82     if(op!=MPI_OP_NULL) op->apply( (char *) sbuf + recv_offset, (char *) rbuf + recv_offset,
83                    &count, dtype);
84   }
85
86   // all-gather
87   for (i = 0; i < (size - 1); i++) {
88     send_offset = ((rank - i + 2 * size) % size) * count * extent;
89     recv_offset = ((rank - 1 - i + 2 * size) % size) * count * extent;
90     Request::sendrecv((char *) rbuf + send_offset, count, dtype, ((rank + 1) % size),
91                  tag + i, (char *) rbuf + recv_offset, count, dtype,
92                  ((rank + size - 1) % size), tag + i, comm, &status);
93   }
94
95   /* when communication size is not divisible by number of process:
96      call the native implementation for the remain chunk at the end of the operation */
97   if (remainder_flag) {
98     return colls::allreduce((char*)sbuf + remainder_offset, (char*)rbuf + remainder_offset, remainder, dtype, op, comm);
99   }
100
101   return 0;
102 }
103 } // namespace simgrid::smpi