Logo AND Algorithmique Numérique Distribuée

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