Actual source code: petscpreload.h
1: /*
2: Macros for preloading a block of code so that startup costs (such as first-touch
3: allocation) are not attributed to the measured run. See `PetscPreLoadBegin()`.
4: */
5: #pragma once
7: #include <petscsys.h>
9: /* MANSEC = Sys */
10: /* SUBMANSEC = Log */
12: /*MC
13: PetscPreLoadBegin - Begin a block of code that is timed twice so that startup costs (such as JIT or first-touch allocation) are not attributed to the measured run
15: Synopsis:
16: #include <petscpreload.h>
17: PetscPreLoadBegin(PetscBool flag, const char name[])
19: Not Collective; No Fortran Support
21: Input Parameters:
22: + flag - whether preloading is desired (may be overridden by the command-line option `-preload`)
23: - name - name to use for the `PetscLogStage` created for the measured run
25: Level: intermediate
27: Note:
28: Use this macro in the form
29: .vb
30: PetscPreLoadBegin(PETSC_TRUE, "Compute");
31: // ... code to be timed
32: PetscPreLoadEnd();
33: .ve
34: It expands to a loop that runs the enclosed code twice when preloading is enabled and once otherwise.
35: Pair with `PetscPreLoadEnd()`. Use `PetscPreLoadStage()` to advance to a new named stage between phases.
37: .seealso: `PetscPreLoadEnd()`, `PetscPreLoadStage()`, `PetscLogStageRegister()`, `PetscLogStagePush()`
38: M*/
39: #define PetscPreLoadBegin(flag, name) \
40: do { \
41: PetscBool PetscPreLoading = flag; \
42: int PetscPreLoadMax, PetscPreLoadIt; \
43: PetscLogStage _stageNum; \
44: PetscCall(PetscOptionsGetBool(NULL, NULL, "-preload", &PetscPreLoading, NULL)); \
45: PetscPreLoadMax = (int)(PetscPreLoading); \
46: PetscPreLoadingUsed = PetscPreLoading ? PETSC_TRUE : PetscPreLoadingUsed; \
47: PetscCall(PetscLogStageGetId(name, &_stageNum)); \
48: for (PetscPreLoadIt = (_stageNum == -1) ? 0 : PetscPreLoadMax; PetscPreLoadIt <= PetscPreLoadMax; PetscPreLoadIt++) { \
49: PetscPreLoadingOn = (PetscBool)(PetscPreLoadIt < PetscPreLoadMax); \
50: PetscCall(PetscBarrier(NULL)); \
51: if (_stageNum == -1) PetscCall(PetscLogStageRegister(name, &_stageNum)); \
52: PetscCall(PetscLogStageSetActive(_stageNum, (PetscBool)(PetscPreLoadIt == PetscPreLoadMax))); \
53: PetscCall(PetscLogStagePush(_stageNum))
55: /*MC
56: PetscPreLoadEnd - Close a preload block started with `PetscPreLoadBegin()`
58: Synopsis:
59: #include <petscpreload.h>
60: PetscPreLoadEnd()
62: Not Collective; No Fortran Support
64: Level: intermediate
66: .seealso: `PetscPreLoadBegin()`, `PetscPreLoadStage()`
67: M*/
68: #define PetscPreLoadEnd() \
69: PetscCall(PetscLogStagePop()); \
70: } \
71: } \
72: while (0)
74: /*MC
75: PetscPreLoadStage - Advance to a new named stage inside a `PetscPreLoadBegin()` / `PetscPreLoadEnd()` block
77: Synopsis:
78: #include <petscpreload.h>
79: PetscPreLoadStage(const char name[])
81: Not Collective; No Fortran Support
83: Input Parameter:
84: . name - name for the new `PetscLogStage`
86: Level: intermediate
88: Note:
89: Pops the previous stage, registers (or reuses) the new stage, and pushes it. Only valid between
90: `PetscPreLoadBegin()` and `PetscPreLoadEnd()`.
92: .seealso: `PetscPreLoadBegin()`, `PetscPreLoadEnd()`, `PetscLogStagePush()`, `PetscLogStagePop()`
93: M*/
94: #define PetscPreLoadStage(name) \
95: do { \
96: PetscCall(PetscLogStagePop()); \
97: PetscCall(PetscLogStageGetId(name, &_stageNum)); \
98: if (_stageNum == -1) PetscCall(PetscLogStageRegister(name, &_stageNum)); \
99: PetscCall(PetscLogStageSetActive(_stageNum, (PetscBool)(!PetscPreLoadMax || PetscPreLoadIt))); \
100: PetscCall(PetscLogStagePush(_stageNum)); \
101: } while (0)
103: PETSC_EXTERN PetscBool PetscPreLoadingUsed; /* true if we are or have done preloading */
104: PETSC_EXTERN PetscBool PetscPreLoadingOn; /* true if we are currently in a preloading calculation */