Logo AND Algorithmique Numérique Distribuée

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