1 static char help[] = "Exhaustive memory tracking for DMPlex.\n\n\n"; 2 3 #include <petscdmplex.h> 4 5 static PetscErrorCode EstimateMemory(DM dm, PetscLogDouble *est) 6 { 7 DMLabel marker; 8 PetscInt cdim, depth, d, pStart, pEnd, p, Nd[4] = {0, 0, 0, 0}, lsize = 0, rmem = 0, imem = 0; 9 PetscInt coneSecMem = 0, coneMem = 0, supportSecMem = 0, supportMem = 0, labelMem = 0; 10 11 PetscFunctionBeginUser; 12 PetscCall(PetscPrintf(PETSC_COMM_SELF, "Memory Estimates\n")); 13 PetscCall(DMGetCoordinateDim(dm, &cdim)); 14 PetscCall(DMPlexGetDepth(dm, &depth)); 15 PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 16 for (d = 0; d <= depth; ++d) { 17 PetscInt start, end; 18 19 PetscCall(DMPlexGetDepthStratum(dm, d, &start, &end)); 20 Nd[d] = end - start; 21 } 22 /* Coordinates: 3 Nv reals + 2*Nv + 2*Nv ints */ 23 rmem += cdim * Nd[0]; 24 imem += 2 * Nd[0] + 2 * Nd[0]; 25 PetscCall(PetscPrintf(PETSC_COMM_SELF, " Coordinate mem: %" PetscInt_FMT " %" PetscInt_FMT "\n", (PetscInt)(cdim * Nd[0] * sizeof(PetscReal)), (PetscInt)(4 * Nd[0] * sizeof(PetscInt)))); 26 /* Depth: Nc+Nf+Ne+Nv ints */ 27 for (d = 0; d <= depth; ++d) labelMem += Nd[d]; 28 /* Cell Type: Nc+Nf+Ne+Nv ints */ 29 for (d = 0; d <= depth; ++d) labelMem += Nd[d]; 30 /* Marker */ 31 PetscCall(DMGetLabel(dm, "marker", &marker)); 32 if (marker) PetscCall(DMLabelGetStratumSize(marker, 1, &lsize)); 33 labelMem += lsize; 34 PetscCall(PetscPrintf(PETSC_COMM_SELF, " Label mem: %" PetscInt_FMT "\n", (PetscInt)(labelMem * sizeof(PetscInt)))); 35 //imem += labelMem; 36 /* Cones and Orientations: 4 Nc + 3 Nf + 2 Ne ints + (Nc+Nf+Ne) ints no separate orientation section */ 37 for (d = 0; d <= depth; ++d) coneSecMem += 2 * Nd[d]; 38 for (p = pStart; p < pEnd; ++p) { 39 PetscInt csize; 40 41 PetscCall(DMPlexGetConeSize(dm, p, &csize)); 42 coneMem += csize; 43 } 44 PetscCall(PetscPrintf(PETSC_COMM_SELF, " Cone mem: %" PetscInt_FMT " %" PetscInt_FMT " (%" PetscInt_FMT ")\n", (PetscInt)(coneMem * sizeof(PetscInt)), (PetscInt)(coneSecMem * sizeof(PetscInt)), (PetscInt)(coneMem * sizeof(PetscInt)))); 45 imem += 2 * coneMem + coneSecMem; 46 /* Supports: 4 Nc + 3 Nf + 2 Ne ints + Nc+Nf+Ne ints */ 47 for (d = 0; d <= depth; ++d) supportSecMem += 2 * Nd[d]; 48 for (p = pStart; p < pEnd; ++p) { 49 PetscInt ssize; 50 51 PetscCall(DMPlexGetSupportSize(dm, p, &ssize)); 52 supportMem += ssize; 53 } 54 PetscCall(PetscPrintf(PETSC_COMM_SELF, " Support mem: %" PetscInt_FMT " %" PetscInt_FMT "\n", (PetscInt)(supportMem * sizeof(PetscInt)), (PetscInt)(supportSecMem * sizeof(PetscInt)))); 55 imem += supportMem + supportSecMem; 56 *est = ((PetscLogDouble)imem) * sizeof(PetscInt) + ((PetscLogDouble)rmem) * sizeof(PetscReal); 57 PetscCall(PetscPrintf(PETSC_COMM_WORLD, " Estimated memory %" PetscInt_FMT "\n", (PetscInt)*est)); 58 PetscFunctionReturn(PETSC_SUCCESS); 59 } 60 61 int main(int argc, char **argv) 62 { 63 DM dm; 64 PetscBool trace = PETSC_FALSE, checkMemory = PETSC_TRUE, auxMemory = PETSC_FALSE; 65 PetscLogDouble before, after, est = 0, clean, max; 66 67 PetscFunctionBeginUser; 68 PetscCall(PetscInitialize(&argc, &argv, NULL, help)); 69 PetscCall(PetscOptionsGetBool(NULL, NULL, "-trace", &trace, NULL)); 70 PetscCall(PetscOptionsGetBool(NULL, NULL, "-check_memory", &checkMemory, NULL)); 71 PetscCall(PetscOptionsGetBool(NULL, NULL, "-aux_memory", &auxMemory, NULL)); 72 PetscCall(PetscMemorySetGetMaximumUsage()); 73 PetscCall(PetscMallocGetCurrentUsage(&before)); 74 if (trace) PetscCall(PetscMallocTraceSet(NULL, PETSC_TRUE, 5000.)); 75 PetscCall(DMCreate(PETSC_COMM_WORLD, &dm)); 76 PetscCall(DMSetType(dm, DMPLEX)); 77 PetscCall(DMSetFromOptions(dm)); 78 if (trace) PetscCall(PetscMallocTraceSet(NULL, PETSC_FALSE, 5000)); 79 PetscCall(DMViewFromOptions(dm, NULL, "-dm_view")); 80 PetscCall(PetscMallocGetCurrentUsage(&after)); 81 PetscCall(PetscMemoryGetMaximumUsage(&max)); 82 PetscCall(EstimateMemory(dm, &est)); 83 PetscCall(DMDestroy(&dm)); 84 PetscCall(PetscMallocGetCurrentUsage(&clean)); 85 PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Measured Memory\n")); 86 if (auxMemory) { 87 PetscCall(PetscPrintf(PETSC_COMM_WORLD, " Initial memory %" PetscInt_FMT "\n Extra memory for build %" PetscInt_FMT "\n Memory after destroy %" PetscInt_FMT "\n", (PetscInt)before, (PetscInt)(max - after), (PetscInt)clean)); 88 } 89 if (checkMemory) { 90 PetscCall(PetscPrintf(PETSC_COMM_WORLD, " Memory for mesh %" PetscInt_FMT "\n", (PetscInt)(after - before))); 91 PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Discrepancy %" PetscInt_FMT "\n", (PetscInt)PetscAbsReal(after - before - est))); 92 } 93 PetscCall(PetscFinalize()); 94 return 0; 95 } 96 97 /*TEST 98 build: 99 requires: !defined(PETSC_USE_64BIT_INDICES) double !complex !defined(PETSCTEST_VALGRIND) 100 101 # Memory checks cannot be included in tests because the allocated memory differs among environments 102 testset: 103 requires: !defined(PETSC_HAVE_THREADSAFETY) 104 args: -malloc_requested_size -dm_plex_box_faces 5,5 -check_memory 0 105 test: 106 suffix: tri 107 requires: triangle 108 args: -dm_plex_simplex 1 -dm_plex_interpolate 0 109 110 test: 111 suffix: tri_interp 112 requires: triangle 113 args: -dm_plex_simplex 1 -dm_plex_interpolate 1 114 115 test: 116 suffix: quad 117 args: -dm_plex_simplex 0 -dm_plex_interpolate 0 118 119 test: 120 suffix: quad_interp 121 args: -dm_plex_simplex 0 -dm_plex_interpolate 1 122 123 # Memory checks cannot be included in tests because the allocated memory differs among environments 124 testset: 125 requires: !defined(PETSC_HAVE_THREADSAFETY) 126 args: -malloc_requested_size -dm_plex_dim 3 -dm_plex_box_faces 5,5,5 -check_memory 0 127 128 # Filter out label memory because tet mesher produce different surface meshes for different compilers 129 test: 130 suffix: tet 131 requires: ctetgen 132 filter: grep -v "Label mem:" 133 args: -dm_plex_simplex 1 -dm_plex_interpolate 0 134 135 # Filter out label memory because tet mesher produce different surface meshes for different compilers 136 test: 137 suffix: tet_interp 138 requires: ctetgen 139 filter: grep -v "Label mem:" 140 args: -dm_plex_simplex 1 -dm_plex_interpolate 1 141 142 test: 143 suffix: hex 144 args: -dm_plex_simplex 0 -dm_plex_interpolate 0 145 146 test: 147 suffix: hex_interp 148 args: -dm_plex_simplex 0 -dm_plex_interpolate 1 149 TEST*/ 150