Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Merge branch 'master' of https://framagit.org/simgrid/simgrid
[simgrid.git] / src / smpi / colls / alltoallv / alltoallv-ompi-basic-linear.cpp
1 /* Copyright (c) 2013-2019. 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{
18 namespace smpi{
19 int alltoallv__ompi_basic_linear(const void *sbuf, const int *scounts, const int *sdisps,
20                                  MPI_Datatype sdtype,
21                                  void *rbuf, const int *rcounts, const int *rdisps,
22                                  MPI_Datatype rdtype,
23                                  MPI_Comm comm)
24 {
25   int size = comm->size();
26   int rank = comm->rank();
27   XBT_DEBUG("coll:tuned:alltoallv_intra_basic_linear rank %d", rank);
28
29   ptrdiff_t sext = sdtype->get_extent();
30   ptrdiff_t rext = rdtype->get_extent();
31
32   /* Simple optimization - handle send to self first */
33   char* psnd = ((char*)sbuf) + (sdisps[rank] * sext);
34   char* prcv = ((char*)rbuf) + (rdisps[rank] * rext);
35   if (0 != scounts[rank]) {
36     Datatype::copy(psnd, scounts[rank], sdtype, prcv, rcounts[rank], rdtype);
37   }
38
39   /* If only one process, we're done. */
40   if (1 == size) {
41     return MPI_SUCCESS;
42   }
43
44   /* Now, initiate all send/recv to/from others. */
45   MPI_Request* ireqs = new MPI_Request[size * 2];
46   int nreqs          = 0;
47   MPI_Request* preq  = ireqs;
48
49   /* Post all receives first */
50   for (int i = 0; i < size; ++i) {
51     if (i == rank) {
52       continue;
53     }
54
55     prcv = ((char*)rbuf) + (rdisps[i] * rext);
56
57     *preq = Request::irecv_init(prcv, rcounts[i], rdtype, i, COLL_TAG_ALLTOALLV, comm);
58     preq++;
59     ++nreqs;
60   }
61
62   /* Now post all sends */
63   for (int i = 0; i < size; ++i) {
64     if (i == rank) {
65       continue;
66     }
67
68     psnd  = ((char*)sbuf) + (sdisps[i] * sext);
69     *preq = Request::isend_init(psnd, scounts[i], sdtype, i, COLL_TAG_ALLTOALLV, comm);
70     preq++;
71     ++nreqs;
72   }
73
74   /* Start your engines.  This will never return an error. */
75   Request::startall(nreqs, ireqs);
76
77   /* Wait for them all.  If there's an error, note that we don't care
78    * what the error was -- just that there *was* an error.  The PML
79    * will finish all requests, even if one or more of them fail.
80    * i.e., by the end of this call, all the requests are free-able.
81    * So free them anyway -- even if there was an error, and return the
82    * error after we free everything. */
83   Request::waitall(nreqs, ireqs, MPI_STATUSES_IGNORE);
84
85   /* Free the requests. */
86   for (int i = 0; i < nreqs; ++i) {
87     if (ireqs[i] != MPI_REQUEST_NULL)
88       Request::unref(&ireqs[i]);
89   }
90   delete[] ireqs;
91
92   return MPI_SUCCESS;
93 }
94 }
95 }