Actual source code: global_dcontext.cxx

  1: #include "petscdevice_interface_internal.hpp" /*I <petscdevice.h> I*/
  2: #include <petscdevice_cupm.h>

  4: static auto               rootDeviceType = PETSC_DEVICE_CONTEXT_DEFAULT_DEVICE_TYPE;
  5: static auto               rootStreamType = PETSC_DEVICE_CONTEXT_DEFAULT_STREAM_TYPE;
  6: static PetscDeviceContext globalContext  = nullptr;

  8: /* when PetsDevice initializes PetscDeviceContext eagerly the type of device created should
  9:  * match whatever device is eagerly initialized */
 10: PetscErrorCode PetscDeviceContextSetRootDeviceType_Internal(PetscDeviceType type)
 11: {
 12:   PetscFunctionBegin;
 14:   rootDeviceType = type;
 15:   PetscFunctionReturn(PETSC_SUCCESS);
 16: }

 18: PetscErrorCode PetscDeviceContextSetRootStreamType_Internal(PetscStreamType type)
 19: {
 20:   PetscFunctionBegin;
 22:   rootStreamType = type;
 23:   PetscFunctionReturn(PETSC_SUCCESS);
 24: }

 26: static inline PetscErrorCode PetscSetDefaultCUPMStreamFromDeviceContext(PetscDeviceContext dctx, PetscDeviceType dtype)
 27: {
 28:   PetscFunctionBegin;
 29: #if PetscDefined(HAVE_CUDA)
 30:   if (dtype == PETSC_DEVICE_CUDA) {
 31:     void *handle;

 33:     PetscCall(PetscDeviceContextGetStreamHandle_Internal(dctx, &handle));
 34:     PetscDefaultCudaStream = *static_cast<cudaStream_t *>(handle);
 35:   }
 36: #endif
 37: #if PetscDefined(HAVE_HIP)
 38:   if (dtype == PETSC_DEVICE_HIP) {
 39:     void *handle;

 41:     PetscCall(PetscDeviceContextGetStreamHandle_Internal(dctx, &handle));
 42:     PetscDefaultHipStream = *static_cast<hipStream_t *>(handle);
 43:   }
 44: #endif
 45: #if !PetscDefined(HAVE_CUDA) && !PetscDefined(HAVE_HIP)
 46:   (void)dctx, (void)dtype;
 47: #endif
 48:   PetscFunctionReturn(PETSC_SUCCESS);
 49: }

 51: static PetscErrorCode PetscDeviceContextSetupGlobalContext_Private() noexcept
 52: {
 53:   PetscFunctionBegin;
 54:   if (PetscUnlikely(!globalContext)) {
 55:     PetscObject pobj;
 56:     const auto  dtype     = rootDeviceType;
 57:     const auto  finalizer = [] {
 58:       PetscDeviceType dtype;

 60:       PetscFunctionBegin;
 61:       PetscCall(PetscDeviceContextGetDeviceType(globalContext, &dtype));
 62:       PetscCall(PetscInfo(globalContext, "Destroying global PetscDeviceContext with device type %s\n", PetscDeviceTypes[dtype]));
 63:       PetscCall(PetscDeviceContextDestroy(&globalContext));
 64:       rootDeviceType = PETSC_DEVICE_CONTEXT_DEFAULT_DEVICE_TYPE;
 65:       rootStreamType = PETSC_DEVICE_CONTEXT_DEFAULT_STREAM_TYPE;
 66:       PetscFunctionReturn(PETSC_SUCCESS);
 67:     };

 69:     /* this exists purely as a valid device check. */
 70:     PetscCall(PetscDeviceInitializePackage());
 71:     PetscCall(PetscRegisterFinalize(std::move(finalizer)));
 72:     PetscCall(PetscDeviceContextCreate(&globalContext));
 73:     PetscCall(PetscInfo(globalContext, "Initializing global PetscDeviceContext with device type %s\n", PetscDeviceTypes[dtype]));
 74:     pobj = PetscObjectCast(globalContext);
 75:     PetscCall(PetscObjectSetName(pobj, "global root"));
 76:     PetscCall(PetscObjectSetOptionsPrefix(pobj, "root_"));
 77:     PetscCall(PetscDeviceContextSetStreamType(globalContext, rootStreamType));
 78:     PetscCall(PetscDeviceContextSetDefaultDeviceForType_Internal(globalContext, dtype));
 79:     PetscCall(PetscDeviceContextSetUp(globalContext));
 80:     PetscCall(PetscSetDefaultCUPMStreamFromDeviceContext(globalContext, dtype));
 81:   }
 82:   PetscFunctionReturn(PETSC_SUCCESS);
 83: }

 85: /*@C
 86:   PetscDeviceContextGetCurrentContext - Get the current active `PetscDeviceContext`

 88:   Not Collective

 90:   Output Parameter:
 91: . dctx - The `PetscDeviceContext`

 93:   Notes:
 94:   The user generally should not destroy contexts retrieved with this routine unless they
 95:   themselves have created them. There exists no protection against destroying the root
 96:   context.

 98:   Developer Notes:
 99:   Unless the user has set their own, this routine creates the "root" context the first time it
100:   is called, registering its destructor to `PetscFinalize()`.

102:   Level: beginner

104: .seealso: `PetscDeviceContextSetCurrentContext()`, `PetscDeviceContextFork()`,
105:           `PetscDeviceContextJoin()`, `PetscDeviceContextCreate()`
106: @*/
107: PetscErrorCode PetscDeviceContextGetCurrentContext(PetscDeviceContext *dctx)
108: {
109:   PetscFunctionBegin;
110:   PetscAssertPointer(dctx, 1);
111:   PetscCall(PetscDeviceContextSetupGlobalContext_Private());
112:   /* while the static analyzer can find global variables, it will throw a warning about not
113:    * being able to connect this back to the function arguments */
115:   *dctx = globalContext;
116:   PetscFunctionReturn(PETSC_SUCCESS);
117: }

