Actual source code: mpiu.c

  1: /*$Id: mpiu.c,v 1.100 2001/03/23 23:20:45 balay Exp $*/

 3:  #include petsc.h

  5: #undef __FUNCT__  
  7: int PetscSequentialPhaseBegin_Private(MPI_Comm comm,int ng)
  8: {
  9:   int        lidx,np,tag = 0,ierr;
 10:   MPI_Status status;

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

 26: #undef __FUNCT__  
 28: int PetscSequentialPhaseEnd_Private(MPI_Comm comm,int ng)
 29: {
 30:   int        lidx,np,tag = 0,ierr;
 31:   MPI_Status status;

 34:   MPI_Comm_rank(comm,&lidx);
 35:   MPI_Comm_size(comm,&np);
 36:   if (np == 1) return(0);

 38:   /* Send to the first process in the next group */
 39:   if ((lidx % ng) == ng - 1 || lidx == np - 1) {
 40:     MPI_Send(0,0,MPI_INT,(lidx + 1) % np,tag,comm);
 41:   }
 42:   if (!lidx) {
 43:     MPI_Recv(0,0,MPI_INT,np-1,tag,comm,&status);
 44:   }
 45:   return(0);
 46: }

 48: /* ---------------------------------------------------------------------*/
 49: /*
 50:     The variable Petsc_Seq_keyval is used to indicate an MPI attribute that
 51:   is attached to a communicator that manages the sequential phase code below.
 52: */
 53: static int Petsc_Seq_keyval = MPI_KEYVAL_INVALID;

 55: #undef __FUNCT__  
 57: /*@C
 58:    PetscSequentialPhaseBegin - Begins a sequential section of code.  

 60:    Collective on MPI_Comm

 62:    Input Parameters:
 63: +  comm - Communicator to sequentialize.  
 64: -  ng   - Number in processor group.  This many processes are allowed to execute
 65:    at the same time (usually 1)

 67:    Level: intermediate

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

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

 86: .seealso: PetscSequentialPhaseEnd()

 88:    Concepts: sequential stage

 90: @*/
 91: int PetscSequentialPhaseBegin(MPI_Comm comm,int ng)
 92: {
 93:   int        ierr,np;
 94:   MPI_Comm   local_comm,*addr_local_comm;

 97:   MPI_Comm_size(comm,&np);
 98:   if (np == 1) return(0);

100:   /* Get the private communicator for the sequential operations */
101:   if (Petsc_Seq_keyval == MPI_KEYVAL_INVALID) {
102:     MPI_Keyval_create(MPI_NULL_COPY_FN,MPI_NULL_DELETE_FN,&Petsc_Seq_keyval,0);
103:   }

105:   MPI_Comm_dup(comm,&local_comm);
106:   PetscMalloc(sizeof(MPI_Comm),&addr_local_comm);
107:   *addr_local_comm = local_comm;
108:   MPI_Attr_put(comm,Petsc_Seq_keyval,(void*)addr_local_comm);
109:   PetscSequentialPhaseBegin_Private(local_comm,ng);
110:   return(0);
111: }

113: #undef __FUNCT__  
115: /*@C
116:    PetscSequentialPhaseEnd - Ends a sequential section of code.

118:    Collective on MPI_Comm

120:    Input Parameters:
121: +  comm - Communicator to sequentialize.  
122: -  ng   - Number in processor group.  This many processes are allowed to execute
123:    at the same time (usually 1)

125:    Level: intermediate

127:    Notes:
128:    See PetscSequentialPhaseBegin() for more details.

130: .seealso: PetscSequentialPhaseBegin()

132:    Concepts: sequential stage

134: @*/
135: int PetscSequentialPhaseEnd(MPI_Comm comm,int ng)
136: {
137:   int        ierr,np,flag;
138:   MPI_Comm   local_comm,*addr_local_comm;

141:   MPI_Comm_size(comm,&np);
142:   if (np == 1) return(0);

144:   MPI_Attr_get(comm,Petsc_Seq_keyval,(void **)&addr_local_comm,&flag);
145:   if (!flag) {
146:     SETERRQ(1,"Wrong MPI communicator; must pass in one used with PetscSequentialPhaseBegin()");
147:   }
148:   local_comm = *addr_local_comm;

150:   PetscSequentialPhaseEnd_Private(local_comm,ng);

152:   PetscFree(addr_local_comm);
153:   MPI_Comm_free(&local_comm);
154:   MPI_Attr_delete(comm,Petsc_Seq_keyval);

156:   return(0);
157: }