10e6b6b59SJacob Faibussowitsch #include "petscdevice_interface_internal.hpp" /*I <petscdevice.h> I*/
257e69c35SJunchao 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
8*54c05997SPierre Jolivet /* when PetscDevice initializes PetscDeviceContext eagerly the type of device created should
9da81f932SPierre Jolivet * match whatever device is eagerly initialized */
PetscDeviceContextSetRootDeviceType_Internal(PetscDeviceType type)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
PetscDeviceContextSetRootStreamType_Internal(PetscStreamType type)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
PetscSetDefaultCUPMStreamFromDeviceContext(PetscDeviceContext dctx,PetscDeviceType dtype)2657e69c35SJunchao Zhang static inline PetscErrorCode PetscSetDefaultCUPMStreamFromDeviceContext(PetscDeviceContext dctx, PetscDeviceType dtype)
2757e69c35SJunchao Zhang {
2857e69c35SJunchao Zhang PetscFunctionBegin;
2957e69c35SJunchao Zhang #if PetscDefined(HAVE_CUDA)
3057e69c35SJunchao Zhang if (dtype == PETSC_DEVICE_CUDA) {
3157e69c35SJunchao Zhang void *handle;
3257e69c35SJunchao Zhang
3357e69c35SJunchao Zhang PetscCall(PetscDeviceContextGetStreamHandle_Internal(dctx, &handle));
3457e69c35SJunchao Zhang PetscDefaultCudaStream = *static_cast<cudaStream_t *>(handle);
3557e69c35SJunchao Zhang }
3657e69c35SJunchao Zhang #endif
3757e69c35SJunchao Zhang #if PetscDefined(HAVE_HIP)
3857e69c35SJunchao Zhang if (dtype == PETSC_DEVICE_HIP) {
3957e69c35SJunchao Zhang void *handle;
4057e69c35SJunchao Zhang
4157e69c35SJunchao Zhang PetscCall(PetscDeviceContextGetStreamHandle_Internal(dctx, &handle));
4257e69c35SJunchao Zhang PetscDefaultHipStream = *static_cast<hipStream_t *>(handle);
4357e69c35SJunchao Zhang }
4457e69c35SJunchao Zhang #endif
45e1d53d03SPierre Jolivet #if !PetscDefined(HAVE_CUDA) && !PetscDefined(HAVE_HIP)
46e1d53d03SPierre Jolivet (void)dctx, (void)dtype;
47e1d53d03SPierre Jolivet #endif
4857e69c35SJunchao Zhang PetscFunctionReturn(PETSC_SUCCESS);
4957e69c35SJunchao Zhang }
5057e69c35SJunchao Zhang
PetscDeviceContextSetupGlobalContext_Private()51d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscDeviceContextSetupGlobalContext_Private() noexcept
52d71ae5a4SJacob Faibussowitsch {
530e6b6b59SJacob Faibussowitsch PetscFunctionBegin;
540e6b6b59SJacob Faibussowitsch if (PetscUnlikely(!globalContext)) {
550e6b6b59SJacob Faibussowitsch PetscObject pobj;
560e6b6b59SJacob Faibussowitsch const auto dtype = rootDeviceType;
570e6b6b59SJacob Faibussowitsch const auto finalizer = [] {
580e6b6b59SJacob Faibussowitsch PetscDeviceType dtype;
590e6b6b59SJacob Faibussowitsch
600e6b6b59SJacob Faibussowitsch PetscFunctionBegin;
610e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextGetDeviceType(globalContext, &dtype));
620e6b6b59SJacob Faibussowitsch PetscCall(PetscInfo(globalContext, "Destroying global PetscDeviceContext with device type %s\n", PetscDeviceTypes[dtype]));
630e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextDestroy(&globalContext));
640e6b6b59SJacob Faibussowitsch rootDeviceType = PETSC_DEVICE_CONTEXT_DEFAULT_DEVICE_TYPE;
650e6b6b59SJacob Faibussowitsch rootStreamType = PETSC_DEVICE_CONTEXT_DEFAULT_STREAM_TYPE;
663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
670e6b6b59SJacob Faibussowitsch };
680e6b6b59SJacob Faibussowitsch
690e6b6b59SJacob Faibussowitsch /* this exists purely as a valid device check. */
700e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceInitializePackage());
710e6b6b59SJacob Faibussowitsch PetscCall(PetscRegisterFinalize(std::move(finalizer)));
720e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextCreate(&globalContext));
730e6b6b59SJacob Faibussowitsch PetscCall(PetscInfo(globalContext, "Initializing global PetscDeviceContext with device type %s\n", PetscDeviceTypes[dtype]));
740e6b6b59SJacob Faibussowitsch pobj = PetscObjectCast(globalContext);
750e6b6b59SJacob Faibussowitsch PetscCall(PetscObjectSetName(pobj, "global root"));
760e6b6b59SJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix(pobj, "root_"));
770e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextSetStreamType(globalContext, rootStreamType));
780e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextSetDefaultDeviceForType_Internal(globalContext, dtype));
790e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextSetUp(globalContext));
8057e69c35SJunchao Zhang PetscCall(PetscSetDefaultCUPMStreamFromDeviceContext(globalContext, dtype));
810e6b6b59SJacob Faibussowitsch }
823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
830e6b6b59SJacob Faibussowitsch }
840e6b6b59SJacob Faibussowitsch
850e6b6b59SJacob Faibussowitsch /*@C
860e6b6b59SJacob Faibussowitsch PetscDeviceContextGetCurrentContext - Get the current active `PetscDeviceContext`
870e6b6b59SJacob Faibussowitsch
880e6b6b59SJacob Faibussowitsch Not Collective
890e6b6b59SJacob Faibussowitsch
900e6b6b59SJacob Faibussowitsch Output Parameter:
910e6b6b59SJacob Faibussowitsch . dctx - The `PetscDeviceContext`
920e6b6b59SJacob Faibussowitsch
930e6b6b59SJacob Faibussowitsch Notes:
940e6b6b59SJacob Faibussowitsch The user generally should not destroy contexts retrieved with this routine unless they
950e6b6b59SJacob Faibussowitsch themselves have created them. There exists no protection against destroying the root
960e6b6b59SJacob Faibussowitsch context.
970e6b6b59SJacob Faibussowitsch
980e6b6b59SJacob Faibussowitsch Developer Notes:
990e6b6b59SJacob Faibussowitsch Unless the user has set their own, this routine creates the "root" context the first time it
1000e6b6b59SJacob Faibussowitsch is called, registering its destructor to `PetscFinalize()`.
1010e6b6b59SJacob Faibussowitsch
1020e6b6b59SJacob Faibussowitsch Level: beginner
1030e6b6b59SJacob Faibussowitsch
1040e6b6b59SJacob Faibussowitsch .seealso: `PetscDeviceContextSetCurrentContext()`, `PetscDeviceContextFork()`,
1050e6b6b59SJacob Faibussowitsch `PetscDeviceContextJoin()`, `PetscDeviceContextCreate()`
1060e6b6b59SJacob Faibussowitsch @*/
PetscDeviceContextGetCurrentContext(PetscDeviceContext * dctx)107d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDeviceContextGetCurrentContext(PetscDeviceContext *dctx)
108d71ae5a4SJacob Faibussowitsch {
1090e6b6b59SJacob Faibussowitsch PetscFunctionBegin;
1104f572ea9SToby Isaac PetscAssertPointer(dctx, 1);
1110e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextSetupGlobalContext_Private());
1120e6b6b59SJacob Faibussowitsch /* while the static analyzer can find global variables, it will throw a warning about not
1130e6b6b59SJacob Faibussowitsch * being able to connect this back to the function arguments */
1140e6b6b59SJacob Faibussowitsch PetscDisableStaticAnalyzerForExpressionUnderstandingThatThisIsDangerousAndBugprone(PetscValidDeviceContext(globalContext, -1));
1150e6b6b59SJacob Faibussowitsch *dctx = globalContext;
1163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1170e6b6b59SJacob Faibussowitsch }
1180e6b6b59SJacob Faibussowitsch
1190e6b6b59SJacob Faibussowitsch /*@C
1200e6b6b59SJacob Faibussowitsch PetscDeviceContextSetCurrentContext - Set the current active `PetscDeviceContext`
1210e6b6b59SJacob Faibussowitsch
1220e6b6b59SJacob Faibussowitsch Not Collective
1230e6b6b59SJacob Faibussowitsch
1240e6b6b59SJacob Faibussowitsch Input Parameter:
1250e6b6b59SJacob Faibussowitsch . dctx - The `PetscDeviceContext`
1260e6b6b59SJacob Faibussowitsch
1270e6b6b59SJacob Faibussowitsch Notes:
1280e6b6b59SJacob Faibussowitsch This routine can be used to set the defacto "root" `PetscDeviceContext` to a user-defined
1290e6b6b59SJacob Faibussowitsch implementation by calling this routine immediately after `PetscInitialize()` and ensuring that
130da81f932SPierre Jolivet `PetscDevice` is not greedily initialized. In this case the user is responsible for destroying
1310e6b6b59SJacob Faibussowitsch their `PetscDeviceContext` before `PetscFinalize()` returns.
1320e6b6b59SJacob Faibussowitsch
1330e6b6b59SJacob Faibussowitsch The old context is not stored in any way by this routine; if one is overriding a context that
1340e6b6b59SJacob Faibussowitsch they themselves do not control, one should take care to temporarily store it by calling
1350e6b6b59SJacob Faibussowitsch `PetscDeviceContextGetCurrentContext()` before calling this routine.
1360e6b6b59SJacob Faibussowitsch
1370e6b6b59SJacob Faibussowitsch Level: beginner
1380e6b6b59SJacob Faibussowitsch
1390e6b6b59SJacob Faibussowitsch .seealso: `PetscDeviceContextGetCurrentContext()`, `PetscDeviceContextFork()`,
1400e6b6b59SJacob Faibussowitsch `PetscDeviceContextJoin()`, `PetscDeviceContextCreate()`
1410e6b6b59SJacob Faibussowitsch @*/
PetscDeviceContextSetCurrentContext(PetscDeviceContext dctx)142d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDeviceContextSetCurrentContext(PetscDeviceContext dctx)
143d71ae5a4SJacob Faibussowitsch {
1440e6b6b59SJacob Faibussowitsch PetscDeviceType dtype;
1450e6b6b59SJacob Faibussowitsch
1460e6b6b59SJacob Faibussowitsch PetscFunctionBegin;
1470e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextGetOptionalNullContext_Internal(&dctx));
1480e6b6b59SJacob 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);
1490e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextGetDeviceType(dctx, &dtype));
1500e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceSetDefaultDeviceType(dtype));
1510e6b6b59SJacob Faibussowitsch globalContext = dctx;
1520e6b6b59SJacob Faibussowitsch PetscCall(PetscInfo(dctx, "Set global PetscDeviceContext id %" PetscInt64_FMT "\n", PetscObjectCast(dctx)->id));
15357e69c35SJunchao Zhang PetscCall(PetscSetDefaultCUPMStreamFromDeviceContext(globalContext, dtype));
1543ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1550e6b6b59SJacob Faibussowitsch }
156