119: /*@C
120:   PetscDeviceContextSetCurrentContext - Set the current active `PetscDeviceContext`

122:   Not Collective

124:   Input Parameter:
125: . dctx - The `PetscDeviceContext`

127:   Notes:
128:   This routine can be used to set the defacto "root" `PetscDeviceContext` to a user-defined
129:   implementation by calling this routine immediately after `PetscInitialize()` and ensuring that
130:   `PetscDevice` is not greedily initialized. In this case the user is responsible for destroying
131:   their `PetscDeviceContext` before `PetscFinalize()` returns.

133:   The old context is not stored in any way by this routine; if one is overriding a context that
134:   they themselves do not control, one should take care to temporarily store it by calling
135:   `PetscDeviceContextGetCurrentContext()` before calling this routine.

137:   Level: beginner

139: .seealso: `PetscDeviceContextGetCurrentContext()`, `PetscDeviceContextFork()`,
140:           `PetscDeviceContextJoin()`, `PetscDeviceContextCreate()`
141: @*/
142: PetscErrorCode PetscDeviceContextSetCurrentContext(PetscDeviceContext dctx)
143: {
144:   PetscDeviceType dtype;

146:   PetscFunctionBegin;
147:   PetscCall(PetscDeviceContextGetOptionalNullContext_Internal(&dctx));
148:   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);
149:   PetscCall(PetscDeviceContextGetDeviceType(dctx, &dtype));
150:   PetscCall(PetscDeviceSetDefaultDeviceType(dtype));
151:   globalContext = dctx;
152:   PetscCall(PetscInfo(dctx, "Set global PetscDeviceContext id %" PetscInt64_FMT "\n", PetscObjectCast(dctx)->id));
153:   PetscCall(PetscSetDefaultCUPMStreamFromDeviceContext(globalContext, dtype));
154:   PetscFunctionReturn(PETSC_SUCCESS);
155: }