Пример #1
0
int
sc_allgather (void *sendbuf, int sendcount, sc_MPI_Datatype sendtype,
              void *recvbuf, int recvcount, sc_MPI_Datatype recvtype,
              sc_MPI_Comm mpicomm)
{
  int                 mpiret;
  int                 mpisize;
  int                 mpirank;
  size_t              datasize;
#ifdef SC_DEBUG
  size_t              datasize2;
#endif

  SC_ASSERT (sendcount >= 0 && recvcount >= 0);

  /* *INDENT-OFF* HORRIBLE indent bug */
  datasize = (size_t) sendcount * sc_mpi_sizeof (sendtype);
#ifdef SC_DEBUG
  datasize2 = (size_t) recvcount * sc_mpi_sizeof (recvtype);
#endif
  /* *INDENT-ON* */

  SC_ASSERT (datasize == datasize2);

  mpiret = sc_MPI_Comm_size (mpicomm, &mpisize);
  SC_CHECK_MPI (mpiret);
  mpiret = sc_MPI_Comm_rank (mpicomm, &mpirank);
  SC_CHECK_MPI (mpiret);

  memcpy (((char *) recvbuf) + mpirank * datasize, sendbuf, datasize);
  sc_allgather_recursive (mpicomm, (char *) recvbuf, (int) datasize,
                          mpisize, mpirank, mpirank);

  return sc_MPI_SUCCESS;
}
Пример #2
0
static void
sc_reduce_alltoall (MPI_Comm mpicomm,
                    void *data, int count, MPI_Datatype datatype,
                    int groupsize, int target,
                    int maxlevel, int level, int branch,
                    sc_reduce_t reduce_fn)
{
  int                 i, l;
  int                 mpiret;
  int                 doall, allcount;
  int                 myrank, peer, peer2;
  int                 shift;
  char               *alldata;
  size_t              datasize;
  MPI_Request        *request, *rrequest, *srequest;

  doall = 0;
  if (target == -1) {
    doall = 1;
    target = 0;
  }

  SC_ASSERT (0 <= target && target < groupsize);

  myrank = sc_search_bias (maxlevel, level, branch, target);

  SC_ASSERT (0 <= myrank && myrank < groupsize);
  SC_ASSERT (reduce_fn != NULL);

  /* *INDENT-OFF* HORRIBLE indent bug */
  datasize = (size_t) count * sc_mpi_sizeof (datatype);
  /* *INDENT-ON* */

  if (doall || target == myrank) {
    allcount = 1 << level;

    alldata = SC_ALLOC (char, allcount * datasize);
    request = SC_ALLOC (MPI_Request, 2 * allcount);
    rrequest = request;
    srequest = request + allcount;

    for (i = 0; i < allcount; ++i) {
      peer = sc_search_bias (maxlevel, level, i, target);

      /* communicate with existing peers */
      if (peer == myrank) {
        memcpy (alldata + i * datasize, data, datasize);
        rrequest[i] = srequest[i] = MPI_REQUEST_NULL;
      }
      else {
        if (peer < groupsize) {
          mpiret = MPI_Irecv (alldata + i * datasize, datasize, MPI_BYTE,
                              peer, SC_TAG_REDUCE, mpicomm, rrequest + i);
          SC_CHECK_MPI (mpiret);
          if (doall) {
            mpiret = MPI_Isend (data, datasize, MPI_BYTE,
                                peer, SC_TAG_REDUCE, mpicomm, srequest + i);
            SC_CHECK_MPI (mpiret);
          }
          else {
            srequest[i] = MPI_REQUEST_NULL;     /* unused */
          }
        }
        else {
          /* ignore non-existing ranks greater or equal mpisize */
          rrequest[i] = srequest[i] = MPI_REQUEST_NULL;
        }
      }
    }

    /* complete receive operations */
    mpiret = MPI_Waitall (allcount, rrequest, MPI_STATUSES_IGNORE);
    SC_CHECK_MPI (mpiret);

    /* process received data in the same order as sc_reduce_recursive */
    for (shift = 0, l = level - 1; l >= 0; ++shift, --l) {
      for (i = 0; i < 1 << l; ++i) {
#ifdef SC_DEBUG
        peer = sc_search_bias (maxlevel, l + 1, 2 * i, target);
#endif
        peer2 = sc_search_bias (maxlevel, l + 1, 2 * i + 1, target);
        SC_ASSERT (peer < peer2);

        if (peer2 < groupsize) {
          reduce_fn (alldata + ((2 * i + 1) << shift) * datasize,
                     alldata + ((2 * i) << shift) * datasize,
                     count, datatype);
        }
      }
    }
    memcpy (data, alldata, datasize);
    SC_FREE (alldata);          /* alldata is not used in send buffers */

    /* wait for sends only after computation is done */
    if (doall) {
      mpiret = MPI_Waitall (allcount, srequest, MPI_STATUSES_IGNORE);
      SC_CHECK_MPI (mpiret);
    }
    SC_FREE (request);
  }