1 /* Copyright (c) 2013-2014. The SimGrid Team.
2 * All rights reserved. */
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. */
9 * (C) 2001 by Argonne National Laboratory.
10 * See COPYRIGHT in top-level directory.
13 #include "colls_private.h"
15 /*****************************************************************************
16 * Function: allgather_mpich_ring
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
26 ****************************************************************************/
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,
34 char * sbuf = NULL, * rbuf = NULL;
36 int torecv=0, tosend=0, min, rank, comm_size;
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);
45 recvtype_extent= smpi_datatype_get_extent( recvtype);
47 for (i=0; i<comm_size; i++)
48 total_count += recvcounts[i];
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);
57 left = (comm_size + rank - 1) % comm_size;
58 right = (rank + 1) % comm_size;
60 torecv = total_count - recvcounts[rank];
61 tosend = total_count - recvcounts[right];
64 for (i = 1; i < comm_size; i++)
65 if (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. */
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);
84 /* Protect against wrap-around of indices */
91 if (!sendnow && !recvnow) {
92 /* Don't do anything. This case is possible if two
93 * consecutive processes contribute 0 bytes each. */
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);
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);
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,
115 if (soffset == recvcounts[sidx]) {
117 sidx = (sidx + comm_size - 1) % comm_size;
119 if (roffset == recvcounts[ridx]) {
121 ridx = (ridx + comm_size - 1) % comm_size;