xref: /petsc/src/sys/objects/device/interface/global_dcontext.cxx (revision da81f9329be15cc55f054c8a00978087195c9247)
10e6b6b59SJacob Faibussowitsch #include "petscdevice_interface_internal.hpp" /*I <petscdevice.h> I*/
20e6b6b59SJacob Faibussowitsch 
30e6b6b59SJacob Faibussowitsch static auto               rootDeviceType = PETSC_DEVICE_CONTEXT_DEFAULT_DEVICE_TYPE;
40e6b6b59SJacob Faibussowitsch static auto               rootStreamType = PETSC_DEVICE_CONTEXT_DEFAULT_STREAM_TYPE;
50e6b6b59SJacob Faibussowitsch static PetscDeviceContext globalContext  = nullptr;
60e6b6b59SJacob Faibussowitsch 
70e6b6b59SJacob Faibussowitsch /* when PetsDevice initializes PetscDeviceContext eagerly the type of device created should
8*da81f932SPierre Jolivet  * match whatever device is eagerly initialized */
9d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDeviceContextSetRootDeviceType_Internal(PetscDeviceType type)
10d71ae5a4SJacob Faibussowitsch {
110e6b6b59SJacob Faibussowitsch   PetscFunctionBegin;
120e6b6b59SJacob Faibussowitsch   PetscValidDeviceType(type, 1);
130e6b6b59SJacob Faibussowitsch   rootDeviceType = type;
140e6b6b59SJacob Faibussowitsch   PetscFunctionReturn(0);
150e6b6b59SJacob Faibussowitsch }
160e6b6b59SJacob Faibussowitsch 
17d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDeviceContextSetRootStreamType_Internal(PetscStreamType type)
18d71ae5a4SJacob Faibussowitsch {
190e6b6b59SJacob Faibussowitsch   PetscFunctionBegin;
200e6b6b59SJacob Faibussowitsch   PetscValidStreamType(type, 1);
210e6b6b59SJacob Faibussowitsch   rootStreamType = type;
220e6b6b59SJacob Faibussowitsch   PetscFunctionReturn(0);
230e6b6b59SJacob Faibussowitsch }
240e6b6b59SJacob Faibussowitsch 
25d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscDeviceContextSetupGlobalContext_Private() noexcept
26d71ae5a4SJacob Faibussowitsch {
270e6b6b59SJacob Faibussowitsch   PetscFunctionBegin;
280e6b6b59SJacob Faibussowitsch   if (PetscUnlikely(!globalContext)) {
290e6b6b59SJacob Faibussowitsch     PetscObject pobj;
300e6b6b59SJacob Faibussowitsch     const auto  dtype     = rootDeviceType;
310e6b6b59SJacob Faibussowitsch     const auto  finalizer = [] {
320e6b6b59SJacob Faibussowitsch       PetscDeviceType dtype;
330e6b6b59SJacob Faibussowitsch 
340e6b6b59SJacob Faibussowitsch       PetscFunctionBegin;
350e6b6b59SJacob Faibussowitsch       PetscCall(PetscDeviceContextGetDeviceType(globalContext, &dtype));
360e6b6b59SJacob Faibussowitsch       PetscCall(PetscInfo(globalContext, "Destroying global PetscDeviceContext with device type %s\n", PetscDeviceTypes[dtype]));
370e6b6b59SJacob Faibussowitsch       PetscCall(PetscDeviceContextDestroy(&globalContext));
380e6b6b59SJacob Faibussowitsch       rootDeviceType = PETSC_DEVICE_CONTEXT_DEFAULT_DEVICE_TYPE;
390e6b6b59SJacob Faibussowitsch       rootStreamType = PETSC_DEVICE_CONTEXT_DEFAULT_STREAM_TYPE;
400e6b6b59SJacob Faibussowitsch       PetscFunctionReturn(0);
410e6b6b59SJacob Faibussowitsch     };
420e6b6b59SJacob Faibussowitsch 
430e6b6b59SJacob Faibussowitsch     /* this exists purely as a valid device check. */
440e6b6b59SJacob Faibussowitsch     PetscCall(PetscDeviceInitializePackage());
450e6b6b59SJacob Faibussowitsch     PetscCall(PetscRegisterFinalize(std::move(finalizer)));
460e6b6b59SJacob Faibussowitsch     PetscCall(PetscDeviceContextCreate(&globalContext));
470e6b6b59SJacob Faibussowitsch     PetscCall(PetscInfo(globalContext, "Initializing global PetscDeviceContext with device type %s\n", PetscDeviceTypes[dtype]));
480e6b6b59SJacob Faibussowitsch     pobj = PetscObjectCast(globalContext);
490e6b6b59SJacob Faibussowitsch     PetscCall(PetscObjectSetName(pobj, "global root"));
500e6b6b59SJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix(pobj, "root_"));
510e6b6b59SJacob Faibussowitsch     PetscCall(PetscDeviceContextSetStreamType(globalContext, rootStreamType));
520e6b6b59SJacob Faibussowitsch     PetscCall(PetscDeviceContextSetDefaultDeviceForType_Internal(globalContext, dtype));
530e6b6b59SJacob Faibussowitsch     PetscCall(PetscDeviceContextSetUp(globalContext));
540e6b6b59SJacob Faibussowitsch   }
550e6b6b59SJacob Faibussowitsch   PetscFunctionReturn(0);
560e6b6b59SJacob Faibussowitsch }
570e6b6b59SJacob Faibussowitsch 
580e6b6b59SJacob Faibussowitsch /*@C
590e6b6b59SJacob Faibussowitsch   PetscDeviceContextGetCurrentContext - Get the current active `PetscDeviceContext`
600e6b6b59SJacob Faibussowitsch 
610e6b6b59SJacob Faibussowitsch   Not Collective
620e6b6b59SJacob Faibussowitsch 
630e6b6b59SJacob Faibussowitsch   Output Parameter:
640e6b6b59SJacob Faibussowitsch . dctx - The `PetscDeviceContext`
650e6b6b59SJacob Faibussowitsch 
660e6b6b59SJacob Faibussowitsch   Notes:
670e6b6b59SJacob Faibussowitsch   The user generally should not destroy contexts retrieved with this routine unless they
680e6b6b59SJacob Faibussowitsch   themselves have created them. There exists no protection against destroying the root
690e6b6b59SJacob Faibussowitsch   context.
700e6b6b59SJacob Faibussowitsch 
710e6b6b59SJacob Faibussowitsch   Developer Notes:
720e6b6b59SJacob Faibussowitsch   Unless the user has set their own, this routine creates the "root" context the first time it
730e6b6b59SJacob Faibussowitsch   is called, registering its destructor to `PetscFinalize()`.
740e6b6b59SJacob Faibussowitsch 
750e6b6b59SJacob Faibussowitsch   Level: beginner
760e6b6b59SJacob Faibussowitsch 
770e6b6b59SJacob Faibussowitsch .seealso: `PetscDeviceContextSetCurrentContext()`, `PetscDeviceContextFork()`,
780e6b6b59SJacob Faibussowitsch           `PetscDeviceContextJoin()`, `PetscDeviceContextCreate()`
790e6b6b59SJacob Faibussowitsch @*/
80d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDeviceContextGetCurrentContext(PetscDeviceContext *dctx)
81d71ae5a4SJacob Faibussowitsch {
820e6b6b59SJacob Faibussowitsch   PetscFunctionBegin;
830e6b6b59SJacob Faibussowitsch   PetscValidPointer(dctx, 1);
840e6b6b59SJacob Faibussowitsch   PetscCall(PetscDeviceContextSetupGlobalContext_Private());
850e6b6b59SJacob Faibussowitsch   /* while the static analyzer can find global variables, it will throw a warning about not
860e6b6b59SJacob Faibussowitsch    * being able to connect this back to the function arguments */
870e6b6b59SJacob Faibussowitsch   PetscDisableStaticAnalyzerForExpressionUnderstandingThatThisIsDangerousAndBugprone(PetscValidDeviceContext(globalContext, -1));
880e6b6b59SJacob Faibussowitsch   *dctx = globalContext;
890e6b6b59SJacob Faibussowitsch   PetscFunctionReturn(0);
900e6b6b59SJacob Faibussowitsch }
910e6b6b59SJacob Faibussowitsch 
920e6b6b59SJacob Faibussowitsch /*@C
930e6b6b59SJacob Faibussowitsch   PetscDeviceContextSetCurrentContext - Set the current active `PetscDeviceContext`
940e6b6b59SJacob Faibussowitsch 
950e6b6b59SJacob Faibussowitsch   Not Collective
960e6b6b59SJacob Faibussowitsch 
970e6b6b59SJacob Faibussowitsch   Input Parameter:
980e6b6b59SJacob Faibussowitsch . dctx - The `PetscDeviceContext`
990e6b6b59SJacob Faibussowitsch 
1000e6b6b59SJacob Faibussowitsch   Notes:
1010e6b6b59SJacob Faibussowitsch   This routine can be used to set the defacto "root" `PetscDeviceContext` to a user-defined
1020e6b6b59SJacob Faibussowitsch   implementation by calling this routine immediately after `PetscInitialize()` and ensuring that
103*da81f932SPierre Jolivet   `PetscDevice` is not greedily initialized. In this case the user is responsible for destroying
1040e6b6b59SJacob Faibussowitsch   their `PetscDeviceContext` before `PetscFinalize()` returns.
1050e6b6b59SJacob Faibussowitsch 
1060e6b6b59SJacob Faibussowitsch   The old context is not stored in any way by this routine; if one is overriding a context that
1070e6b6b59SJacob Faibussowitsch   they themselves do not control, one should take care to temporarily store it by calling
1080e6b6b59SJacob Faibussowitsch   `PetscDeviceContextGetCurrentContext()` before calling this routine.
1090e6b6b59SJacob Faibussowitsch 
1100e6b6b59SJacob Faibussowitsch   Level: beginner
1110e6b6b59SJacob Faibussowitsch 
1120e6b6b59SJacob Faibussowitsch .seealso: `PetscDeviceContextGetCurrentContext()`, `PetscDeviceContextFork()`,
1130e6b6b59SJacob Faibussowitsch           `PetscDeviceContextJoin()`, `PetscDeviceContextCreate()`
1140e6b6b59SJacob Faibussowitsch @*/
115d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDeviceContextSetCurrentContext(PetscDeviceContext dctx)
116d71ae5a4SJacob Faibussowitsch {
1170e6b6b59SJacob Faibussowitsch   PetscDeviceType dtype;
1180e6b6b59SJacob Faibussowitsch 
1190e6b6b59SJacob Faibussowitsch   PetscFunctionBegin;
1200e6b6b59SJacob Faibussowitsch   PetscCall(PetscDeviceContextGetOptionalNullContext_Internal(&dctx));
1210e6b6b59SJacob 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);
1220e6b6b59SJacob Faibussowitsch   PetscCall(PetscDeviceContextGetDeviceType(dctx, &dtype));
1230e6b6b59SJacob Faibussowitsch   PetscCall(PetscDeviceSetDefaultDeviceType(dtype));
1240e6b6b59SJacob Faibussowitsch   globalContext = dctx;
1250e6b6b59SJacob Faibussowitsch   PetscCall(PetscInfo(dctx, "Set global PetscDeviceContext id %" PetscInt64_FMT "\n", PetscObjectCast(dctx)->id));
1260e6b6b59SJacob Faibussowitsch   PetscFunctionReturn(0);
1270e6b6b59SJacob Faibussowitsch }
128