Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Update copyright lines for 2022.
[simgrid.git] / src / smpi / colls / alltoallv / alltoallv-bruck.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 #include "../colls_private.hpp"
8
9 /**
10  * Alltoall Bruck
11  *
12  * Openmpi calls this routine when the message size sent to each rank < 2000 bytes and size < 12
13  * FIXME: uh, check smpi_pmpi again, but this routine is called for > 12, not
14  * less...
15  **/
16 namespace simgrid{
17 namespace smpi{
18 int alltoallv__bruck(const void *sendbuf, const int *sendcounts, const int *senddisps,
19                      MPI_Datatype sendtype, void *recvbuf,
20                      const int *recvcounts,const int *recvdisps, MPI_Datatype recvtype,
21                      MPI_Comm comm)
22 {
23   int system_tag = COLL_TAG_ALLTOALLV;
24   int i, rank, size, err, count;
25   MPI_Aint lb;
26   MPI_Aint sendext = 0;
27   MPI_Aint recvext = 0;
28
29   // FIXME: check implementation
30   rank = comm->rank();
31   size = comm->size();
32   XBT_DEBUG("<%d> algorithm alltoall_bruck() called.", rank);
33
34   sendtype->extent(&lb, &sendext);
35   recvtype->extent(&lb, &recvext);
36   /* Local copy from self */
37   err =
38       Datatype::copy((char *)sendbuf + senddisps[rank] * sendext,
39                          sendcounts[rank], sendtype,
40                          (char *)recvbuf + recvdisps[rank] * recvext,
41                          recvcounts[rank], recvtype);
42   if (err == MPI_SUCCESS && size > 1) {
43     /* Initiate all send/recv to/from others. */
44
45     int bblock = 4; // MPIR_PARAM_ALLTOALL_THROTTLE
46     // if (bblock == 0) bblock = comm_size;
47
48     // MPI_Request* requests = new MPI_Request[2 * (bblock - 1)];
49     int ii, ss, dst;
50     /* post only bblock isends/irecvs at a time as suggested by Tony Ladd */
51     for (ii = 0; ii < size; ii += bblock) {
52       auto* requests = new MPI_Request[2 * bblock];
53
54       ss    = size - ii < bblock ? size - ii : bblock;
55       count = 0;
56
57       /* do the communication -- post ss sends and receives: */
58       for (i = 0; i < ss; i++) {
59         dst = (rank + i + ii) % size;
60         if (dst == rank) {
61           XBT_DEBUG("<%d> skip request creation [src = %d, recvcount = %d]", rank, i, recvcounts[dst]);
62           continue;
63         }
64
65         requests[count] =
66             Request::irecv((char*)recvbuf + recvdisps[dst] * recvext, recvcounts[dst], recvtype, dst, system_tag, comm);
67         count++;
68       }
69       /* Now create all sends  */
70       for (i = 0; i < ss; i++) {
71         dst = (rank - i - ii + size) % size;
72         if (dst == rank) {
73           XBT_DEBUG("<%d> skip request creation [dst = %d, sendcount = %d]", rank, i, sendcounts[dst]);
74           continue;
75         }
76         requests[count] =
77             Request::isend((char*)sendbuf + senddisps[dst] * sendext, sendcounts[dst], sendtype, dst, system_tag, comm);
78         count++;
79       }
80       /* Wait for them all. */
81       // colls::startall(count, requests);
82       XBT_DEBUG("<%d> wait for %d requests", rank, count);
83       Request::waitall(count, requests, MPI_STATUSES_IGNORE);
84       delete[] requests;
85     }
86   }
87   return MPI_SUCCESS;
88 }
89 }
90 }