Actual source code: mpiu.c
petsc-3.8.4 2018-03-24
2: #include <petscsys.h>
3: #include <petsc/private/petscimpl.h>
4: /*
5: Note that tag of 0 is ok because comm is a private communicator
6: generated below just for these routines.
7: */
9: PetscErrorCode PetscSequentialPhaseBegin_Private(MPI_Comm comm,int ng)
10: {
12: PetscMPIInt rank,size,tag = 0;
13: MPI_Status status;
16: MPI_Comm_size(comm,&size);
17: if (size == 1) return(0);
18: MPI_Comm_rank(comm,&rank);
19: if (rank) {
20: MPI_Recv(0,0,MPI_INT,rank-1,tag,comm,&status);
21: }
22: /* Send to the next process in the group unless we are the last process */
23: if ((rank % ng) < ng - 1 && rank != size - 1) {
24: MPI_Send(0,0,MPI_INT,rank + 1,tag,comm);
25: }
26: return(0);
27: }
29: PetscErrorCode PetscSequentialPhaseEnd_Private(MPI_Comm comm,int ng)
30: {
32: PetscMPIInt rank,size,tag = 0;
33: MPI_Status status;
36: MPI_Comm_rank(comm,&rank);
37: MPI_Comm_size(comm,&size);
38: if (size == 1) return(0);
40: /* Send to the first process in the next group */
41: if ((rank % ng) == ng - 1 || rank == size - 1) {
42: MPI_Send(0,0,MPI_INT,(rank + 1) % size,tag,comm);
43: }
44: if (!rank) {
45: MPI_Recv(0,0,MPI_INT,size-1,tag,comm,&status);
46: }
47: return(0);
48: }
50: /* ---------------------------------------------------------------------*/
51: /*
52: The variable Petsc_Seq_keyval is used to indicate an MPI attribute that
53: is attached to a communicator that manages the sequential phase code below.
54: */
55: PetscMPIInt Petsc_Seq_keyval = MPI_KEYVAL_INVALID;
57: /*@
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: PetscErrorCode PetscSequentialPhaseBegin(MPI_Comm comm,int ng)
92: {
94: PetscMPIInt size;
95: MPI_Comm local_comm,*addr_local_comm;
98: MPI_Comm_size(comm,&size);
99: if (size == 1) return(0);
101: /* Get the private communicator for the sequential operations */
102: if (Petsc_Seq_keyval == MPI_KEYVAL_INVALID) {
103: MPI_Keyval_create(MPI_NULL_COPY_FN,MPI_NULL_DELETE_FN,&Petsc_Seq_keyval,0);
104: }
106: MPI_Comm_dup(comm,&local_comm);
107: PetscMalloc1(1,&addr_local_comm);
109: *addr_local_comm = local_comm;
111: MPI_Attr_put(comm,Petsc_Seq_keyval,(void*)addr_local_comm);
112: PetscSequentialPhaseBegin_Private(local_comm,ng);
113: return(0);
114: }
116: /*@
117: PetscSequentialPhaseEnd - Ends a sequential section of code.
119: Collective on MPI_Comm
121: Input Parameters:
122: + comm - Communicator to sequentialize.
123: - ng - Number in processor group. This many processes are allowed to execute
124: at the same time (usually 1)
126: Level: intermediate
128: Notes:
129: See PetscSequentialPhaseBegin() for more details.
131: .seealso: PetscSequentialPhaseBegin()
133: Concepts: sequential stage
135: @*/
136: PetscErrorCode PetscSequentialPhaseEnd(MPI_Comm comm,int ng)
137: {
139: PetscMPIInt size,flag;
140: MPI_Comm local_comm,*addr_local_comm;
143: MPI_Comm_size(comm,&size);
144: if (size == 1) return(0);
146: MPI_Attr_get(comm,Petsc_Seq_keyval,(void**)&addr_local_comm,&flag);
147: if (!flag) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Wrong MPI communicator; must pass in one used with PetscSequentialPhaseBegin()");
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);
155: return(0);
156: }