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