Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Merge branch 'master' into actor-yield
[simgrid.git] / src / smpi / colls / alltoallv / alltoallv-bruck.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.hpp"
8
9 /**
10  * Alltoall Bruck
11  *
12  * Openmpi calls this routine when the message size sent to each rank < 2000 bytes and size < 12
13  * FIXME: uh, check smpi_pmpi again, but this routine is called for > 12, not
14  * less...
15  **/
16 namespace simgrid{
17 namespace smpi{
18 int Coll_alltoallv_bruck::alltoallv(void *sendbuf, int *sendcounts, int *senddisps,
19                                    MPI_Datatype sendtype, void *recvbuf,
20                                    int *recvcounts, int *recvdisps, MPI_Datatype recvtype,
21                                    MPI_Comm comm)
22 {
23   int system_tag = COLL_TAG_ALLTOALLV;
24   int i, rank, size, err, count;
25   MPI_Aint lb;
26   MPI_Aint sendext = 0;
27   MPI_Aint recvext = 0;
28   MPI_Request *requests;
29
30   // FIXME: check implementation
31   rank = comm->rank();
32   size = comm->size();
33   XBT_DEBUG("<%d> algorithm alltoall_bruck() called.", rank);
34
35   sendtype->extent(&lb, &sendext);
36   recvtype->extent(&lb, &recvext);
37   /* Local copy from self */
38   err =
39       Datatype::copy((char *)sendbuf + senddisps[rank] * sendext,
40                          sendcounts[rank], sendtype,
41                          (char *)recvbuf + recvdisps[rank] * recvext,
42                          recvcounts[rank], recvtype);
43   if (err == MPI_SUCCESS && size > 1) {
44     /* Initiate all send/recv to/from others. */
45
46       int bblock = 4;//MPIR_PARAM_ALLTOALL_THROTTLE
47       //if (bblock == 0) bblock = comm_size;
48
49
50      // requests = xbt_new(MPI_Request, 2 * (bblock - 1));
51       int ii, ss, dst;
52       /* post only bblock isends/irecvs at a time as suggested by Tony Ladd */
53       for (ii=0; ii<size; ii+=bblock) {
54           requests = xbt_new(MPI_Request, 2 * (bblock ));
55
56           ss = size-ii < bblock ? size-ii : bblock;
57           count = 0;
58
59           /* do the communication -- post ss sends and receives: */
60           for ( i=0; i<ss; i++ ) {
61             dst = (rank+i+ii) % size;
62               if (dst == rank) {
63                 XBT_DEBUG("<%d> skip request creation [src = %d, recvcount = %d]",
64                        rank, i, recvcounts[dst]);
65                 continue;
66               }
67
68               requests[count]=Request::irecv((char *)recvbuf + recvdisps[dst] * recvext, recvcounts[dst],
69                                   recvtype, dst, system_tag, comm );
70               count++;
71             }
72             /* Now create all sends  */
73           for ( i=0; i<ss; i++ ) {
74               dst = (rank-i-ii+size) % size;
75               if (dst == rank) {
76                 XBT_DEBUG("<%d> skip request creation [dst = %d, sendcount = %d]",
77                        rank, i, sendcounts[dst]);
78                 continue;
79               }
80               requests[count]=Request::isend((char *)sendbuf + senddisps[dst] * sendext, sendcounts[dst],
81                                   sendtype, dst, system_tag, comm);
82               count++;
83             }
84             /* Wait for them all. */
85             //Colls::startall(count, requests);
86             XBT_DEBUG("<%d> wait for %d requests", rank, count);
87             Request::waitall(count, requests, MPI_STATUSES_IGNORE);
88             xbt_free(requests);
89
90           }
91
92   }
93   return MPI_SUCCESS;
94 }
95 }
96 }