Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
fc726453ed6b3d7d5dc3543d3fd84a97526d5b33
[simgrid.git] / src / smpi / colls / allgatherv-mpich-ring.c
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 /*
8  *
9  *  (C) 2001 by Argonne National Laboratory.
10  *      See COPYRIGHT in top-level directory.
11  */
12
13 #include "colls_private.h"
14
15 /*****************************************************************************
16  * Function: allgather_mpich_ring
17  * return: int
18  * inputs:
19  *   send_buff: send input buffer
20  *   send_count: number of elements to send
21  *   send_type: data type of elements being sent
22  *   recv_buff: receive output buffer
23  *   recv_count: number of elements to received
24  *   recv_type: data type of elements being received
25  *   comm: communication
26  ****************************************************************************/
27 int
28 smpi_coll_tuned_allgatherv_mpich_ring(void *sendbuf, int sendcount,
29     MPI_Datatype send_type, void *recvbuf,
30     int *recvcounts, int *displs, MPI_Datatype recvtype,
31     MPI_Comm comm)
32 {
33
34   char * sbuf = NULL, * rbuf = NULL;
35   int soffset, roffset;
36   int torecv=0, tosend=0, min, rank, comm_size;
37   int sendnow, recvnow;
38   int sidx, ridx;
39   MPI_Status status;
40   MPI_Aint recvtype_extent;
41   int right, left, total_count, i;
42   rank= smpi_comm_rank(comm);
43   comm_size=smpi_comm_size(comm);
44
45   recvtype_extent= smpi_datatype_get_extent( recvtype);
46   total_count = 0;
47   for (i=0; i<comm_size; i++)
48     total_count += recvcounts[i];
49
50   if (sendbuf != MPI_IN_PLACE) {
51       /* First, load the "local" version in the recvbuf. */
52       smpi_datatype_copy(sendbuf, sendcount, send_type,
53           ((char *)recvbuf + displs[rank]*recvtype_extent),
54           recvcounts[rank], recvtype);
55   }
56
57   left  = (comm_size + rank - 1) % comm_size;
58   right = (rank + 1) % comm_size;
59
60   torecv = total_count - recvcounts[rank];
61   tosend = total_count - recvcounts[right];
62
63   min = recvcounts[0];
64   for (i = 1; i < comm_size; i++)
65     if (min > recvcounts[i])
66       min = recvcounts[i];
67   if (min * recvtype_extent < 32768*8)
68     min = 32768*8 / recvtype_extent;
69   /* Handle the case where the datatype extent is larger than
70    * the pipeline size. */
71   if (!min)
72     min = 1;
73
74   sidx = rank;
75   ridx = left;
76   soffset = 0;
77   roffset = 0;
78   while (tosend || torecv) { /* While we have data to send or receive */
79       sendnow = ((recvcounts[sidx] - soffset) > min) ? min : (recvcounts[sidx] - soffset);
80       recvnow = ((recvcounts[ridx] - roffset) > min) ? min : (recvcounts[ridx] - roffset);
81       sbuf = (char *)recvbuf + ((displs[sidx] + soffset) * recvtype_extent);
82       rbuf = (char *)recvbuf + ((displs[ridx] + roffset) * recvtype_extent);
83
84       /* Protect against wrap-around of indices */
85       if (!tosend)
86         sendnow = 0;
87       if (!torecv)
88         recvnow = 0;
89
90       /* Communicate */
91       if (!sendnow && !recvnow) {
92           /* Don't do anything. This case is possible if two
93            * consecutive processes contribute 0 bytes each. */
94       }
95       else if (!sendnow) { /* If there's no data to send, just do a recv call */
96           smpi_mpi_recv(rbuf, recvnow, recvtype, left, COLL_TAG_ALLGATHERV, comm, &status);
97
98           torecv -= recvnow;
99       }
100       else if (!recvnow) { /* If there's no data to receive, just do a send call */
101           smpi_mpi_send(sbuf, sendnow, recvtype, right, COLL_TAG_ALLGATHERV, comm);
102
103           tosend -= sendnow;
104       }
105       else { /* There's data to be sent and received */
106           smpi_mpi_sendrecv(sbuf, sendnow, recvtype, right, COLL_TAG_ALLGATHERV,
107               rbuf, recvnow, recvtype, left, COLL_TAG_ALLGATHERV,
108               comm, &status);
109           tosend -= sendnow;
110           torecv -= recvnow;
111       }
112
113       soffset += sendnow;
114       roffset += recvnow;
115       if (soffset == recvcounts[sidx]) {
116           soffset = 0;
117           sidx = (sidx + comm_size - 1) % comm_size;
118       }
119       if (roffset == recvcounts[ridx]) {
120           roffset = 0;
121           ridx = (ridx + comm_size - 1) % comm_size;
122       }
123   }
124
125   return MPI_SUCCESS;
126 }