Actual source code: global_dcontext.cxx
1: #include "petscdevice_interface_internal.hpp" /*I <petscdevice.h> I*/
3: static auto rootDeviceType = PETSC_DEVICE_CONTEXT_DEFAULT_DEVICE_TYPE;
4: static auto rootStreamType = PETSC_DEVICE_CONTEXT_DEFAULT_STREAM_TYPE;
5: static PetscDeviceContext globalContext = nullptr;
7: /* when PetsDevice initializes PetscDeviceContext eagerly the type of device created should
8: * match whatever device is eagerly initialized */
9: PetscErrorCode PetscDeviceContextSetRootDeviceType_Internal(PetscDeviceType type)
10: {
11: PetscFunctionBegin;
13: rootDeviceType = type;
14: PetscFunctionReturn(PETSC_SUCCESS);
15: }
17: PetscErrorCode PetscDeviceContextSetRootStreamType_Internal(PetscStreamType type)
18: {
19: PetscFunctionBegin;
21: rootStreamType = type;
22: PetscFunctionReturn(PETSC_SUCCESS);
23: }
25: static PetscErrorCode PetscDeviceContextSetupGlobalContext_Private() noexcept
26: {
27: PetscFunctionBegin;
28: if (PetscUnlikely(!globalContext)) {
29: PetscObject pobj;
30: const auto dtype = rootDeviceType;
31: const auto finalizer = [] {
32: PetscDeviceType dtype;
34: PetscFunctionBegin;
35: PetscCall(PetscDeviceContextGetDeviceType(globalContext, &dtype));
36: PetscCall(PetscInfo(globalContext, "Destroying global PetscDeviceContext with device type %s\n", PetscDeviceTypes[dtype]));
37: PetscCall(PetscDeviceContextDestroy(&globalContext));
38: rootDeviceType = PETSC_DEVICE_CONTEXT_DEFAULT_DEVICE_TYPE;
39: rootStreamType = PETSC_DEVICE_CONTEXT_DEFAULT_STREAM_TYPE;
40: PetscFunctionReturn(PETSC_SUCCESS);
41: };
43: /* this exists purely as a valid device check. */
44: PetscCall(PetscDeviceInitializePackage());
45: PetscCall(PetscRegisterFinalize(std::move(finalizer)));
46: PetscCall(PetscDeviceContextCreate(&globalContext));
47: PetscCall(PetscInfo(globalContext, "Initializing global PetscDeviceContext with device type %s\n", PetscDeviceTypes[dtype]));
48: pobj = PetscObjectCast(globalContext);
49: PetscCall(PetscObjectSetName(pobj, "global root"));
50: PetscCall(PetscObjectSetOptionsPrefix(pobj, "root_"));
51: PetscCall(PetscDeviceContextSetStreamType(globalContext, rootStreamType));
52: PetscCall(PetscDeviceContextSetDefaultDeviceForType_Internal(globalContext, dtype));
53: PetscCall(PetscDeviceContextSetUp(globalContext));
54: }
55: PetscFunctionReturn(PETSC_SUCCESS);
56: }
58: /*@C
59: PetscDeviceContextGetCurrentContext - Get the current active `PetscDeviceContext`
61: Not Collective
63: Output Parameter:
64: . dctx - The `PetscDeviceContext`
66: Notes:
67: The user generally should not destroy contexts retrieved with this routine unless they
68: themselves have created them. There exists no protection against destroying the root
69: context.
71: Developer Notes:
72: Unless the user has set their own, this routine creates the "root" context the first time it
73: is called, registering its destructor to `PetscFinalize()`.
75: Level: beginner
77: .seealso: `PetscDeviceContextSetCurrentContext()`, `PetscDeviceContextFork()`,
78: `PetscDeviceContextJoin()`, `PetscDeviceContextCreate()`
79: @*/
80: PetscErrorCode PetscDeviceContextGetCurrentContext(PetscDeviceContext *dctx)
81: {
82: PetscFunctionBegin;
83: PetscAssertPointer(dctx, 1);
84: PetscCall(PetscDeviceContextSetupGlobalContext_Private());
85: /* while the static analyzer can find global variables, it will throw a warning about not
86: * being able to connect this back to the function arguments */
88: *dctx = globalContext;
89: PetscFunctionReturn(PETSC_SUCCESS);
90: }
92: /*@C
93: PetscDeviceContextSetCurrentContext - Set the current active `PetscDeviceContext`
95: Not Collective
97: Input Parameter:
98: . dctx - The `PetscDeviceContext`
100: Notes:
101: This routine can be used to set the defacto "root" `PetscDeviceContext` to a user-defined
102: implementation by calling this routine immediately after `PetscInitialize()` and ensuring that
103: `PetscDevice` is not greedily initialized. In this case the user is responsible for destroying
104: their `PetscDeviceContext` before `PetscFinalize()` returns.
106: The old context is not stored in any way by this routine; if one is overriding a context that
107: they themselves do not control, one should take care to temporarily store it by calling
108: `PetscDeviceContextGetCurrentContext()` before calling this routine.
110: Level: beginner
112: .seealso: `PetscDeviceContextGetCurrentContext()`, `PetscDeviceContextFork()`,
113: `PetscDeviceContextJoin()`, `PetscDeviceContextCreate()`
114: @*/
115: PetscErrorCode PetscDeviceContextSetCurrentContext(PetscDeviceContext dctx)
116: {
117: PetscDeviceType dtype;
119: PetscFunctionBegin;
120: PetscCall(PetscDeviceContextGetOptionalNullContext_Internal(&dctx));
121: PetscAssert(dctx->setup, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "PetscDeviceContext %" PetscInt64_FMT " must be set up before being set as global context", PetscObjectCast(dctx)->id);
122: PetscCall(PetscDeviceContextGetDeviceType(dctx, &dtype));
123: PetscCall(PetscDeviceSetDefaultDeviceType(dtype));
124: globalContext = dctx;
125: PetscCall(PetscInfo(dctx, "Set global PetscDeviceContext id %" PetscInt64_FMT "\n", PetscObjectCast(dctx)->id));
126: PetscFunctionReturn(PETSC_SUCCESS);
127: }