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