Actual source code: deviceimpl.h

  1: #pragma once

  3: #include <petscdevice.h>
  4: #include <petsc/private/petscimpl.h>

  6: /* logging support */
  7: PETSC_INTERN PetscLogEvent CUBLAS_HANDLE_CREATE;
  8: PETSC_INTERN PetscLogEvent CUSOLVER_HANDLE_CREATE;
  9: PETSC_INTERN PetscLogEvent HIPSOLVER_HANDLE_CREATE;
 10: PETSC_INTERN PetscLogEvent HIPBLAS_HANDLE_CREATE;

 12: PETSC_INTERN PetscLogEvent DCONTEXT_Create;
 13: PETSC_INTERN PetscLogEvent DCONTEXT_Destroy;
 14: PETSC_INTERN PetscLogEvent DCONTEXT_ChangeStream;
 15: PETSC_INTERN PetscLogEvent DCONTEXT_SetDevice;
 16: PETSC_INTERN PetscLogEvent DCONTEXT_SetUp;
 17: PETSC_INTERN PetscLogEvent DCONTEXT_Duplicate;
 18: PETSC_INTERN PetscLogEvent DCONTEXT_QueryIdle;
 19: PETSC_INTERN PetscLogEvent DCONTEXT_WaitForCtx;
 20: PETSC_INTERN PetscLogEvent DCONTEXT_Fork;
 21: PETSC_INTERN PetscLogEvent DCONTEXT_Join;
 22: PETSC_INTERN PetscLogEvent DCONTEXT_Sync;
 23: PETSC_INTERN PetscLogEvent DCONTEXT_Mark;

 25: /* type cast macros for some additional type-safety in C++ land */
 26: #if defined(__cplusplus)
 27:   #define PetscStreamTypeCast(...)     static_cast<PetscStreamType>(__VA_ARGS__)
 28:   #define PetscDeviceTypeCast(...)     static_cast<PetscDeviceType>(__VA_ARGS__)
 29:   #define PetscDeviceInitTypeCast(...) static_cast<PetscDeviceInitType>(__VA_ARGS__)
 30: #else
 31:   #define PetscStreamTypeCast(...)     ((PetscStreamType)(__VA_ARGS__))
 32:   #define PetscDeviceTypeCast(...)     ((PetscDeviceType)(__VA_ARGS__))
 33:   #define PetscDeviceInitTypeCast(...) ((PetscDeviceInitType)(__VA_ARGS__))
 34: #endif

 36: #if defined(PETSC_CLANG_STATIC_ANALYZER)
 37: template <typename T>
 39: template <typename T, typename U>
 40: extern void PetscCheckCompatibleDeviceTypes(T, int, U, int);
 41: template <typename T>
 43: template <typename T>
 45: template <typename T, typename U>
 46: extern void PetscCheckCompatibleDevices(T, int, U, int);
 47: template <typename T>
 49: template <typename T>
 51: template <typename T, typename U>
 52: extern void PetscCheckCompatibleDeviceContexts(T, int, U, int);
 53: #elif PetscDefined(HAVE_CXX) && (PetscDefined(USE_DEBUG) || PetscDefined(DEVICE_KEEP_ERROR_CHECKING_MACROS))
 55:     do { \
 56:       PetscDeviceType pvdt_dtype_ = PetscDeviceTypeCast(dtype); \
 57:       int             pvdt_argno_ = (int)(argno); \
 58:       PetscCheck(((int)pvdt_dtype_ >= (int)PETSC_DEVICE_HOST) && ((int)pvdt_dtype_ <= (int)PETSC_DEVICE_MAX), PETSC_COMM_SELF, PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown PetscDeviceType '%d': Argument #%d", pvdt_dtype_, pvdt_argno_); \
 59:       if (PetscUnlikely(!PetscDeviceConfiguredFor_Internal(pvdt_dtype_))) { \
 60:         PetscCheck((int)pvdt_dtype_ != (int)PETSC_DEVICE_MAX, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Invalid PetscDeviceType '%s': Argument #%d", PetscDeviceTypes[pvdt_dtype_], pvdt_argno_); \
 61:         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, \
 62:                 "Not configured for PetscDeviceType '%s': Argument #%d;" \
 63:                 " run configure --help %s for available options", \
 64:                 PetscDeviceTypes[pvdt_dtype_], pvdt_argno_, PetscDeviceTypes[pvdt_dtype_]); \
 65:       } \
 66:     } while (0)

 68:   #define PetscCheckCompatibleDeviceTypes(dtype1, argno1, dtype2, argno2) \
 69:     do { \
 70:       PetscDeviceType pccdt_dtype1_ = PetscDeviceTypeCast(dtype1); \
 71:       PetscDeviceType pccdt_dtype2_ = PetscDeviceTypeCast(dtype2); \
 74:       PetscCheck(pccdt_dtype1_ == pccdt_dtype2_, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMETYPE, "PetscDeviceTypes are incompatible: Arguments #%d and #%d. Expected PetscDeviceType '%s' but have '%s' instead", argno1, argno2, PetscDeviceTypes[pccdt_dtype1_], PetscDeviceTypes[pccdt_dtype2_]); \
 75:     } while (0)

 78:     do { \
 79:       PetscDevice pvd_dev_   = dev; \
 80:       int         pvd_argno_ = (int)(argno); \
 81:       PetscAssertPointer(pvd_dev_, pvd_argno_); \
 83:       PetscCheck(pvd_dev_->id >= 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid PetscDevice: Argument #%d; id %" PetscInt_FMT " < 0", pvd_argno_, pvd_dev_->id); \
 84:       PetscCheck(pvd_dev_->refcnt >= 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid PetscDevice: Argument #%d; negative reference count %" PetscInt_FMT, pvd_argno_, pvd_dev_->refcnt); \
 85:     } while (0)

 88:     do { \
 89:       PetscDeviceAttribute pvda_attr_  = (dattr); \
 90:       int                  pvda_argno_ = (int)(argno); \
 91:       PetscCheck((((int)pvda_attr_) >= 0) && (pvda_attr_ <= PETSC_DEVICE_ATTR_MAX), PETSC_COMM_SELF, PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown PetscDeviceAttribute '%d': Argument #%d", (int)pvda_attr_, pvda_argno_); \
 92:       PetscCheck(pvda_attr_ != PETSC_DEVICE_ATTR_MAX, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Invalid PetscDeviceAttribute '%s': Argument #%d", PetscDeviceAttributes[pvda_attr_], pvda_argno_); \
 93:     } while (0)

 95:   /*
 96:   for now just checks strict equality, but this can be changed as some devices (i.e. kokkos and
 97:   any cupm should be compatible once implemented)
 98: */
 99:   #define PetscCheckCompatibleDevices(dev1, argno1, dev2, argno2) \
100:     do { \
101:       PetscDevice pccd_dev1_ = (dev1), pccd_dev2_ = (dev2); \
102:       int         pccd_argno1_ = (int)(argno1), pccd_argno2_ = (int)(argno2); \
105:       PetscCheckCompatibleDeviceTypes(pccd_dev1_->type, pccd_argno1_, pccd_dev2_->type, pccd_argno2_); \
106:     } while (0)

109:     do { \
110:       PetscStreamType pvst_stype_ = PetscStreamTypeCast(stype); \
111:       int             pvst_argno_ = (int)(argno); \
112:       PetscCheck(((int)pvst_stype_ >= 0) && ((int)pvst_stype_ <= (int)PETSC_STREAM_MAX), PETSC_COMM_SELF, PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown PetscStreamType '%d': Argument #%d", pvst_stype_, pvst_argno_); \
113:       PetscCheck((int)pvst_stype_ != (int)PETSC_STREAM_MAX, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Invalid PetscStreamType '%s': Argument #%d", PetscStreamTypes[pvst_stype_], pvst_argno_); \
114:     } while (0)

117:     do { \
118:       PetscDeviceContext pvdc_dctx_  = dctx; \
119:       int                pvdc_argno_ = (int)(argno); \
122:       if (pvdc_dctx_->device) { \
124:       } else { \
125:         PetscCheck(!pvdc_dctx_->setup, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, \
126:                    "Invalid PetscDeviceContext: Argument #%d; " \
127:                    "PetscDeviceContext is setup but has no PetscDevice", \
128:                    pvdc_argno_); \
129:       } \
130:       PetscCheck(((PetscObject)pvdc_dctx_)->id >= 1, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid PetscDeviceContext: Argument #%d; id %" PetscInt64_FMT " < 1", pvdc_argno_, ((PetscObject)pvdc_dctx_)->id); \
131:       PetscCheck(pvdc_dctx_->numChildren <= pvdc_dctx_->maxNumChildren, PETSC_COMM_SELF, PETSC_ERR_ARG_CORRUPT, "Invalid PetscDeviceContext: Argument #%d; number of children %" PetscInt_FMT " > max number of children %" PetscInt_FMT, pvdc_argno_, \
132:                  pvdc_dctx_->numChildren, pvdc_dctx_->maxNumChildren); \
133:     } while (0)

135:   #define PetscCheckCompatibleDeviceContexts(dctx1, argno1, dctx2, argno2) \
136:     do { \
137:       PetscDeviceContext pccdc_dctx1_ = (dctx1), pccdc_dctx2_ = (dctx2); \
138:       int                pccdc_argno1_ = (int)(argno1), pccdc_argno2_ = (int)(argno2); \
141:       if (pccdc_dctx1_->device && pccdc_dctx2_->device) PetscCheckCompatibleDevices(pccdc_dctx1_->device, pccdc_argno1_, pccdc_dctx2_->device, pccdc_argno2_); \
142:     } while (0)
143: #else /* PetscDefined(USE_DEBUG) */
145:   #define PetscCheckCompatibleDeviceTypes(dtype1, argno1, dtype2, argno2)
148:   #define PetscCheckCompatibleDevices(dev1, argno1, dev2, argno2)
151:   #define PetscCheckCompatibleDeviceContexts(dctx1, argno1, dctx2, argno2)
152: #endif /* PetscDefined(USE_DEBUG) */

154: /* if someone is ready to rock with more than 128 GPUs on hand then we're in real trouble */
155: #define PETSC_DEVICE_MAX_DEVICES 128

157: /*
158:   the configure-time default device type, used as the initial the value of
159:   PETSC_DEVICE_DEFAULT() as well as what it is restored to during PetscFinalize()
160: */
161: #if PetscDefined(HAVE_HIP)
162:   #define PETSC_DEVICE_HARDWARE_DEFAULT_TYPE PETSC_DEVICE_HIP
163: #elif PetscDefined(HAVE_CUDA)
164:   #define PETSC_DEVICE_HARDWARE_DEFAULT_TYPE PETSC_DEVICE_CUDA
165: #elif PetscDefined(HAVE_SYCL)
166:   #define PETSC_DEVICE_HARDWARE_DEFAULT_TYPE PETSC_DEVICE_SYCL
167: #else
168:   #define PETSC_DEVICE_HARDWARE_DEFAULT_TYPE PETSC_DEVICE_HOST
169: #endif

171: #define PETSC_DEVICE_CONTEXT_DEFAULT_DEVICE_TYPE PETSC_DEVICE_HARDWARE_DEFAULT_TYPE
172: // REMOVE ME (change)
173: #define PETSC_DEVICE_CONTEXT_DEFAULT_STREAM_TYPE PETSC_STREAM_GLOBAL_BLOCKING

175: typedef struct _DeviceOps *DeviceOps;
176: struct _DeviceOps {
177:   /* the creation routine for the corresponding PetscDeviceContext, this is NOT intended
178:    * to be called by the PetscDevice itself */
179:   PetscErrorCode (*createcontext)(PetscDeviceContext);
180:   PetscErrorCode (*configure)(PetscDevice);
181:   PetscErrorCode (*view)(PetscDevice, PetscViewer);
182:   PetscErrorCode (*getattribute)(PetscDevice, PetscDeviceAttribute, void *);
183: };

185: struct _n_PetscDevice {
186:   struct _DeviceOps ops[1];
187:   void             *data;     /* placeholder */
188:   PetscInt          refcnt;   /* reference count for the device */
189:   PetscInt          id;       /* unique id per created PetscDevice */
190:   PetscInt          deviceId; /* the id of the underlying device, i.e. the return of
191:                                * cudaGetDevice() for example */
192:   PetscDeviceType   type;     /* type of device */
193: };

195: typedef struct _n_PetscEvent *PetscEvent;
196: struct _n_PetscEvent {
197:   PetscDeviceType  dtype;      // this cannot change for the lifetime of the event
198:   PetscObjectId    dctx_id;    // id of last dctx to record this event
199:   PetscObjectState dctx_state; // state of last dctx to record this event
200:   void            *data;       // event handle
201:   PetscErrorCode (*destroy)(PetscEvent);
202: };

204: typedef struct _DeviceContextOps *DeviceContextOps;
205: struct _DeviceContextOps {
206:   PetscErrorCode (*destroy)(PetscDeviceContext);
207:   PetscErrorCode (*changestreamtype)(PetscDeviceContext, PetscStreamType);
208:   PetscErrorCode (*setup)(PetscDeviceContext);
209:   PetscErrorCode (*query)(PetscDeviceContext, PetscBool *);
210:   PetscErrorCode (*waitforcontext)(PetscDeviceContext, PetscDeviceContext);
211:   PetscErrorCode (*synchronize)(PetscDeviceContext);
212:   PetscErrorCode (*getblashandle)(PetscDeviceContext, void *);
213:   PetscErrorCode (*getsolverhandle)(PetscDeviceContext, void *);
214:   PetscErrorCode (*getstreamhandle)(PetscDeviceContext, void **);
215:   PetscErrorCode (*begintimer)(PetscDeviceContext);
216:   PetscErrorCode (*endtimer)(PetscDeviceContext, PetscLogDouble *);
217:   PetscErrorCode (*memalloc)(PetscDeviceContext, PetscBool, PetscMemType, size_t, size_t, void **);                             // optional
218:   PetscErrorCode (*memfree)(PetscDeviceContext, PetscMemType, void **);                                                         // optional
219:   PetscErrorCode (*memcopy)(PetscDeviceContext, void *PETSC_RESTRICT, const void *PETSC_RESTRICT, size_t, PetscDeviceCopyMode); // optional
220:   PetscErrorCode (*memset)(PetscDeviceContext, PetscMemType, void *, PetscInt, size_t);                                         // optional
221:   PetscErrorCode (*createevent)(PetscDeviceContext, PetscEvent);                                                                // optional
222:   PetscErrorCode (*recordevent)(PetscDeviceContext, PetscEvent);                                                                // optional
223:   PetscErrorCode (*waitforevent)(PetscDeviceContext, PetscEvent);                                                               // optional
224: };

226: struct _p_PetscDeviceContext {
227:   PETSCHEADER(struct _DeviceContextOps);
228:   PetscDevice     device;         /* the device this context stems from */
229:   void           *data;           /* solver contexts, event, stream */
230:   PetscObjectId  *childIDs;       /* array containing ids of contexts currently forked from this one */
231:   PetscInt        numChildren;    /* how many children does this context expect to destroy */
232:   PetscInt        maxNumChildren; /* how many children can this context have room for without realloc'ing */
233:   PetscStreamType streamType;     /* how should this contexts stream behave around other streams? */
234:   PetscBool       setup;
235:   PetscBool       usersetdevice;
236: };

238: // ===================================================================================
239: //                            PetscDevice Internal Functions
240: // ===================================================================================
241: #if PetscDefined(HAVE_CXX)
242: PETSC_INTERN PetscErrorCode                PetscDeviceInitializeFromOptions_Internal(MPI_Comm);
243: PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode PetscDeviceGetDefaultForType_Internal(PetscDeviceType, PetscDevice *);

245: static inline PetscErrorCode PetscDeviceReference_Internal(PetscDevice device)
246: {
247:   PetscFunctionBegin;
248:   ++(device->refcnt);
249:   PetscFunctionReturn(PETSC_SUCCESS);
250: }

252: static inline PetscErrorCode PetscDeviceDereference_Internal(PetscDevice device)
253: {
254:   PetscFunctionBegin;
255:   --(device->refcnt);
256:   PetscAssert(device->refcnt >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_CORRUPT, "PetscDevice has negative reference count %" PetscInt_FMT, device->refcnt);
257:   PetscFunctionReturn(PETSC_SUCCESS);
258: }
259: #else /* PETSC_HAVE_CXX for PetscDevice Internal Functions */
260:   #define PetscDeviceInitializeFromOptions_Internal(comm)     PETSC_SUCCESS
261:   #define PetscDeviceGetDefaultForType_Internal(Type, device) (*(device) = PETSC_NULLPTR, PETSC_SUCCESS)
262:   #define PetscDeviceReference_Internal(device)               PETSC_SUCCESS
263:   #define PetscDeviceDereference_Internal(device)             PETSC_SUCCESS
264: #endif /* PETSC_HAVE_CXX for PetscDevice Internal Functions */

266: static inline PetscErrorCode PetscDeviceCheckDeviceCount_Internal(PetscInt count)
267: {
268:   PetscFunctionBegin;
269:   PetscAssert(count < PETSC_DEVICE_MAX_DEVICES, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Detected %" PetscInt_FMT " devices, which is larger than maximum supported number of devices %d", count, PETSC_DEVICE_MAX_DEVICES);
270:   PetscFunctionReturn(PETSC_SUCCESS);
271: }

273: /* More general form of PetscDeviceDefaultType_Internal(), as it calls the former using
274:  * the automatically selected default PetscDeviceType */
275: #define PetscDeviceGetDefault_Internal(device) PetscDeviceGetDefaultForType_Internal(PETSC_DEVICE_DEFAULT(), device)

277: static inline PETSC_CONSTEXPR_14 PetscBool PetscDeviceConfiguredFor_Internal(PetscDeviceType type)
278: {
279:   switch (type) {
280:   case PETSC_DEVICE_HOST:
281:     return PETSC_TRUE;
282:     /* casts are needed in C++ */
283:   case PETSC_DEVICE_CUDA:
284:     return (PetscBool)PetscDefined(HAVE_CUDA);
285:   case PETSC_DEVICE_HIP:
286:     return (PetscBool)PetscDefined(HAVE_HIP);
287:   case PETSC_DEVICE_SYCL:
288:     return (PetscBool)PetscDefined(HAVE_SYCL);
289:   case PETSC_DEVICE_MAX:
290:     return PETSC_FALSE;
291:     /* Do not add default case! Will make compiler warn on new additions to PetscDeviceType! */
292:   }
293:   PetscUnreachable();
294:   return PETSC_FALSE;
295: }

297: // ===================================================================================
298: //                     PetscDeviceContext Internal Functions
299: // ===================================================================================
300: #if PetscDefined(HAVE_CXX)
301: PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode PetscDeviceContextGetNullContext_Internal(PetscDeviceContext *);

303: static inline PetscErrorCode PetscDeviceContextGetBLASHandle_Internal(PetscDeviceContext dctx, void *handle)
304: {
305:   PetscFunctionBegin;
306:   /* we do error checking here as this routine is an entry-point */
308:   PetscUseTypeMethod(dctx, getblashandle, handle);
309:   PetscFunctionReturn(PETSC_SUCCESS);
310: }

312: static inline PetscErrorCode PetscDeviceContextGetSOLVERHandle_Internal(PetscDeviceContext dctx, void *handle)
313: {
314:   PetscFunctionBegin;
315:   /* we do error checking here as this routine is an entry-point */
317:   PetscUseTypeMethod(dctx, getsolverhandle, handle);
318:   PetscFunctionReturn(PETSC_SUCCESS);
319: }

321: static inline PetscErrorCode PetscDeviceContextGetStreamHandle_Internal(PetscDeviceContext dctx, void **handle)
322: {
323:   PetscFunctionBegin;
324:   /* we do error checking here as this routine is an entry-point */
326:   PetscAssertPointer(handle, 2);
327:   PetscUseTypeMethod(dctx, getstreamhandle, handle);
328:   PetscFunctionReturn(PETSC_SUCCESS);
329: }

331: static inline PetscErrorCode PetscDeviceContextBeginTimer_Internal(PetscDeviceContext dctx)
332: {
333:   PetscFunctionBegin;
334:   /* we do error checking here as this routine is an entry-point */
336:   PetscUseTypeMethod(dctx, begintimer);
337:   PetscFunctionReturn(PETSC_SUCCESS);
338: }

340: static inline PetscErrorCode PetscDeviceContextEndTimer_Internal(PetscDeviceContext dctx, PetscLogDouble *elapsed)
341: {
342:   PetscFunctionBegin;
343:   /* we do error checking here as this routine is an entry-point */
345:   PetscAssertPointer(elapsed, 2);
346:   PetscUseTypeMethod(dctx, endtimer, elapsed);
347:   PetscFunctionReturn(PETSC_SUCCESS);
348: }
349: #else /* PETSC_HAVE_CXX for PetscDeviceContext Internal Functions */
350:   #define PetscDeviceContextGetNullContext_Internal(dctx)          (*(dctx) = PETSC_NULLPTR, PETSC_SUCCESS)
351:   #define PetscDeviceContextGetBLASHandle_Internal(dctx, handle)   (*(handle) = PETSC_NULLPTR, PETSC_SUCCESS)
352:   #define PetscDeviceContextGetSOLVERHandle_Internal(dctx, handle) (*(handle) = PETSC_NULLPTR, PETSC_SUCCESS)
353:   #define PetscDeviceContextGetStreamHandle_Internal(dctx, handle) (*(handle) = PETSC_NULLPTR, PETSC_SUCCESS)
354:   #define PetscDeviceContextBeginTimer_Internal(dctx)              PETSC_SUCCESS
355:   #define PetscDeviceContextEndTimer_Internal(dctx, elapsed)       PETSC_SUCCESS
356: #endif /* PETSC_HAVE_CXX for PetscDeviceContext Internal Functions */

358: /* note, only does assertion checking in debug mode */
359: static inline PetscErrorCode PetscDeviceContextGetCurrentContextAssertType_Internal(PetscDeviceContext *dctx, PetscDeviceType type)
360: {
361:   PetscFunctionBegin;
362:   PetscCall(PetscDeviceContextGetCurrentContext(dctx));
363:   if (PetscDefined(USE_DEBUG)) {
364:     PetscDeviceType dtype;

367:     PetscCall(PetscDeviceContextGetDeviceType(*dctx, &dtype));
368:     PetscCheckCompatibleDeviceTypes(dtype, 1, type, 2);
369:   } else (void)type;
370:   PetscFunctionReturn(PETSC_SUCCESS);
371: }

373: static inline PetscErrorCode PetscDeviceContextGetOptionalNullContext_Internal(PetscDeviceContext *dctx)
374: {
375:   PetscFunctionBegin;
376:   PetscAssertPointer(dctx, 1);
377:   if (!*dctx) PetscCall(PetscDeviceContextGetNullContext_Internal(dctx));
379:   PetscFunctionReturn(PETSC_SUCCESS);
380: }

382: /* Experimental API -- it will eventually become public */
383: #if PetscDefined(HAVE_CXX)
384: PETSC_EXTERN PetscErrorCode PetscDeviceRegisterMemory(const void *PETSC_RESTRICT, PetscMemType, size_t);
385: PETSC_EXTERN PetscErrorCode PetscDeviceGetAttribute(PetscDevice, PetscDeviceAttribute, void *);
386: PETSC_EXTERN PetscErrorCode PetscDeviceContextMarkIntentFromID(PetscDeviceContext, PetscObjectId, PetscMemoryAccessMode, const char name[]);
387:   #if defined(__cplusplus)
388: namespace
389: {

391: inline PetscErrorCode PetscDeviceContextMarkIntentFromID(PetscDeviceContext dctx, PetscObject obj, PetscMemoryAccessMode mode, const char name[])
392: {
393:   PetscFunctionBegin;
394:   PetscCall(PetscDeviceContextMarkIntentFromID(dctx, obj->id, mode, name));
395:   PetscFunctionReturn(PETSC_SUCCESS);
396: }

398: } // anonymous namespace
399:   #endif // __cplusplus
400: #else
401:   #define PetscDeviceRegisterMemory(void_ptr, PetscMemType, size)                                           PETSC_SUCCESS
402:   #define PetscDeviceGetAttribute(PetscDevice, PetscDeviceAttribute, void_star)                             ((*((int *)(void_star)) = 0), PETSC_SUCCESS)
403:   #define PetscDeviceContextMarkIntentFromID(PetscDeviceContext, PetscObjectId, PetscMemoryAccessMode, ptr) PETSC_SUCCESS
404: #endif

406: PETSC_INTERN PetscErrorCode PetscDeviceContextCreate_HOST(PetscDeviceContext);
407: #if PetscDefined(HAVE_CUDA)
408: PETSC_INTERN PetscErrorCode PetscDeviceContextCreate_CUDA(PetscDeviceContext);
409: #endif
410: #if PetscDefined(HAVE_HIP)
411: PETSC_INTERN PetscErrorCode PetscDeviceContextCreate_HIP(PetscDeviceContext);
412: #endif
413: #if PetscDefined(HAVE_SYCL)
414: PETSC_INTERN PetscErrorCode PetscDeviceContextCreate_SYCL(PetscDeviceContext);
415: #endif

417: // Used for testing purposes, internal use ONLY
418: PETSC_EXTERN PetscErrorCode PetscGetMarkedObjectMap_Internal(size_t *, PetscObjectId **, PetscMemoryAccessMode **, size_t **, PetscEvent ***);
419: PETSC_EXTERN PetscErrorCode PetscRestoreMarkedObjectMap_Internal(size_t, PetscObjectId **, PetscMemoryAccessMode **, size_t **, PetscEvent ***);

421: static inline PetscErrorCode PetscDeviceContextSynchronizeIfGlobalBlocking_Internal(PetscDeviceContext dctx)
422: {
423:   PetscStreamType stream_type;

425:   PetscFunctionBegin;
426:   PetscCall(PetscDeviceContextGetStreamType(dctx, &stream_type));
427:   if (stream_type == PETSC_STREAM_GLOBAL_BLOCKING) PetscCall(PetscDeviceContextSynchronize(dctx));
428:   PetscFunctionReturn(PETSC_SUCCESS);
429: }