10e6b6b59SJacob Faibussowitsch #include "petscdevice_interface_internal.hpp" /*I <petscdevice.h> I*/ 2*57e69c35SJunchao Zhang #include <petscdevice_cupm.h> 30e6b6b59SJacob Faibussowitsch 40e6b6b59SJacob Faibussowitsch static auto rootDeviceType = PETSC_DEVICE_CONTEXT_DEFAULT_DEVICE_TYPE; 50e6b6b59SJacob Faibussowitsch static auto rootStreamType = PETSC_DEVICE_CONTEXT_DEFAULT_STREAM_TYPE; 60e6b6b59SJacob Faibussowitsch static PetscDeviceContext globalContext = nullptr; 70e6b6b59SJacob Faibussowitsch 80e6b6b59SJacob Faibussowitsch /* when PetsDevice initializes PetscDeviceContext eagerly the type of device created should 9da81f932SPierre Jolivet * match whatever device is eagerly initialized */ 10d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDeviceContextSetRootDeviceType_Internal(PetscDeviceType type) 11d71ae5a4SJacob Faibussowitsch { 120e6b6b59SJacob Faibussowitsch PetscFunctionBegin; 130e6b6b59SJacob Faibussowitsch PetscValidDeviceType(type, 1); 140e6b6b59SJacob Faibussowitsch rootDeviceType = type; 153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 160e6b6b59SJacob Faibussowitsch } 170e6b6b59SJacob Faibussowitsch 18d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDeviceContextSetRootStreamType_Internal(PetscStreamType type) 19d71ae5a4SJacob Faibussowitsch { 200e6b6b59SJacob Faibussowitsch PetscFunctionBegin; 210e6b6b59SJacob Faibussowitsch PetscValidStreamType(type, 1); 220e6b6b59SJacob Faibussowitsch rootStreamType = type; 233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 240e6b6b59SJacob Faibussowitsch } 250e6b6b59SJacob Faibussowitsch 26*57e69c35SJunchao Zhang static inline PetscErrorCode PetscSetDefaultCUPMStreamFromDeviceContext(PetscDeviceContext dctx, PetscDeviceType dtype) 27*57e69c35SJunchao Zhang { 28*57e69c35SJunchao Zhang PetscFunctionBegin; 29*57e69c35SJunchao Zhang #if PetscDefined(HAVE_CUDA) 30*57e69c35SJunchao Zhang if (dtype == PETSC_DEVICE_CUDA) { 31*57e69c35SJunchao Zhang void *handle; 32*57e69c35SJunchao Zhang 33*57e69c35SJunchao Zhang PetscCall(PetscDeviceContextGetStreamHandle_Internal(dctx, &handle)); 34*57e69c35SJunchao Zhang PetscDefaultCudaStream = *static_cast<cudaStream_t *>(handle); 35*57e69c35SJunchao Zhang } 36*57e69c35SJunchao Zhang #endif 37*57e69c35SJunchao Zhang #if PetscDefined(HAVE_HIP) 38*57e69c35SJunchao Zhang if (dtype == PETSC_DEVICE_HIP) { 39*57e69c35SJunchao Zhang void *handle; 40*57e69c35SJunchao Zhang 41*57e69c35SJunchao Zhang PetscCall(PetscDeviceContextGetStreamHandle_Internal(dctx, &handle)); 42*57e69c35SJunchao Zhang PetscDefaultHipStream = *static_cast<hipStream_t *>(handle); 43*57e69c35SJunchao Zhang } 44*57e69c35SJunchao Zhang #endif 45*57e69c35SJunchao Zhang PetscFunctionReturn(PETSC_SUCCESS); 46*57e69c35SJunchao Zhang } 47*57e69c35SJunchao Zhang 48d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscDeviceContextSetupGlobalContext_Private() noexcept 49d71ae5a4SJacob Faibussowitsch { 500e6b6b59SJacob Faibussowitsch PetscFunctionBegin; 510e6b6b59SJacob Faibussowitsch if (PetscUnlikely(!globalContext)) { 520e6b6b59SJacob Faibussowitsch PetscObject pobj; 530e6b6b59SJacob Faibussowitsch const auto dtype = rootDeviceType; 540e6b6b59SJacob Faibussowitsch const auto finalizer = [] { 550e6b6b59SJacob Faibussowitsch PetscDeviceType dtype; 560e6b6b59SJacob Faibussowitsch 570e6b6b59SJacob Faibussowitsch PetscFunctionBegin; 580e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextGetDeviceType(globalContext, &dtype)); 590e6b6b59SJacob Faibussowitsch PetscCall(PetscInfo(globalContext, "Destroying global PetscDeviceContext with device type %s\n", PetscDeviceTypes[dtype])); 600e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextDestroy(&globalContext)); 610e6b6b59SJacob Faibussowitsch rootDeviceType = PETSC_DEVICE_CONTEXT_DEFAULT_DEVICE_TYPE; 620e6b6b59SJacob Faibussowitsch rootStreamType = PETSC_DEVICE_CONTEXT_DEFAULT_STREAM_TYPE; 633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 640e6b6b59SJacob Faibussowitsch }; 650e6b6b59SJacob Faibussowitsch 660e6b6b59SJacob Faibussowitsch /* this exists purely as a valid device check. */ 670e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceInitializePackage()); 680e6b6b59SJacob Faibussowitsch PetscCall(PetscRegisterFinalize(std::move(finalizer))); 690e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextCreate(&globalContext)); 700e6b6b59SJacob Faibussowitsch PetscCall(PetscInfo(globalContext, "Initializing global PetscDeviceContext with device type %s\n", PetscDeviceTypes[dtype])); 710e6b6b59SJacob Faibussowitsch pobj = PetscObjectCast(globalContext); 720e6b6b59SJacob Faibussowitsch PetscCall(PetscObjectSetName(pobj, "global root")); 730e6b6b59SJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix(pobj, "root_")); 740e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextSetStreamType(globalContext, rootStreamType)); 750e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextSetDefaultDeviceForType_Internal(globalContext, dtype)); 760e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextSetUp(globalContext)); 77*57e69c35SJunchao Zhang PetscCall(PetscSetDefaultCUPMStreamFromDeviceContext(globalContext, dtype)); 780e6b6b59SJacob Faibussowitsch } 793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 800e6b6b59SJacob Faibussowitsch } 810e6b6b59SJacob Faibussowitsch 820e6b6b59SJacob Faibussowitsch /*@C 830e6b6b59SJacob Faibussowitsch PetscDeviceContextGetCurrentContext - Get the current active `PetscDeviceContext` 840e6b6b59SJacob Faibussowitsch 850e6b6b59SJacob Faibussowitsch Not Collective 860e6b6b59SJacob Faibussowitsch 870e6b6b59SJacob Faibussowitsch Output Parameter: 880e6b6b59SJacob Faibussowitsch . dctx - The `PetscDeviceContext` 890e6b6b59SJacob Faibussowitsch 900e6b6b59SJacob Faibussowitsch Notes: 910e6b6b59SJacob Faibussowitsch The user generally should not destroy contexts retrieved with this routine unless they 920e6b6b59SJacob Faibussowitsch themselves have created them. There exists no protection against destroying the root 930e6b6b59SJacob Faibussowitsch context. 940e6b6b59SJacob Faibussowitsch 950e6b6b59SJacob Faibussowitsch Developer Notes: 960e6b6b59SJacob Faibussowitsch Unless the user has set their own, this routine creates the "root" context the first time it 970e6b6b59SJacob Faibussowitsch is called, registering its destructor to `PetscFinalize()`. 980e6b6b59SJacob Faibussowitsch 990e6b6b59SJacob Faibussowitsch Level: beginner 1000e6b6b59SJacob Faibussowitsch 1010e6b6b59SJacob Faibussowitsch .seealso: `PetscDeviceContextSetCurrentContext()`, `PetscDeviceContextFork()`, 1020e6b6b59SJacob Faibussowitsch `PetscDeviceContextJoin()`, `PetscDeviceContextCreate()` 1030e6b6b59SJacob Faibussowitsch @*/ 104d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDeviceContextGetCurrentContext(PetscDeviceContext *dctx) 105d71ae5a4SJacob Faibussowitsch { 1060e6b6b59SJacob Faibussowitsch PetscFunctionBegin; 1074f572ea9SToby Isaac PetscAssertPointer(dctx, 1); 1080e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextSetupGlobalContext_Private()); 1090e6b6b59SJacob Faibussowitsch /* while the static analyzer can find global variables, it will throw a warning about not 1100e6b6b59SJacob Faibussowitsch * being able to connect this back to the function arguments */ 1110e6b6b59SJacob Faibussowitsch PetscDisableStaticAnalyzerForExpressionUnderstandingThatThisIsDangerousAndBugprone(PetscValidDeviceContext(globalContext, -1)); 1120e6b6b59SJacob Faibussowitsch *dctx = globalContext; 1133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1140e6b6b59SJacob Faibussowitsch } 1150e6b6b59SJacob Faibussowitsch 1160e6b6b59SJacob Faibussowitsch /*@C 1170e6b6b59SJacob Faibussowitsch PetscDeviceContextSetCurrentContext - Set the current active `PetscDeviceContext` 1180e6b6b59SJacob Faibussowitsch 1190e6b6b59SJacob Faibussowitsch Not Collective 1200e6b6b59SJacob Faibussowitsch 1210e6b6b59SJacob Faibussowitsch Input Parameter: 1220e6b6b59SJacob Faibussowitsch . dctx - The `PetscDeviceContext` 1230e6b6b59SJacob Faibussowitsch 1240e6b6b59SJacob Faibussowitsch Notes: 1250e6b6b59SJacob Faibussowitsch This routine can be used to set the defacto "root" `PetscDeviceContext` to a user-defined 1260e6b6b59SJacob Faibussowitsch implementation by calling this routine immediately after `PetscInitialize()` and ensuring that 127da81f932SPierre Jolivet `PetscDevice` is not greedily initialized. In this case the user is responsible for destroying 1280e6b6b59SJacob Faibussowitsch their `PetscDeviceContext` before `PetscFinalize()` returns. 1290e6b6b59SJacob Faibussowitsch 1300e6b6b59SJacob Faibussowitsch The old context is not stored in any way by this routine; if one is overriding a context that 1310e6b6b59SJacob Faibussowitsch they themselves do not control, one should take care to temporarily store it by calling 1320e6b6b59SJacob Faibussowitsch `PetscDeviceContextGetCurrentContext()` before calling this routine. 1330e6b6b59SJacob Faibussowitsch 1340e6b6b59SJacob Faibussowitsch Level: beginner 1350e6b6b59SJacob Faibussowitsch 1360e6b6b59SJacob Faibussowitsch .seealso: `PetscDeviceContextGetCurrentContext()`, `PetscDeviceContextFork()`, 1370e6b6b59SJacob Faibussowitsch `PetscDeviceContextJoin()`, `PetscDeviceContextCreate()` 1380e6b6b59SJacob Faibussowitsch @*/ 139d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDeviceContextSetCurrentContext(PetscDeviceContext dctx) 140d71ae5a4SJacob Faibussowitsch { 1410e6b6b59SJacob Faibussowitsch PetscDeviceType dtype; 1420e6b6b59SJacob Faibussowitsch 1430e6b6b59SJacob Faibussowitsch PetscFunctionBegin; 1440e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextGetOptionalNullContext_Internal(&dctx)); 1450e6b6b59SJacob 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); 1460e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextGetDeviceType(dctx, &dtype)); 1470e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceSetDefaultDeviceType(dtype)); 1480e6b6b59SJacob Faibussowitsch globalContext = dctx; 1490e6b6b59SJacob Faibussowitsch PetscCall(PetscInfo(dctx, "Set global PetscDeviceContext id %" PetscInt64_FMT "\n", PetscObjectCast(dctx)->id)); 150*57e69c35SJunchao Zhang PetscCall(PetscSetDefaultCUPMStreamFromDeviceContext(globalContext, dtype)); 1513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1520e6b6b59SJacob Faibussowitsch } 153