Beispiel #1
0
PUBLIC int MPI_Bcast (void *buffer, int count, MPI_Datatype datatype, int root, MPI_Comm comm)
{
   check_comm (comm);
   check_coll_root (root, comm);
   check_datatype (datatype, comm);

   if (comm->group->size == 1)
      return MPI_SUCCESS;

   if (comm->group->rank == root)
   {
      int i, j, rval;
      MPI_Request *reqs = mymalloc (comm->group->size - 1, MPI_Request);

      for (i = 0; i < root; i++)
         if (rval = MPI_Isend (buffer, count, datatype, i, MPII_BCAST_TAG,
               comm, &(reqs[i])))
         {
            free (reqs);
            return rval;
         }
      for (j = i++; i < comm->group->size; i++, j++)
         if (rval = MPI_Isend (buffer, count, datatype, i, MPII_BCAST_TAG,
               comm, &(reqs[j])))
         {
            free (reqs);
            return rval;
         }

      rval = MPI_Waitall (comm->group->size - 1, reqs, NULL);
      free (reqs);
      return rval;
   }
   else
      return MPI_Recv (buffer, count, datatype, root, MPII_BCAST_TAG, comm,
            NULL);
}
Beispiel #2
0
PUBLIC int MPI_Recv (void *buf, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm, MPI_Status *status)
{
   MPI_Request req;
   MPII_Msg msg;
   MPII_Member *member;
   int rval, retry = 0;

   check_comm (comm);
   check_datatype (datatype, comm);
   if (source < 0 || source > comm->group->size)
     if (source == MPI_PROC_NULL)
     {
       /* The following two equalities are defined in MPI-1 (section 3.11) */
       status->MPI_SOURCE = MPI_PROC_NULL;
       status->MPI_TAG = MPI_ANY_TAG;
       status->MPII_COUNT = 0;
       return MPI_SUCCESS;
     }
     else if (source != MPI_ANY_SOURCE)
       return MPII_Error (comm, MPII_RANK_RANGE);

   req.type = MPII_REQUEST_RECV;
   req.comm = comm;
   req.buf = buf;
   req.count = count;
   req.datatype = datatype;
   req.srcdest = source;
   req.tag = tag;

   post_recv ();

   member = MPII_Me (comm);
   lock (member->mutex);
      while (!MPII_queue_search (&retry, &(member->queue), MPII_match_recv,
                                 &req, &msg))
         wait (member->cond, member->mutex);
   unlock (member->mutex);

   if (status != NULL)
   {
      status->MPI_SOURCE = msg.req->comm->group->rank;
      status->MPI_TAG = msg.req->tag;
      status->MPII_COUNT = msg.req->count * MPII_types[msg.req->datatype].size;
   }

   if (datatype != msg.req->datatype)
      rval = MPII_Error (comm, MPII_TYPE_MISMATCH);
   else if (count >= msg.req->count)
   {
      memcpy (buf, msg.req->buf, msg.req->count * MPII_types[datatype].size);
      rval = MPI_SUCCESS;
   }
   else
   {
      memcpy (buf, msg.req->buf, count * MPII_types[datatype].size);
      rval = MPII_Error (comm, MPII_OVERFLOW);
   }

   notify_sender (((MPII_Member **) msg.req->comm->group->members)
         [msg.req->comm->group->rank], msg, member);

   return rval;
}
Beispiel #3
0
PUBLIC int MPI_Reduce (void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype, MPI_Op op, int root, MPI_Comm comm)
#endif
{
    int rval = MPI_SUCCESS;

    check_comm (comm);
    check_coll_root (root, comm);
    check_datatype (datatype, comm);
    check_op (op, comm);

    if (comm->group->size == 1)
    {
        memcpy (recvbuf, sendbuf, count * MPII_types[datatype].size);
        return MPI_SUCCESS;
    }

    if (comm->group->rank == root)
    {
        int i;
        int len = count * MPII_types[datatype].size;
        void *tempbuf = MPII_Malloc (len);
#ifdef ALLREDUCE
        MPI_Request *reqs;
#endif

        if (MPII_ops[op].commute)
        {
            if ((rval = MPI_Recv (recvbuf, count, datatype, MPI_ANY_SOURCE,
                                  MPII_REDUCE_TAG, comm, NULL)))
            {
                free (tempbuf);
                return rval;
            }
            (*(MPII_ops[op].f)) (sendbuf, recvbuf, &count, &datatype);

            for (i = 0; i < comm->group->size - 1; i++)
            {
                if ((rval = MPI_Recv (tempbuf, count, datatype, MPI_ANY_SOURCE,
                                      MPII_REDUCE_TAG, comm, NULL)))
                {
                    free (tempbuf);
                    return rval;
                }
                (*(MPII_ops[op].f)) (tempbuf, recvbuf, &count, &datatype);
            }
        }
        else
        {
            if (root == 0)
                memmove (recvbuf, sendbuf, len);
            else if ((rval = MPI_Recv (recvbuf, count, datatype, 0,
                                       MPII_REDUCE_TAG, comm, NULL)))
            {
                free (tempbuf);
                return rval;
            }

            for (i = 1; i < comm->group->size; i++)
            {
                if (root == i)
                    memmove (tempbuf, sendbuf, len);
                else if ((rval = MPI_Recv (tempbuf, count, datatype, i,
                                           MPII_REDUCE_TAG, comm, NULL)))
                {
                    free (tempbuf);
                    return rval;
                }
                (*(MPII_ops[op].f)) (recvbuf, tempbuf, &count, &datatype);

                if (++i >= comm->group->size)
                {
                    memmove (recvbuf, tempbuf, len);
                    break;
                }

                if ((rval = MPI_Recv (recvbuf, count, datatype, i,
                                      MPII_REDUCE_TAG, comm, NULL)))
                {
                    free (tempbuf);
                    return rval;
                }
                (*(MPII_ops[op].f)) (tempbuf, recvbuf, &count, &datatype);
            }
        }

        free (tempbuf);

#ifdef ALLREDUCE
        int j;
        reqs = mymalloc (comm->group->size - 1, MPI_Request);
        for (i = 0; i < root; i++)
            if ((rval = MPI_Isend (recvbuf, count, datatype, i, MPII_ALLREDUCE_TAG2,
                                   comm, &(reqs[i]))))
            {
                free (reqs);
                return rval;
            }
        for (j = i++; i < comm->group->size; i++, j++)
            if ((rval = MPI_Isend (recvbuf, count, datatype, i, MPII_ALLREDUCE_TAG2,
                                   comm, &(reqs[j]))))
            {
                free (reqs);
                return rval;
            }
        rval = MPI_Waitall (comm->group->size - 1, reqs, NULL);
        free (reqs);
#endif
    }
    else
    {
        if ((rval = MPI_Send (sendbuf, count, datatype, root, MPII_REDUCE_TAG, comm)))
            return rval;
#ifdef ALLREDUCE
        rval = MPI_Recv (recvbuf, count, datatype, root, MPII_ALLREDUCE_TAG2, comm,
                         NULL);
#endif
    }
    return rval;
}