Date: 2013-07-02T14:39:06+00:00

Actual source code: mpiu.c
petsc-3.4.2 2013-07-02

      2: #include <petscsys.h>        /*I  "petscsys.h"  I*/
      3: /*
      4:     Note that tag of 0 is ok because comm is a private communicator
      5:   generated below just for these routines.
      6: */

     10: PetscErrorCode PetscSequentialPhaseBegin_Private(MPI_Comm comm,int ng)
     11: {
     13:   PetscMPIInt    rank,size,tag = 0;
     14:   MPI_Status     status;

     17:   MPI_Comm_size(comm,&size);
     18:   if (size == 1) return(0);
     19:   MPI_Comm_rank(comm,&rank);
     20:   if (rank) {
     21:     MPI_Recv(0,0,MPI_INT,rank-1,tag,comm,&status);
     22:   }
     23:   /* Send to the next process in the group unless we are the last process */
     24:   if ((rank % ng) < ng - 1 && rank != size - 1) {
     25:     MPI_Send(0,0,MPI_INT,rank + 1,tag,comm);
     26:   }
     27:   return(0);
     28: }

     32: PetscErrorCode PetscSequentialPhaseEnd_Private(MPI_Comm comm,int ng)
     33: {
     35:   PetscMPIInt    rank,size,tag = 0;
     36:   MPI_Status     status;

     39:   MPI_Comm_rank(comm,&rank);
     40:   MPI_Comm_size(comm,&size);
     41:   if (size == 1) return(0);

     43:   /* Send to the first process in the next group */
     44:   if ((rank % ng) == ng - 1 || rank == size - 1) {
     45:     MPI_Send(0,0,MPI_INT,(rank + 1) % size,tag,comm);
     46:   }
     47:   if (!rank) {
     48:     MPI_Recv(0,0,MPI_INT,size-1,tag,comm,&status);
     49:   }
     50:   return(0);
     51: }

     53: /* ---------------------------------------------------------------------*/
     54: /*
     55:     The variable Petsc_Seq_keyval is used to indicate an MPI attribute that
     56:   is attached to a communicator that manages the sequential phase code below.
     57: */
     58: static int Petsc_Seq_keyval = MPI_KEYVAL_INVALID;

     62: /*@
     63:    PetscSequentialPhaseBegin - Begins a sequential section of code.

     65:    Collective on MPI_Comm

     67:    Input Parameters:
     68: +  comm - Communicator to sequentialize.
     69: -  ng   - Number in processor group.  This many processes are allowed to execute
     70:    at the same time (usually 1)

     72:    Level: intermediate

     74:    Notes:
     75:    PetscSequentialPhaseBegin() and PetscSequentialPhaseEnd() provide a
     76:    way to force a section of code to be executed by the processes in
     77:    rank order.  Typically, this is done with
     78: .vb
     79:       PetscSequentialPhaseBegin(comm, 1);
     80:       <code to be executed sequentially>
     81:       PetscSequentialPhaseEnd(comm, 1);
     82: .ve

     84:    Often, the sequential code contains output statements (e.g., printf) to
     85:    be executed.  Note that you may need to flush the I/O buffers before
     86:    calling PetscSequentialPhaseEnd().  Also, note that some systems do
     87:    not propagate I/O in any order to the controling terminal (in other words,
     88:    even if you flush the output, you may not get the data in the order
     89:    that you want).

     91: .seealso: PetscSequentialPhaseEnd()

     93:    Concepts: sequential stage

     95: @*/
     96: PetscErrorCode  PetscSequentialPhaseBegin(MPI_Comm comm,int ng)
     97: {
     99:   PetscMPIInt    size;
    100:   MPI_Comm       local_comm,*addr_local_comm;

    103:   MPI_Comm_size(comm,&size);
    104:   if (size == 1) return(0);

    106:   /* Get the private communicator for the sequential operations */
    107:   if (Petsc_Seq_keyval == MPI_KEYVAL_INVALID) {
    108:     MPI_Keyval_create(MPI_NULL_COPY_FN,MPI_NULL_DELETE_FN,&Petsc_Seq_keyval,0);
    109:   }

    111:   MPI_Comm_dup(comm,&local_comm);
    112:   PetscMalloc(sizeof(MPI_Comm),&addr_local_comm);

    114:   *addr_local_comm = local_comm;

    116:   MPI_Attr_put(comm,Petsc_Seq_keyval,(void*)addr_local_comm);
    117:   PetscSequentialPhaseBegin_Private(local_comm,ng);
    118:   return(0);
    119: }

    123: /*@
    124:    PetscSequentialPhaseEnd - Ends a sequential section of code.

    126:    Collective on MPI_Comm

    128:    Input Parameters:
    129: +  comm - Communicator to sequentialize.
    130: -  ng   - Number in processor group.  This many processes are allowed to execute
    131:    at the same time (usually 1)

    133:    Level: intermediate

    135:    Notes:
    136:    See PetscSequentialPhaseBegin() for more details.

    138: .seealso: PetscSequentialPhaseBegin()

    140:    Concepts: sequential stage

    142: @*/
    143: PetscErrorCode  PetscSequentialPhaseEnd(MPI_Comm comm,int ng)
    144: {
    146:   PetscMPIInt    size,flag;
    147:   MPI_Comm       local_comm,*addr_local_comm;

    150:   MPI_Comm_size(comm,&size);
    151:   if (size == 1) return(0);

    153:   MPI_Attr_get(comm,Petsc_Seq_keyval,(void**)&addr_local_comm,&flag);
    154:   if (!flag) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Wrong MPI communicator; must pass in one used with PetscSequentialPhaseBegin()");
    155:   local_comm = *addr_local_comm;

    157:   PetscSequentialPhaseEnd_Private(local_comm,ng);

    159:   PetscFree(addr_local_comm);
    160:   MPI_Comm_free(&local_comm);
    161:   MPI_Attr_delete(comm,Petsc_Seq_keyval);
    162:   return(0);
    163: }