Logo AND Algorithmique Numérique Distribuée

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