Actual source code: psplit.c
1: #include <petscsys.h>
3: /*@
4: PetscSplitOwnershipBlock - Given a global (or local) length determines a local
5: (or global) length via a simple formula. Splits so each processors local size
6: is divisible by the block size.
8: Collective (if `N` is `PETSC_DECIDE`)
10: Input Parameters:
11: + comm - MPI communicator that shares the object being divided
12: . bs - block size
13: . n - local length (or `PETSC_DECIDE` to have it set)
14: - N - global length (or `PETSC_DECIDE`)
16: Level: developer
18: Notes:
19: `n` and `N` cannot be both `PETSC_DECIDE`
21: If one processor calls this with `N` of `PETSC_DECIDE` then all processors
22: must, otherwise the program will hang.
24: .seealso: `PetscSplitOwnership()`, `PetscSplitOwnershipEqual()`
25: @*/
26: PetscErrorCode PetscSplitOwnershipBlock(MPI_Comm comm, PetscInt bs, PetscInt *n, PetscInt *N)
27: {
28: PetscMPIInt size, rank;
30: PetscFunctionBegin;
31: PetscCheck(*N != PETSC_DECIDE || *n != PETSC_DECIDE, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Both n and N cannot be PETSC_DECIDE");
33: if (*N == PETSC_DECIDE) {
34: PetscCheck(*n % bs == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "local size %" PetscInt_FMT " not divisible by block size %" PetscInt_FMT, *n, bs);
35: PetscCall(MPIU_Allreduce(n, N, 1, MPIU_INT, MPI_SUM, comm));
36: } else if (*n == PETSC_DECIDE) {
37: PetscInt Nbs = *N / bs;
38: PetscCallMPI(MPI_Comm_size(comm, &size));
39: PetscCallMPI(MPI_Comm_rank(comm, &rank));
40: *n = bs * (Nbs / size + ((Nbs % size) > rank));
41: }
42: PetscFunctionReturn(PETSC_SUCCESS);
43: }
45: /*@
46: PetscSplitOwnership - Given a global (or local) length determines a local
47: (or global) length via a simple formula
49: Collective (if `n` or `N` is `PETSC_DECIDE`)
51: Input Parameters:
52: + comm - MPI communicator that shares the object being divided
53: . n - local length (or `PETSC_DECIDE` to have it set)
54: - N - global length (or `PETSC_DECIDE`)
56: Level: developer
58: Notes:
59: `n` and `N` cannot be both `PETSC_DECIDE`
61: If one processor calls this with `n` or `N` of `PETSC_DECIDE` then all processors
62: must. Otherwise, an error is thrown in debug mode while the program will hang
63: in optimized (i.e. configured --with-debugging=0) mode.
65: .seealso: `PetscSplitOwnershipBlock()`, `PetscSplitOwnershipEqual()`
66: @*/
67: PetscErrorCode PetscSplitOwnership(MPI_Comm comm, PetscInt *n, PetscInt *N)
68: {
69: PetscMPIInt size, rank;
71: PetscFunctionBegin;
72: PetscCheck(*N != PETSC_DECIDE || *n != PETSC_DECIDE, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Both n and N cannot be PETSC_DECIDE\n likely a call to VecSetSizes() or MatSetSizes() is wrong.\nSee https://petsc.org/release/faq/#split-ownership");
73: if (PetscDefined(USE_DEBUG)) {
74: PetscMPIInt l[2], g[2];
75: l[0] = (*n == PETSC_DECIDE) ? 1 : 0;
76: l[1] = (*N == PETSC_DECIDE) ? 1 : 0;
77: PetscCallMPI(MPI_Comm_size(comm, &size));
78: PetscCall(MPIU_Allreduce(l, g, 2, MPI_INT, MPI_SUM, comm));
79: PetscCheck(!g[0] || g[0] == size, comm, PETSC_ERR_ARG_INCOMP, "All processes must supply PETSC_DECIDE for local size");
80: PetscCheck(!g[1] || g[1] == size, comm, PETSC_ERR_ARG_INCOMP, "All processes must supply PETSC_DECIDE for global size");
81: }
83: if (*N == PETSC_DECIDE) {
84: PetscInt64 m = *n, M;
85: PetscCall(MPIU_Allreduce(&m, &M, 1, MPIU_INT64, MPI_SUM, comm));
86: PetscCheck(M <= PETSC_MAX_INT, comm, PETSC_ERR_INT_OVERFLOW, "Global size overflow %" PetscInt64_FMT ". You may consider ./configure PETSc with --with-64-bit-indices for the case you are running", M);
87: *N = (PetscInt)M;
88: } else if (*n == PETSC_DECIDE) {
89: PetscCallMPI(MPI_Comm_size(comm, &size));
90: PetscCallMPI(MPI_Comm_rank(comm, &rank));
91: *n = *N / size + ((*N % size) > rank);
92: } else if (PetscDefined(USE_DEBUG)) {
93: PetscInt tmp;
94: PetscCall(MPIU_Allreduce(n, &tmp, 1, MPIU_INT, MPI_SUM, comm));
95: PetscCheck(tmp == *N, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Sum of local lengths %" PetscInt_FMT " does not equal global length %" PetscInt_FMT ", my local length %" PetscInt_FMT "\n likely a call to VecSetSizes() or MatSetSizes() is wrong.\nSee https://petsc.org/release/faq/#split-ownership", tmp, *N, *n);
96: }
97: PetscFunctionReturn(PETSC_SUCCESS);
98: }
100: /*@
101: PetscSplitOwnershipEqual - Given a global (or local) length determines a local
102: (or global) length via a simple formula, trying to have all local lengths equal
104: Collective (if `n` or `N` is `PETSC_DECIDE`)
106: Input Parameters:
107: + comm - MPI communicator that shares the object being divided
108: . n - local length (or `PETSC_DECIDE` to have it set)
109: - N - global length (or `PETSC_DECIDE`)
111: Level: developer
113: Notes:
114: This is intended to be used with `MATSCALAPACK`, where the local size must
115: be equal in all processes (except possibly the last one). For instance,
116: the local sizes when splitting `N`=50 with 6 processes are 9,9,9,9,9,5
118: n and N cannot be both `PETSC_DECIDE`
120: If one processor calls this with `n` or `N` of `PETSC_DECIDE` then all processors
121: must. Otherwise, an error is thrown in debug mode while the program will hang
122: in optimized (i.e. configured --with-debugging=0) mode.
124: .seealso: `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`
125: @*/
126: PetscErrorCode PetscSplitOwnershipEqual(MPI_Comm comm, PetscInt *n, PetscInt *N)
127: {
128: PetscMPIInt size, rank;
130: PetscFunctionBegin;
131: PetscCheck(*N != PETSC_DECIDE || *n != PETSC_DECIDE, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Both n and N cannot be PETSC_DECIDE");
132: if (PetscDefined(USE_DEBUG)) {
133: PetscMPIInt l[2], g[2];
134: l[0] = (*n == PETSC_DECIDE) ? 1 : 0;
135: l[1] = (*N == PETSC_DECIDE) ? 1 : 0;
136: PetscCallMPI(MPI_Comm_size(comm, &size));
137: PetscCall(MPIU_Allreduce(l, g, 2, MPI_INT, MPI_SUM, comm));
138: PetscCheck(!g[0] || g[0] == size, comm, PETSC_ERR_ARG_INCOMP, "All processes must supply PETSC_DECIDE for local size");
139: PetscCheck(!g[1] || g[1] == size, comm, PETSC_ERR_ARG_INCOMP, "All processes must supply PETSC_DECIDE for global size");
140: }
142: if (*N == PETSC_DECIDE) {
143: PetscInt64 m = *n, M;
144: PetscCall(MPIU_Allreduce(&m, &M, 1, MPIU_INT64, MPI_SUM, comm));
145: PetscCheck(M <= PETSC_MAX_INT, comm, PETSC_ERR_INT_OVERFLOW, "Global size overflow %" PetscInt64_FMT ". You may consider ./configure PETSc with --with-64-bit-indices for the case you are running", M);
146: *N = (PetscInt)M;
147: } else if (*n == PETSC_DECIDE) {
148: PetscCallMPI(MPI_Comm_size(comm, &size));
149: PetscCallMPI(MPI_Comm_rank(comm, &rank));
150: *n = *N / size;
151: if (*N % size) {
152: if ((rank + 1) * (*n + 1) <= *N) *n = *n + 1;
153: else if (rank * (*n + 1) <= *N) *n = *N - rank * (*n + 1);
154: else *n = 0;
155: }
156: } else if (PetscDefined(USE_DEBUG)) {
157: PetscInt tmp;
158: PetscCall(MPIU_Allreduce(n, &tmp, 1, MPIU_INT, MPI_SUM, comm));
159: PetscCheck(tmp == *N, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Sum of local lengths %" PetscInt_FMT " does not equal global length %" PetscInt_FMT ", my local length %" PetscInt_FMT, tmp, *N, *n);
160: }
161: PetscFunctionReturn(PETSC_SUCCESS);
162: }