Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Concatenate nested namespaces (sonar).
[simgrid.git] / src / smpi / colls / allgatherv / allgatherv-mpich-ring.cpp
1 /* Copyright (c) 2013-2022. 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  *
9  *  (C) 2001 by Argonne National Laboratory.
10  *      See COPYRIGHT in top-level directory.
11  */
12
13 #include "../colls_private.hpp"
14
15 /*****************************************************************************
16  * Function: allgather_mpich_ring
17  * return: int
18  * inputs:
19  *   send_buff: send input buffer
20  *   send_count: number of elements to send
21  *   send_type: data type of elements being sent
22  *   recv_buff: receive output buffer
23  *   recv_count: number of elements to received
24  *   recv_type: data type of elements being received
25  *   comm: communication
26  ****************************************************************************/
27
28 namespace simgrid::smpi {
29
30 int allgatherv__mpich_ring(const void *sendbuf, int sendcount,
31                            MPI_Datatype send_type, void *recvbuf,
32                            const int *recvcounts, const int *displs, MPI_Datatype recvtype,
33                            MPI_Comm comm)
34 {
35
36   char *sbuf = nullptr, *rbuf = nullptr;
37   int soffset, roffset;
38   int torecv=0, tosend=0, min, rank, comm_size;
39   int sendnow, recvnow;
40   int sidx, ridx;
41   MPI_Status status;
42   MPI_Aint recvtype_extent;
43   int right, left, total_count, i;
44   rank= comm->rank();
45   comm_size=comm->size();
46
47   recvtype_extent= recvtype->get_extent();
48   total_count = 0;
49   for (i=0; i<comm_size; i++)
50     total_count += recvcounts[i];
51
52   if (sendbuf != MPI_IN_PLACE) {
53       /* First, load the "local" version in the recvbuf. */
54       Datatype::copy(sendbuf, sendcount, send_type,
55           ((char *)recvbuf + displs[rank]*recvtype_extent),
56           recvcounts[rank], recvtype);
57   }
58
59   left  = (comm_size + rank - 1) % comm_size;
60   right = (rank + 1) % comm_size;
61
62   torecv = total_count - recvcounts[rank];
63   tosend = total_count - recvcounts[right];
64
65   min = recvcounts[0];
66   for (i = 1; i < comm_size; i++)
67     if (min > recvcounts[i])
68       min = recvcounts[i];
69   if (min * recvtype_extent < 32768*8)
70     min = 32768*8 / recvtype_extent;
71   /* Handle the case where the datatype extent is larger than
72    * the pipeline size. */
73   if (not min)
74     min = 1;
75
76   sidx = rank;
77   ridx = left;
78   soffset = 0;
79   roffset = 0;
80   while (tosend || torecv) { /* While we have data to send or receive */
81       sendnow = ((recvcounts[sidx] - soffset) > min) ? min : (recvcounts[sidx] - soffset);
82       recvnow = ((recvcounts[ridx] - roffset) > min) ? min : (recvcounts[ridx] - roffset);
83       sbuf = (char *)recvbuf + ((displs[sidx] + soffset) * recvtype_extent);
84       rbuf = (char *)recvbuf + ((displs[ridx] + roffset) * recvtype_extent);
85
86       /* Protect against wrap-around of indices */
87       if (not tosend)
88         sendnow = 0;
89       if (not torecv)
90         recvnow = 0;
91
92       /* Communicate */
93       if (not sendnow && not recvnow) {
94         /* Don't do anything. This case is possible if two
95          * consecutive processes contribute 0 bytes each. */
96       } else if (not sendnow) { /* If there's no data to send, just do a recv call */
97         Request::recv(rbuf, recvnow, recvtype, left, COLL_TAG_ALLGATHERV, comm, &status);
98
99         torecv -= recvnow;
100       } else if (not recvnow) { /* If there's no data to receive, just do a send call */
101         Request::send(sbuf, sendnow, recvtype, right, COLL_TAG_ALLGATHERV, comm);
102
103         tosend -= sendnow;
104       }
105       else { /* There's data to be sent and received */
106           Request::sendrecv(sbuf, sendnow, recvtype, right, COLL_TAG_ALLGATHERV,
107               rbuf, recvnow, recvtype, left, COLL_TAG_ALLGATHERV,
108               comm, &status);
109           tosend -= sendnow;
110           torecv -= recvnow;
111       }
112
113       soffset += sendnow;
114       roffset += recvnow;
115       if (soffset == recvcounts[sidx]) {
116           soffset = 0;
117           sidx = (sidx + comm_size - 1) % comm_size;
118       }
119       if (roffset == recvcounts[ridx]) {
120           roffset = 0;
121           ridx = (ridx + comm_size - 1) % comm_size;
122       }
123   }
124
125   return MPI_SUCCESS;
126 }
127
128 } // namespace simgrid::smpi