Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Add new entry in Release_Notes.
[simgrid.git] / src / smpi / colls / alltoallv / alltoallv-ompi-basic-linear.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  * Linear functions are copied from the basic coll module.  For
10  * some small number of nodes and/or small data sizes they are just as
11  * fast as tuned/tree based segmenting operations and as such may be
12  * selected by the decision functions.  These are copied into this module
13  * due to the way we select modules in V1. i.e. in V2 we will handle this
14  * differently and so will not have to duplicate code.
15  * GEF Oct05 after asking Jeff.
16  */
17 namespace simgrid::smpi {
18 int alltoallv__ompi_basic_linear(const void *sbuf, const int *scounts, const int *sdisps,
19                                  MPI_Datatype sdtype,
20                                  void *rbuf, const int *rcounts, const int *rdisps,
21                                  MPI_Datatype rdtype,
22                                  MPI_Comm comm)
23 {
24   int size = comm->size();
25   int rank = comm->rank();
26   XBT_DEBUG("coll:tuned:alltoallv_intra_basic_linear rank %d", rank);
27
28   ptrdiff_t sext = sdtype->get_extent();
29   ptrdiff_t rext = rdtype->get_extent();
30
31   /* Simple optimization - handle send to self first */
32   char* psnd = ((char*)sbuf) + (sdisps[rank] * sext);
33   char* prcv = ((char*)rbuf) + (rdisps[rank] * rext);
34   if (0 != scounts[rank]) {
35     Datatype::copy(psnd, scounts[rank], sdtype, prcv, rcounts[rank], rdtype);
36   }
37
38   /* If only one process, we're done. */
39   if (1 == size) {
40     return MPI_SUCCESS;
41   }
42
43   /* Now, initiate all send/recv to/from others. */
44   auto* ireqs        = new MPI_Request[size * 2];
45   int nreqs          = 0;
46   MPI_Request* preq  = ireqs;
47
48   /* Post all receives first */
49   for (int i = 0; i < size; ++i) {
50     if (i == rank) {
51       continue;
52     }
53
54     prcv = ((char*)rbuf) + (rdisps[i] * rext);
55
56     *preq = Request::irecv_init(prcv, rcounts[i], rdtype, i, COLL_TAG_ALLTOALLV, comm);
57     preq++;
58     ++nreqs;
59   }
60
61   /* Now post all sends */
62   for (int i = 0; i < size; ++i) {
63     if (i == rank) {
64       continue;
65     }
66
67     psnd  = ((char*)sbuf) + (sdisps[i] * sext);
68     *preq = Request::isend_init(psnd, scounts[i], sdtype, i, COLL_TAG_ALLTOALLV, comm);
69     preq++;
70     ++nreqs;
71   }
72
73   /* Start your engines.  This will never return an error. */
74   Request::startall(nreqs, ireqs);
75
76   /* Wait for them all.  If there's an error, note that we don't care
77    * what the error was -- just that there *was* an error.  The PML
78    * will finish all requests, even if one or more of them fail.
79    * i.e., by the end of this call, all the requests are free-able.
80    * So free them anyway -- even if there was an error, and return the
81    * error after we free everything. */
82   Request::waitall(nreqs, ireqs, MPI_STATUSES_IGNORE);
83
84   /* Free the requests. */
85   for (int i = 0; i < nreqs; ++i) {
86     if (ireqs[i] != MPI_REQUEST_NULL)
87       Request::unref(&ireqs[i]);
88   }
89   delete[] ireqs;
90
91   return MPI_SUCCESS;
92 }
93 } // namespace simgrid::smpi