Logo AND Algorithmique Numérique Distribuée

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