Logo AND Algorithmique Numérique Distribuée

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