Actual source code: mpiu.c
1: #include <petsc/private/petscimpl.h>
2: /*
3: Note that tag of 0 is ok because comm is a private communicator
4: generated below just for these routines.
5: */
7: PETSC_INTERN PetscErrorCode PetscSequentialPhaseBegin_Private(MPI_Comm comm, int ng)
8: {
9: PetscMPIInt rank, size, tag = 0;
10: MPI_Status status;
12: PetscFunctionBegin;
13: PetscCallMPI(MPI_Comm_size(comm, &size));
14: if (size == 1) PetscFunctionReturn(PETSC_SUCCESS);
15: PetscCallMPI(MPI_Comm_rank(comm, &rank));
16: if (rank) PetscCallMPI(MPI_Recv(NULL, 0, MPI_INT, rank - 1, tag, comm, &status));
17: /* Send to the next process in the group unless we are the last process */
18: if ((rank % ng) < ng - 1 && rank != size - 1) PetscCallMPI(MPI_Send(NULL, 0, MPI_INT, rank + 1, tag, comm));
19: PetscFunctionReturn(PETSC_SUCCESS);
20: }
22: PETSC_INTERN PetscErrorCode PetscSequentialPhaseEnd_Private(MPI_Comm comm, int ng)
23: {
24: PetscMPIInt rank, size, tag = 0;
25: MPI_Status status;
27: PetscFunctionBegin;
28: PetscCallMPI(MPI_Comm_rank(comm, &rank));
29: PetscCallMPI(MPI_Comm_size(comm, &size));
30: if (size == 1) PetscFunctionReturn(PETSC_SUCCESS);
32: /* Send to the first process in the next group */
33: if ((rank % ng) == ng - 1 || rank == size - 1) PetscCallMPI(MPI_Send(NULL, 0, MPI_INT, (rank + 1) % size, tag, comm));
34: if (rank == 0) PetscCallMPI(MPI_Recv(NULL, 0, MPI_INT, size - 1, tag, comm, &status));
35: PetscFunctionReturn(PETSC_SUCCESS);
36: }
38: /*
39: The variable Petsc_Seq_keyval is used to indicate an MPI attribute that
40: is attached to a communicator that manages the sequential phase code below.
41: */
42: PetscMPIInt Petsc_Seq_keyval = MPI_KEYVAL_INVALID;
44: /*@
45: PetscSequentialPhaseBegin - Begins a sequential section of code.
47: Collective
49: Input Parameters:
50: + comm - Communicator to sequentialize over
51: - ng - Number in processor group. This many processes are allowed to execute
52: at the same time (usually 1)
54: Level: intermediate
56: Notes:
57: `PetscSequentialPhaseBegin()` and `PetscSequentialPhaseEnd()` provide a
58: way to force a section of code to be executed by the processes in
59: rank order. Typically, this is done with
60: .vb
61: PetscSequentialPhaseBegin(comm, 1);
62: <code to be executed sequentially>
63: PetscSequentialPhaseEnd(comm, 1);
64: .ve
66: You should use `PetscSynchronizedPrintf()` to ensure output between MPI ranks is properly order and not these routines.
68: .seealso: `PetscSequentialPhaseEnd()`, `PetscSynchronizedPrintf()`
69: @*/
70: PetscErrorCode PetscSequentialPhaseBegin(MPI_Comm comm, int ng)
71: {
72: PetscMPIInt size;
73: MPI_Comm local_comm, *addr_local_comm;
75: PetscFunctionBegin;
76: PetscCall(PetscSysInitializePackage());
77: PetscCallMPI(MPI_Comm_size(comm, &size));
78: if (size == 1) PetscFunctionReturn(PETSC_SUCCESS);
80: /* Get the private communicator for the sequential operations */
81: if (Petsc_Seq_keyval == MPI_KEYVAL_INVALID) PetscCallMPI(MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, MPI_COMM_NULL_DELETE_FN, &Petsc_Seq_keyval, NULL));
83: PetscCallMPI(MPI_Comm_dup(comm, &local_comm));
84: PetscCall(PetscMalloc1(1, &addr_local_comm));
86: *addr_local_comm = local_comm;
88: PetscCallMPI(MPI_Comm_set_attr(comm, Petsc_Seq_keyval, (void *)addr_local_comm));
89: PetscCall(PetscSequentialPhaseBegin_Private(local_comm, ng));
90: PetscFunctionReturn(PETSC_SUCCESS);
91: }
93: /*@
94: PetscSequentialPhaseEnd - Ends a sequential section of code.
96: Collective
98: Input Parameters:
99: + comm - Communicator to sequentialize.
100: - ng - Number in processor group. This many processes are allowed to execute
101: at the same time (usually 1)
103: Level: intermediate
105: Note:
106: See `PetscSequentialPhaseBegin()` for more details.
108: .seealso: `PetscSequentialPhaseBegin()`
109: @*/
110: PetscErrorCode PetscSequentialPhaseEnd(MPI_Comm comm, int ng)
111: {
112: PetscMPIInt size, iflg;
113: MPI_Comm local_comm, *addr_local_comm;
115: PetscFunctionBegin;
116: PetscCallMPI(MPI_Comm_size(comm, &size));
117: if (size == 1) PetscFunctionReturn(PETSC_SUCCESS);
119: PetscCallMPI(MPI_Comm_get_attr(comm, Petsc_Seq_keyval, (void **)&addr_local_comm, &iflg));
120: PetscCheck(iflg, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Wrong MPI communicator; must pass in one used with PetscSequentialPhaseBegin()");
121: local_comm = *addr_local_comm;
123: PetscCall(PetscSequentialPhaseEnd_Private(local_comm, ng));
125: PetscCall(PetscFree(addr_local_comm));
126: PetscCallMPI(MPI_Comm_free(&local_comm));
127: PetscCallMPI(MPI_Comm_delete_attr(comm, Petsc_Seq_keyval));
128: PetscFunctionReturn(PETSC_SUCCESS);
129: }
131: /*@
132: PetscGlobalMinMaxInt - Get the global min/max from local min/max input
134: Collective
136: Input Parameters:
137: + comm - The MPI communicator to reduce with
138: - minMaxVal - An array with the local min and max
140: Output Parameter:
141: . minMaxValGlobal - An array with the global min and max
143: Level: beginner
145: .seealso: `PetscSplitOwnership()`, `PetscGlobalMinMaxReal()`
146: @*/
147: PetscErrorCode PetscGlobalMinMaxInt(MPI_Comm comm, const PetscInt minMaxVal[2], PetscInt minMaxValGlobal[2])
148: {
149: PetscInt buf[3];
150: PetscBool hasminint = (PetscBool)(minMaxVal[0] == PETSC_MIN_INT);
152: PetscFunctionBegin;
153: buf[0] = hasminint ? PETSC_MIN_INT : -minMaxVal[0]; /* Note that -PETSC_INT_MIN = PETSC_INT_MIN: ternary to suppress sanitizer warnings */
154: buf[1] = minMaxVal[1];
155: buf[2] = hasminint ? 1 : 0; /* Are there PETSC_INT_MIN in minMaxVal[0]? */
156: PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, buf, 3, MPIU_INT, MPI_MAX, comm));
157: minMaxValGlobal[0] = buf[2] ? PETSC_INT_MIN : -buf[0];
158: minMaxValGlobal[1] = buf[1];
159: PetscFunctionReturn(PETSC_SUCCESS);
160: }
162: /*@
163: PetscGlobalMinMaxReal - Get the global min/max from local min/max input
165: Collective
167: Input Parameters:
168: + comm - The MPI communicator to reduce with
169: - minMaxVal - An array with the local min and max
171: Output Parameter:
172: . minMaxValGlobal - An array with the global min and max
174: Level: beginner
176: .seealso: `PetscSplitOwnership()`, `PetscGlobalMinMaxInt()`
177: @*/
178: PetscErrorCode PetscGlobalMinMaxReal(MPI_Comm comm, const PetscReal minMaxVal[2], PetscReal minMaxValGlobal[2])
179: {
180: PetscFunctionBegin;
181: minMaxValGlobal[0] = -minMaxVal[0];
182: minMaxValGlobal[1] = minMaxVal[1];
183: PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, minMaxValGlobal, 2, MPIU_REAL, MPIU_MAX, comm));
184: minMaxValGlobal[0] = -minMaxValGlobal[0];
185: PetscFunctionReturn(PETSC_SUCCESS);
186: }