1 #include "colls_private.h"
3 /* -*- Mode: C; c-basic-offset:4 ; -*- */
6 * (C) 2001 by Argonne National Laboratory.
7 * See COPYRIGHT in top-level directory.
10 /*****************************************************************************
11 * Function: allgather_mpich_ring
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
21 ****************************************************************************/
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,
29 char * sbuf = NULL, * rbuf = NULL;
31 int torecv=0, tosend=0, min, rank, comm_size;
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);
40 recvtype_extent= smpi_datatype_get_extent( recvtype);
42 for (i=0; i<comm_size; i++)
43 total_count += recvcounts[i];
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);
52 left = (comm_size + rank - 1) % comm_size;
53 right = (rank + 1) % comm_size;
55 torecv = total_count - recvcounts[rank];
56 tosend = total_count - recvcounts[right];
59 for (i = 1; i < comm_size; i++)
60 if (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. */
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);
79 /* Protect against wrap-around of indices */
86 if (!sendnow && !recvnow) {
87 /* Don't do anything. This case is possible if two
88 * consecutive processes contribute 0 bytes each. */
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);
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);
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,
110 if (soffset == recvcounts[sidx]) {
112 sidx = (sidx + comm_size - 1) % comm_size;
114 if (roffset == recvcounts[ridx]) {
116 ridx = (ridx + comm_size - 1) % comm_size;