1030f984aSJacob Faibussowitsch #include <petsc/private/deviceimpl.h> /*I "petscdevice.h" I*/ 2030f984aSJacob Faibussowitsch #include "objpool.hpp" 3030f984aSJacob Faibussowitsch 49371c9d4SSatish Balay const char *const PetscStreamTypes[] = {"global_blocking", "default_blocking", "global_nonblocking", "max", "PetscStreamType", "PETSC_STREAM_", nullptr}; 5a4af0ceeSJacob Faibussowitsch 69371c9d4SSatish Balay const char *const PetscDeviceContextJoinModes[] = {"destroy", "sync", "no_sync", "PetscDeviceContextJoinMode", "PETSC_DEVICE_CONTEXT_JOIN_", nullptr}; 7a4af0ceeSJacob Faibussowitsch 8030f984aSJacob Faibussowitsch /* Define the allocator */ 99371c9d4SSatish Balay struct PetscDeviceContextAllocator : Petsc::AllocatorBase<PetscDeviceContext> { 10030f984aSJacob Faibussowitsch static PetscInt PetscDeviceContextID; 11030f984aSJacob Faibussowitsch 129371c9d4SSatish Balay PETSC_NODISCARD static PetscErrorCode create(PetscDeviceContext *dctx) noexcept { 13030f984aSJacob Faibussowitsch PetscDeviceContext dc; 14030f984aSJacob Faibussowitsch 15030f984aSJacob Faibussowitsch PetscFunctionBegin; 169566063dSJacob Faibussowitsch PetscCall(PetscNew(&dc)); 17030f984aSJacob Faibussowitsch dc->id = PetscDeviceContextID++; 18030f984aSJacob Faibussowitsch dc->streamType = PETSC_STREAM_DEFAULT_BLOCKING; 19030f984aSJacob Faibussowitsch *dctx = dc; 20030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 21030f984aSJacob Faibussowitsch } 22030f984aSJacob Faibussowitsch 239371c9d4SSatish Balay PETSC_NODISCARD static PetscErrorCode destroy(PetscDeviceContext dctx) noexcept { 24030f984aSJacob Faibussowitsch PetscFunctionBegin; 25bf025ffbSJacob Faibussowitsch PetscAssert(!dctx->numChildren, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Device context still has %" PetscInt_FMT " un-joined children, must call PetscDeviceContextJoin() with all children before destroying", dctx->numChildren); 26dbbe0bcdSBarry Smith PetscTryTypeMethod(dctx, destroy); 279566063dSJacob Faibussowitsch PetscCall(PetscDeviceDestroy(&dctx->device)); 289566063dSJacob Faibussowitsch PetscCall(PetscFree(dctx->childIDs)); 299566063dSJacob Faibussowitsch PetscCall(PetscFree(dctx)); 30030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 31030f984aSJacob Faibussowitsch } 32030f984aSJacob Faibussowitsch 339371c9d4SSatish Balay PETSC_NODISCARD static PetscErrorCode reset(PetscDeviceContext dctx) noexcept { 34030f984aSJacob Faibussowitsch PetscFunctionBegin; 35030f984aSJacob Faibussowitsch /* don't deallocate the child array, rather just zero it out */ 369566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(dctx->childIDs, dctx->maxNumChildren)); 37030f984aSJacob Faibussowitsch dctx->setup = PETSC_FALSE; 38030f984aSJacob Faibussowitsch dctx->numChildren = 0; 39030f984aSJacob Faibussowitsch dctx->streamType = PETSC_STREAM_DEFAULT_BLOCKING; 40030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 41030f984aSJacob Faibussowitsch } 42030f984aSJacob Faibussowitsch 4317f48955SJacob Faibussowitsch PETSC_NODISCARD static constexpr PetscErrorCode finalize() noexcept { return 0; } 44030f984aSJacob Faibussowitsch }; 45a4af0ceeSJacob Faibussowitsch /* an ID = 0 is invalid */ 46a4af0ceeSJacob Faibussowitsch PetscInt PetscDeviceContextAllocator::PetscDeviceContextID = 1; 47030f984aSJacob Faibussowitsch 48030f984aSJacob Faibussowitsch static Petsc::ObjectPool<PetscDeviceContext, PetscDeviceContextAllocator> contextPool; 49030f984aSJacob Faibussowitsch 50030f984aSJacob Faibussowitsch /*@C 51030f984aSJacob Faibussowitsch PetscDeviceContextCreate - Creates a PetscDeviceContext 52030f984aSJacob Faibussowitsch 53030f984aSJacob Faibussowitsch Not Collective, Asynchronous 54030f984aSJacob Faibussowitsch 5501d2d390SJose E. Roman Output Paramemter: 56030f984aSJacob Faibussowitsch . dctx - The PetscDeviceContext 57030f984aSJacob Faibussowitsch 58030f984aSJacob Faibussowitsch Notes: 59030f984aSJacob Faibussowitsch Unlike almost every other PETSc class it is advised that most users use 60030f984aSJacob Faibussowitsch PetscDeviceContextDuplicate() rather than this routine to create new contexts. Contexts 61030f984aSJacob Faibussowitsch of different types are incompatible with one another; using 62030f984aSJacob Faibussowitsch PetscDeviceContextDuplicate() ensures compatible types. 63030f984aSJacob Faibussowitsch 64030f984aSJacob Faibussowitsch Level: beginner 65030f984aSJacob Faibussowitsch 66db781477SPatrick Sanan .seealso: `PetscDeviceContextDuplicate()`, `PetscDeviceContextSetDevice()`, 67db781477SPatrick Sanan `PetscDeviceContextSetStreamType()`, `PetscDeviceContextSetUp()`, 68db781477SPatrick Sanan `PetscDeviceContextSetFromOptions()`, `PetscDeviceContextDestroy()` 69030f984aSJacob Faibussowitsch @*/ 709371c9d4SSatish Balay PetscErrorCode PetscDeviceContextCreate(PetscDeviceContext *dctx) { 71030f984aSJacob Faibussowitsch PetscFunctionBegin; 72030f984aSJacob Faibussowitsch PetscValidPointer(dctx, 1); 739566063dSJacob Faibussowitsch PetscCall(PetscDeviceInitializePackage()); 749566063dSJacob Faibussowitsch PetscCall(contextPool.get(*dctx)); 75030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 76030f984aSJacob Faibussowitsch } 77030f984aSJacob Faibussowitsch 78030f984aSJacob Faibussowitsch /*@C 79030f984aSJacob Faibussowitsch PetscDeviceContextDestroy - Frees a PetscDeviceContext 80030f984aSJacob Faibussowitsch 81030f984aSJacob Faibussowitsch Not Collective, Asynchronous 82030f984aSJacob Faibussowitsch 83030f984aSJacob Faibussowitsch Input Parameters: 84030f984aSJacob Faibussowitsch . dctx - The PetscDeviceContext 85030f984aSJacob Faibussowitsch 86030f984aSJacob Faibussowitsch Notes: 87030f984aSJacob Faibussowitsch No implicit synchronization occurs due to this routine, all resources are released completely asynchronously 88030f984aSJacob Faibussowitsch w.r.t. the host. If one needs to guarantee access to the data produced on this contexts stream one should perform the 89030f984aSJacob Faibussowitsch appropriate synchronization before calling this routine. 90030f984aSJacob Faibussowitsch 91030f984aSJacob Faibussowitsch Developer Notes: 92030f984aSJacob Faibussowitsch The context is never actually "destroyed", only returned to an ever growing pool of 93030f984aSJacob Faibussowitsch contexts. There are currently no safeguards on the size of the pool, this should perhaps 94030f984aSJacob Faibussowitsch be implemented. 95030f984aSJacob Faibussowitsch 96030f984aSJacob Faibussowitsch Level: beginner 97030f984aSJacob Faibussowitsch 98db781477SPatrick Sanan .seealso: `PetscDeviceContextCreate()`, `PetscDeviceContextSetDevice()`, `PetscDeviceContextSetUp()`, `PetscDeviceContextSynchronize()` 99030f984aSJacob Faibussowitsch @*/ 1009371c9d4SSatish Balay PetscErrorCode PetscDeviceContextDestroy(PetscDeviceContext *dctx) { 101030f984aSJacob Faibussowitsch PetscFunctionBegin; 102030f984aSJacob Faibussowitsch if (!*dctx) PetscFunctionReturn(0); 1039566063dSJacob Faibussowitsch PetscCall(contextPool.reclaim(std::move(*dctx))); 104bf025ffbSJacob Faibussowitsch *dctx = nullptr; 105030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 106030f984aSJacob Faibussowitsch } 107030f984aSJacob Faibussowitsch 108030f984aSJacob Faibussowitsch /*@C 109030f984aSJacob Faibussowitsch PetscDeviceContextSetStreamType - Set the implementation type of the underlying stream for a PetscDeviceContext 110030f984aSJacob Faibussowitsch 111030f984aSJacob Faibussowitsch Not Collective, Asynchronous 112030f984aSJacob Faibussowitsch 11301d2d390SJose E. Roman Input Parameters: 114030f984aSJacob Faibussowitsch + dctx - The PetscDeviceContext 115030f984aSJacob Faibussowitsch - type - The PetscStreamType 116030f984aSJacob Faibussowitsch 117030f984aSJacob Faibussowitsch Notes: 118030f984aSJacob Faibussowitsch See PetscStreamType in include/petscdevicetypes.h for more information on the available 119030f984aSJacob Faibussowitsch types and their interactions. If the PetscDeviceContext was previously set up and stream 120030f984aSJacob Faibussowitsch type was changed, you must call PetscDeviceContextSetUp() again after this routine. 121030f984aSJacob Faibussowitsch 122030f984aSJacob Faibussowitsch Level: intermediate 123030f984aSJacob Faibussowitsch 124db781477SPatrick Sanan .seealso: `PetscStreamType`, `PetscDeviceContextGetStreamType()`, `PetscDeviceContextCreate()`, `PetscDeviceContextSetUp()`, `PetscDeviceContextSetFromOptions()` 125030f984aSJacob Faibussowitsch @*/ 1269371c9d4SSatish Balay PetscErrorCode PetscDeviceContextSetStreamType(PetscDeviceContext dctx, PetscStreamType type) { 127030f984aSJacob Faibussowitsch PetscFunctionBegin; 128030f984aSJacob Faibussowitsch PetscValidDeviceContext(dctx, 1); 129030f984aSJacob Faibussowitsch PetscValidStreamType(type, 2); 130030f984aSJacob Faibussowitsch /* only need to do complex swapping if the object has already been setup */ 131030f984aSJacob Faibussowitsch if (dctx->setup && (dctx->streamType != type)) { 132dbbe0bcdSBarry Smith PetscUseTypeMethod(dctx, changestreamtype, type); 133030f984aSJacob Faibussowitsch dctx->setup = PETSC_FALSE; 134030f984aSJacob Faibussowitsch } 135030f984aSJacob Faibussowitsch dctx->streamType = type; 136030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 137030f984aSJacob Faibussowitsch } 138030f984aSJacob Faibussowitsch 139030f984aSJacob Faibussowitsch /*@C 140030f984aSJacob Faibussowitsch PetscDeviceContextGetStreamType - Get the implementation type of the underlying stream for a PetscDeviceContext 141030f984aSJacob Faibussowitsch 142030f984aSJacob Faibussowitsch Not Collective, Asynchronous 143030f984aSJacob Faibussowitsch 14401d2d390SJose E. Roman Input Parameter: 145030f984aSJacob Faibussowitsch . dctx - The PetscDeviceContext 146030f984aSJacob Faibussowitsch 147030f984aSJacob Faibussowitsch Output Parameter: 148030f984aSJacob Faibussowitsch . type - The PetscStreamType 149030f984aSJacob Faibussowitsch 150030f984aSJacob Faibussowitsch Notes: 151030f984aSJacob Faibussowitsch See PetscStreamType in include/petscdevicetypes.h for more information on the available types and their interactions 152030f984aSJacob Faibussowitsch 153030f984aSJacob Faibussowitsch Level: intermediate 154030f984aSJacob Faibussowitsch 155db781477SPatrick Sanan .seealso: `PetscDeviceContextSetStreamType()`, `PetscDeviceContextCreate()`, `PetscDeviceContextSetFromOptions()` 156030f984aSJacob Faibussowitsch @*/ 1579371c9d4SSatish Balay PetscErrorCode PetscDeviceContextGetStreamType(PetscDeviceContext dctx, PetscStreamType *type) { 158030f984aSJacob Faibussowitsch PetscFunctionBegin; 159030f984aSJacob Faibussowitsch PetscValidDeviceContext(dctx, 1); 160030f984aSJacob Faibussowitsch PetscValidIntPointer(type, 2); 161030f984aSJacob Faibussowitsch *type = dctx->streamType; 162030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 163030f984aSJacob Faibussowitsch } 164030f984aSJacob Faibussowitsch 165030f984aSJacob Faibussowitsch /*@C 166030f984aSJacob Faibussowitsch PetscDeviceContextSetDevice - Set the underlying device for the PetscDeviceContext 167030f984aSJacob Faibussowitsch 168030f984aSJacob Faibussowitsch Not Collective, Possibly Synchronous 169030f984aSJacob Faibussowitsch 17001d2d390SJose E. Roman Input Parameters: 171030f984aSJacob Faibussowitsch + dctx - The PetscDeviceContext 172030f984aSJacob Faibussowitsch - device - The PetscDevice 173030f984aSJacob Faibussowitsch 174030f984aSJacob Faibussowitsch Notes: 175030f984aSJacob Faibussowitsch This routine is effectively PetscDeviceContext's "set-type" (so every PetscDeviceContext 176030f984aSJacob Faibussowitsch must also have an attached PetscDevice). Unlike the usual set-type semantics, it is 177030f984aSJacob Faibussowitsch not stricly necessary to set a contexts device to enable usage, any created device 178030f984aSJacob Faibussowitsch contexts will always come equipped with the "default" device. 179030f984aSJacob Faibussowitsch 180a4af0ceeSJacob Faibussowitsch This routine is a no-op if dctx is already attached to device. 181a4af0ceeSJacob Faibussowitsch 1825181c4f9SJacob Faibussowitsch This routine may initialize the backend device and incur synchronization. 1835181c4f9SJacob Faibussowitsch 184030f984aSJacob Faibussowitsch Level: intermediate 185030f984aSJacob Faibussowitsch 186db781477SPatrick Sanan .seealso: `PetscDeviceCreate()`, `PetscDeviceConfigure()`, `PetscDeviceContextGetDevice()` 187030f984aSJacob Faibussowitsch @*/ 1889371c9d4SSatish Balay PetscErrorCode PetscDeviceContextSetDevice(PetscDeviceContext dctx, PetscDevice device) { 189030f984aSJacob Faibussowitsch PetscFunctionBegin; 190030f984aSJacob Faibussowitsch PetscValidDeviceContext(dctx, 1); 191030f984aSJacob Faibussowitsch PetscValidDevice(device, 2); 192a4af0ceeSJacob Faibussowitsch if (dctx->device) { 193a4af0ceeSJacob Faibussowitsch /* can't do a strict pointer equality check since PetscDevice's are reused */ 194a4af0ceeSJacob Faibussowitsch if (dctx->device->ops->createcontext == device->ops->createcontext) PetscFunctionReturn(0); 195a4af0ceeSJacob Faibussowitsch } 1969566063dSJacob Faibussowitsch PetscCall(PetscDeviceDestroy(&dctx->device)); 197dbbe0bcdSBarry Smith PetscTryTypeMethod(dctx, destroy); 1989566063dSJacob Faibussowitsch PetscCall(PetscMemzero(dctx->ops, sizeof(*dctx->ops))); 1999566063dSJacob Faibussowitsch PetscCall((*device->ops->createcontext)(dctx)); 2009566063dSJacob Faibussowitsch PetscCall(PetscDeviceReference_Internal(device)); 201a4af0ceeSJacob Faibussowitsch dctx->device = device; 202030f984aSJacob Faibussowitsch dctx->setup = PETSC_FALSE; 203030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 204030f984aSJacob Faibussowitsch } 205030f984aSJacob Faibussowitsch 206030f984aSJacob Faibussowitsch /*@C 207030f984aSJacob Faibussowitsch PetscDeviceContextGetDevice - Get the underlying PetscDevice for a PetscDeviceContext 208030f984aSJacob Faibussowitsch 209030f984aSJacob Faibussowitsch Not Collective, Asynchronous 210030f984aSJacob Faibussowitsch 211030f984aSJacob Faibussowitsch Input Parameter: 212030f984aSJacob Faibussowitsch . dctx - the PetscDeviceContext 213030f984aSJacob Faibussowitsch 214030f984aSJacob Faibussowitsch Output Parameter: 215030f984aSJacob Faibussowitsch . device - The PetscDevice 216030f984aSJacob Faibussowitsch 217030f984aSJacob Faibussowitsch Notes: 218030f984aSJacob Faibussowitsch This is a borrowed reference, the user should not destroy the device. 219030f984aSJacob Faibussowitsch 220a375dbeeSPatrick Sanan Level: intermediate 221a375dbeeSPatrick Sanan 222db781477SPatrick Sanan .seealso: `PetscDeviceContextSetDevice()`, `PetscDevice` 223030f984aSJacob Faibussowitsch @*/ 2249371c9d4SSatish Balay PetscErrorCode PetscDeviceContextGetDevice(PetscDeviceContext dctx, PetscDevice *device) { 225030f984aSJacob Faibussowitsch PetscFunctionBegin; 226030f984aSJacob Faibussowitsch PetscValidDeviceContext(dctx, 1); 227030f984aSJacob Faibussowitsch PetscValidPointer(device, 2); 228bf025ffbSJacob Faibussowitsch PetscAssert(dctx->device, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "PetscDeviceContext %" PetscInt_FMT " has no attached PetscDevice to get", dctx->id); 229030f984aSJacob Faibussowitsch *device = dctx->device; 230030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 231030f984aSJacob Faibussowitsch } 232030f984aSJacob Faibussowitsch 233030f984aSJacob Faibussowitsch /*@C 234030f984aSJacob Faibussowitsch PetscDeviceContextSetUp - Prepares a PetscDeviceContext for use 235030f984aSJacob Faibussowitsch 236030f984aSJacob Faibussowitsch Not Collective, Asynchronous 237030f984aSJacob Faibussowitsch 23801d2d390SJose E. Roman Input Parameter: 239030f984aSJacob Faibussowitsch . dctx - The PetscDeviceContext 240030f984aSJacob Faibussowitsch 241030f984aSJacob Faibussowitsch Developer Notes: 242030f984aSJacob Faibussowitsch This routine is usually the stage where a PetscDeviceContext acquires device-side data structures such as streams, 243030f984aSJacob Faibussowitsch events, and (possibly) handles. 244030f984aSJacob Faibussowitsch 245030f984aSJacob Faibussowitsch Level: beginner 246030f984aSJacob Faibussowitsch 247db781477SPatrick Sanan .seealso: `PetscDeviceContextCreate()`, `PetscDeviceContextSetDevice()`, `PetscDeviceContextDestroy()`, `PetscDeviceContextSetFromOptions()` 248030f984aSJacob Faibussowitsch @*/ 2499371c9d4SSatish Balay PetscErrorCode PetscDeviceContextSetUp(PetscDeviceContext dctx) { 250030f984aSJacob Faibussowitsch PetscFunctionBegin; 251030f984aSJacob Faibussowitsch PetscValidDeviceContext(dctx, 1); 252030f984aSJacob Faibussowitsch if (!dctx->device) { 2539566063dSJacob Faibussowitsch PetscCall(PetscInfo(nullptr, "PetscDeviceContext %" PetscInt_FMT " did not have an explicitly attached PetscDevice, using default with type %s\n", dctx->id, PetscDeviceTypes[PETSC_DEVICE_DEFAULT])); 2549566063dSJacob Faibussowitsch PetscCall(PetscDeviceContextSetDefaultDevice_Internal(dctx)); 255030f984aSJacob Faibussowitsch } 256030f984aSJacob Faibussowitsch if (dctx->setup) PetscFunctionReturn(0); 257dbbe0bcdSBarry Smith PetscUseTypeMethod(dctx, setup); 258030f984aSJacob Faibussowitsch dctx->setup = PETSC_TRUE; 259030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 260030f984aSJacob Faibussowitsch } 261030f984aSJacob Faibussowitsch 262030f984aSJacob Faibussowitsch /*@C 263030f984aSJacob Faibussowitsch PetscDeviceContextDuplicate - Duplicates a PetscDeviceContext object 264030f984aSJacob Faibussowitsch 265030f984aSJacob Faibussowitsch Not Collective, Asynchronous 266030f984aSJacob Faibussowitsch 267030f984aSJacob Faibussowitsch Input Parameter: 268030f984aSJacob Faibussowitsch . dctx - The PetscDeviceContext to duplicate 269030f984aSJacob Faibussowitsch 2706aad120cSJose E. Roman Output Parameter: 271050c0c3dSJacob Faibussowitsch . dctxdup - The duplicated PetscDeviceContext 272030f984aSJacob Faibussowitsch 273030f984aSJacob Faibussowitsch Notes: 274030f984aSJacob Faibussowitsch This is a shorthand method for creating a PetscDeviceContext with the exact same 275030f984aSJacob Faibussowitsch settings as another. Note however that the duplicated PetscDeviceContext does not "share" 276030f984aSJacob Faibussowitsch any of the underlying data with the original, (including its current stream-state) they 277030f984aSJacob Faibussowitsch are completely separate objects. 278030f984aSJacob Faibussowitsch 279030f984aSJacob Faibussowitsch Level: beginner 280030f984aSJacob Faibussowitsch 281db781477SPatrick Sanan .seealso: `PetscDeviceContextCreate()`, `PetscDeviceContextSetDevice()`, `PetscDeviceContextSetStreamType()` 282030f984aSJacob Faibussowitsch @*/ 2839371c9d4SSatish Balay PetscErrorCode PetscDeviceContextDuplicate(PetscDeviceContext dctx, PetscDeviceContext *dctxdup) { 284a4af0ceeSJacob Faibussowitsch PetscDeviceContext dup; 285030f984aSJacob Faibussowitsch 286030f984aSJacob Faibussowitsch PetscFunctionBegin; 287030f984aSJacob Faibussowitsch PetscValidDeviceContext(dctx, 1); 288030f984aSJacob Faibussowitsch PetscValidPointer(dctxdup, 2); 2899566063dSJacob Faibussowitsch PetscCall(PetscDeviceContextCreate(&dup)); 2909566063dSJacob Faibussowitsch PetscCall(PetscDeviceContextSetStreamType(dup, dctx->streamType)); 2919566063dSJacob Faibussowitsch if (dctx->device) PetscCall(PetscDeviceContextSetDevice(dup, dctx->device)); 2929566063dSJacob Faibussowitsch PetscCall(PetscDeviceContextSetUp(dup)); 293a4af0ceeSJacob Faibussowitsch *dctxdup = dup; 294030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 295030f984aSJacob Faibussowitsch } 296030f984aSJacob Faibussowitsch 297030f984aSJacob Faibussowitsch /*@C 298030f984aSJacob Faibussowitsch PetscDeviceContextQueryIdle - Returns whether or not a PetscDeviceContext is idle 299030f984aSJacob Faibussowitsch 300030f984aSJacob Faibussowitsch Not Collective, Asynchronous 301030f984aSJacob Faibussowitsch 302030f984aSJacob Faibussowitsch Input Parameter: 303030f984aSJacob Faibussowitsch . dctx - The PetscDeviceContext object 304030f984aSJacob Faibussowitsch 305030f984aSJacob Faibussowitsch Output Parameter: 306030f984aSJacob Faibussowitsch . idle - PETSC_TRUE if PetscDeviceContext has NO work, PETSC_FALSE if it has work 307030f984aSJacob Faibussowitsch 308030f984aSJacob Faibussowitsch Notes: 309ef657721SJacob Faibussowitsch This routine only refers a singular context and does NOT take any of its children into 310ef657721SJacob Faibussowitsch account. That is, if dctx is idle but has dependents who do have work, this routine still 311ef657721SJacob Faibussowitsch returns PETSC_TRUE. 312030f984aSJacob Faibussowitsch 313030f984aSJacob Faibussowitsch Level: intermediate 314030f984aSJacob Faibussowitsch 315db781477SPatrick Sanan .seealso: `PetscDeviceContextCreate()`, `PetscDeviceContextWaitForContext()`, `PetscDeviceContextFork()` 316030f984aSJacob Faibussowitsch @*/ 3179371c9d4SSatish Balay PetscErrorCode PetscDeviceContextQueryIdle(PetscDeviceContext dctx, PetscBool *idle) { 318030f984aSJacob Faibussowitsch PetscFunctionBegin; 319030f984aSJacob Faibussowitsch PetscValidDeviceContext(dctx, 1); 320030f984aSJacob Faibussowitsch PetscValidBoolPointer(idle, 2); 321dbbe0bcdSBarry Smith PetscUseTypeMethod(dctx, query, idle); 3229566063dSJacob Faibussowitsch PetscCall(PetscInfo(nullptr, "PetscDeviceContext id %" PetscInt_FMT " %s idle\n", dctx->id, *idle ? "was" : "was not")); 323030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 324030f984aSJacob Faibussowitsch } 325030f984aSJacob Faibussowitsch 326030f984aSJacob Faibussowitsch /*@C 327030f984aSJacob Faibussowitsch PetscDeviceContextWaitForContext - Make one context wait for another context to finish 328030f984aSJacob Faibussowitsch 329030f984aSJacob Faibussowitsch Not Collective, Asynchronous 330030f984aSJacob Faibussowitsch 331030f984aSJacob Faibussowitsch Input Parameters: 332030f984aSJacob Faibussowitsch + dctxa - The PetscDeviceContext object that is waiting 333030f984aSJacob Faibussowitsch - dctxb - The PetscDeviceContext object that is being waited on 334030f984aSJacob Faibussowitsch 335030f984aSJacob Faibussowitsch Notes: 336030f984aSJacob Faibussowitsch Serializes two PetscDeviceContexts. This routine uses only the state of dctxb at the moment this routine was 337030f984aSJacob Faibussowitsch called, so any future work queued will not affect dctxa. It is safe to pass the same context to both arguments. 338030f984aSJacob Faibussowitsch 339030f984aSJacob Faibussowitsch Level: beginner 340030f984aSJacob Faibussowitsch 341db781477SPatrick Sanan .seealso: `PetscDeviceContextCreate()`, `PetscDeviceContextQueryIdle()`, `PetscDeviceContextJoin()` 342030f984aSJacob Faibussowitsch @*/ 3439371c9d4SSatish Balay PetscErrorCode PetscDeviceContextWaitForContext(PetscDeviceContext dctxa, PetscDeviceContext dctxb) { 344030f984aSJacob Faibussowitsch PetscFunctionBegin; 345030f984aSJacob Faibussowitsch PetscCheckCompatibleDeviceContexts(dctxa, 1, dctxb, 2); 346030f984aSJacob Faibussowitsch if (dctxa == dctxb) PetscFunctionReturn(0); 347dbbe0bcdSBarry Smith PetscUseTypeMethod(dctxa, waitforcontext, dctxb); 348030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 349030f984aSJacob Faibussowitsch } 350030f984aSJacob Faibussowitsch 351050c0c3dSJacob Faibussowitsch #define PETSC_USE_DEBUG_AND_INFO (PetscDefined(USE_DEBUG) && PetscDefined(USE_INFO)) 352050c0c3dSJacob Faibussowitsch #if PETSC_USE_DEBUG_AND_INFO 353050c0c3dSJacob Faibussowitsch #include <string> 354050c0c3dSJacob Faibussowitsch #endif 355030f984aSJacob Faibussowitsch /*@C 356030f984aSJacob Faibussowitsch PetscDeviceContextFork - Create a set of dependent child contexts from a parent context 357030f984aSJacob Faibussowitsch 358030f984aSJacob Faibussowitsch Not Collective, Asynchronous 359030f984aSJacob Faibussowitsch 360030f984aSJacob Faibussowitsch Input Parameters: 361030f984aSJacob Faibussowitsch + dctx - The parent PetscDeviceContext 362030f984aSJacob Faibussowitsch - n - The number of children to create 363030f984aSJacob Faibussowitsch 364030f984aSJacob Faibussowitsch Output Parameter: 365030f984aSJacob Faibussowitsch . dsub - The created child context(s) 366030f984aSJacob Faibussowitsch 367030f984aSJacob Faibussowitsch Notes: 368030f984aSJacob Faibussowitsch This routine creates n edges of a DAG from a source node which are causally dependent on the source node, meaning 369030f984aSJacob Faibussowitsch that work queued on child contexts will not start until the parent context finishes its work. This accounts for work 370030f984aSJacob Faibussowitsch queued on the parent up until calling this function, any subsequent work enqueued on the parent has no effect on the children. 371030f984aSJacob Faibussowitsch 372030f984aSJacob Faibussowitsch Any children created with this routine have their lifetimes bounded by the parent. That is, the parent context expects 373030f984aSJacob Faibussowitsch to free all of it's children (and ONLY its children) before itself is freed. 374030f984aSJacob Faibussowitsch 375030f984aSJacob Faibussowitsch DAG representation: 376030f984aSJacob Faibussowitsch .vb 377030f984aSJacob Faibussowitsch time -> 378030f984aSJacob Faibussowitsch 379030f984aSJacob Faibussowitsch -> dctx \----> dctx ------> 380030f984aSJacob Faibussowitsch \---> dsub[0] ---> 381030f984aSJacob Faibussowitsch \--> ... -------> 382030f984aSJacob Faibussowitsch \-> dsub[n-1] -> 383030f984aSJacob Faibussowitsch .ve 384030f984aSJacob Faibussowitsch 385030f984aSJacob Faibussowitsch Level: intermediate 386030f984aSJacob Faibussowitsch 387db781477SPatrick Sanan .seealso: `PetscDeviceContextJoin()`, `PetscDeviceContextSynchronize()`, `PetscDeviceContextQueryIdle()` 388030f984aSJacob Faibussowitsch @*/ 3899371c9d4SSatish Balay PetscErrorCode PetscDeviceContextFork(PetscDeviceContext dctx, PetscInt n, PetscDeviceContext **dsub) { 390050c0c3dSJacob Faibussowitsch #if PETSC_USE_DEBUG_AND_INFO 391030f984aSJacob Faibussowitsch const PetscInt nBefore = n; 392030f984aSJacob Faibussowitsch static std::string idList; 393030f984aSJacob Faibussowitsch #endif 394bf025ffbSJacob Faibussowitsch PetscDeviceContext *dsubTmp = nullptr; 395030f984aSJacob Faibussowitsch PetscInt i = 0; 396030f984aSJacob Faibussowitsch 397030f984aSJacob Faibussowitsch PetscFunctionBegin; 398030f984aSJacob Faibussowitsch PetscValidDeviceContext(dctx, 1); 399030f984aSJacob Faibussowitsch PetscValidPointer(dsub, 3); 400bf025ffbSJacob Faibussowitsch PetscAssert(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of contexts requested %" PetscInt_FMT " < 0", n); 4013ca90d2dSJacob Faibussowitsch #if PETSC_USE_DEBUG_AND_INFO 402030f984aSJacob Faibussowitsch /* reserve 4 chars per id, 2 for number and 2 for ', ' separator */ 403030f984aSJacob Faibussowitsch idList.reserve(4 * n); 404030f984aSJacob Faibussowitsch #endif 405030f984aSJacob Faibussowitsch /* update child totals */ 406030f984aSJacob Faibussowitsch dctx->numChildren += n; 407030f984aSJacob Faibussowitsch /* now to find out if we have room */ 408030f984aSJacob Faibussowitsch if (dctx->numChildren > dctx->maxNumChildren) { 409030f984aSJacob Faibussowitsch /* no room, either from having too many kids or not having any */ 410030f984aSJacob Faibussowitsch if (dctx->childIDs) { 411030f984aSJacob Faibussowitsch /* have existing children, must reallocate them */ 4129566063dSJacob Faibussowitsch PetscCall(PetscRealloc(dctx->numChildren * sizeof(*dctx->childIDs), &dctx->childIDs)); 413030f984aSJacob Faibussowitsch /* clear the extra memory since realloc doesn't do it for us */ 4149566063dSJacob Faibussowitsch PetscCall(PetscArrayzero((dctx->childIDs) + (dctx->maxNumChildren), (dctx->numChildren) - (dctx->maxNumChildren))); 415030f984aSJacob Faibussowitsch } else { 416030f984aSJacob Faibussowitsch /* have no children */ 4179566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(dctx->numChildren, &dctx->childIDs)); 418030f984aSJacob Faibussowitsch } 419030f984aSJacob Faibussowitsch /* update total number of children */ 420030f984aSJacob Faibussowitsch dctx->maxNumChildren = dctx->numChildren; 421030f984aSJacob Faibussowitsch } 4229566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n, &dsubTmp)); 423030f984aSJacob Faibussowitsch while (n) { 424030f984aSJacob Faibussowitsch /* empty child slot */ 425030f984aSJacob Faibussowitsch if (!(dctx->childIDs[i])) { 426030f984aSJacob Faibussowitsch /* create the child context in the image of its parent */ 4279566063dSJacob Faibussowitsch PetscCall(PetscDeviceContextDuplicate(dctx, dsubTmp + i)); 4289566063dSJacob Faibussowitsch PetscCall(PetscDeviceContextWaitForContext(dsubTmp[i], dctx)); 429030f984aSJacob Faibussowitsch /* register the child with its parent */ 430030f984aSJacob Faibussowitsch dctx->childIDs[i] = dsubTmp[i]->id; 431050c0c3dSJacob Faibussowitsch #if PETSC_USE_DEBUG_AND_INFO 432030f984aSJacob Faibussowitsch idList += std::to_string(dsubTmp[i]->id); 433030f984aSJacob Faibussowitsch if (n != 1) idList += ", "; 434030f984aSJacob Faibussowitsch #endif 435030f984aSJacob Faibussowitsch --n; 436030f984aSJacob Faibussowitsch } 437030f984aSJacob Faibussowitsch ++i; 438030f984aSJacob Faibussowitsch } 4393ca90d2dSJacob Faibussowitsch #if PETSC_USE_DEBUG_AND_INFO 4409566063dSJacob Faibussowitsch PetscCall(PetscInfo(nullptr, "Forked %" PetscInt_FMT " children from parent %" PetscInt_FMT " with IDs: %s\n", nBefore, dctx->id, idList.c_str())); 441030f984aSJacob Faibussowitsch /* resets the size but doesn't deallocate the memory */ 442030f984aSJacob Faibussowitsch idList.clear(); 443030f984aSJacob Faibussowitsch #endif 444030f984aSJacob Faibussowitsch /* pass the children back to caller */ 445030f984aSJacob Faibussowitsch *dsub = dsubTmp; 446030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 447030f984aSJacob Faibussowitsch } 448030f984aSJacob Faibussowitsch 449030f984aSJacob Faibussowitsch /*@C 4505181c4f9SJacob Faibussowitsch PetscDeviceContextJoin - Converge a set of child contexts 451030f984aSJacob Faibussowitsch 452030f984aSJacob Faibussowitsch Not Collective, Asynchronous 453030f984aSJacob Faibussowitsch 454030f984aSJacob Faibussowitsch Input Parameters: 455030f984aSJacob Faibussowitsch + dctx - A PetscDeviceContext to converge on 456030f984aSJacob Faibussowitsch . n - The number of sub contexts to converge 457030f984aSJacob Faibussowitsch . joinMode - The type of join to perform 458030f984aSJacob Faibussowitsch - dsub - The sub contexts to converge 459030f984aSJacob Faibussowitsch 460030f984aSJacob Faibussowitsch Notes: 461030f984aSJacob Faibussowitsch If PetscDeviceContextFork() creates n edges from a source node which all depend on the 462030f984aSJacob Faibussowitsch source node, then this routine is the exact mirror. That is, it creates a node 463030f984aSJacob Faibussowitsch (represented in dctx) which recieves n edges (and optionally destroys them) which is 464030f984aSJacob Faibussowitsch dependent on the completion of all incoming edges. 465030f984aSJacob Faibussowitsch 466030f984aSJacob Faibussowitsch If joinMode is PETSC_DEVICE_CONTEXT_JOIN_DESTROY all contexts in dsub will be destroyed 467030f984aSJacob Faibussowitsch by this routine. Thus all sub contexts must have been created with the dctx passed to 468030f984aSJacob Faibussowitsch this routine. 469030f984aSJacob Faibussowitsch 470030f984aSJacob Faibussowitsch if joinMode is PETSC_DEVICE_CONTEXT_JOIN_NO_SYNC dctx waits for all sub contexts but the 471030f984aSJacob Faibussowitsch sub contexts do not wait for one another afterwards. 472030f984aSJacob Faibussowitsch 473030f984aSJacob Faibussowitsch If joinMode is PETSC_DEVICE_CONTEXT_JOIN_SYNC all sub contexts will additionally 474030f984aSJacob Faibussowitsch wait on dctx after converging. This has the effect of "synchronizing" the outgoing 475030f984aSJacob Faibussowitsch edges. 476030f984aSJacob Faibussowitsch 477030f984aSJacob Faibussowitsch DAG representations: 478030f984aSJacob Faibussowitsch If joinMode is PETSC_DEVICE_CONTEXT_JOIN_DESTROY 479030f984aSJacob Faibussowitsch .vb 480030f984aSJacob Faibussowitsch time -> 481030f984aSJacob Faibussowitsch 482030f984aSJacob Faibussowitsch -> dctx ---------/- dctx -> 483030f984aSJacob Faibussowitsch -> dsub[0] -----/ 484030f984aSJacob Faibussowitsch -> ... -------/ 485030f984aSJacob Faibussowitsch -> dsub[n-1] -/ 486030f984aSJacob Faibussowitsch .ve 487030f984aSJacob Faibussowitsch If joinMode is PETSC_DEVICE_CONTEXT_JOIN_NO_SYNC 488030f984aSJacob Faibussowitsch .vb 489030f984aSJacob Faibussowitsch time -> 490030f984aSJacob Faibussowitsch 491030f984aSJacob Faibussowitsch -> dctx ---------/- dctx -> 492030f984aSJacob Faibussowitsch -> dsub[0] -----/---------> 493030f984aSJacob Faibussowitsch -> ... -------/----------> 494030f984aSJacob Faibussowitsch -> dsub[n-1] -/-----------> 495030f984aSJacob Faibussowitsch .ve 496030f984aSJacob Faibussowitsch If joinMode is PETSC_DEVICE_CONTEXT_JOIN_SYNC 497030f984aSJacob Faibussowitsch .vb 498030f984aSJacob Faibussowitsch time -> 499030f984aSJacob Faibussowitsch 500030f984aSJacob Faibussowitsch -> dctx ---------/- dctx -\----> dctx ------> 501030f984aSJacob Faibussowitsch -> dsub[0] -----/ \---> dsub[0] ---> 502030f984aSJacob Faibussowitsch -> ... -------/ \--> ... -------> 503030f984aSJacob Faibussowitsch -> dsub[n-1] -/ \-> dsub[n-1] -> 504030f984aSJacob Faibussowitsch .ve 505030f984aSJacob Faibussowitsch 506030f984aSJacob Faibussowitsch Level: intermediate 507030f984aSJacob Faibussowitsch 508db781477SPatrick Sanan .seealso: `PetscDeviceContextFork()`, `PetscDeviceContextSynchronize()`, `PetscDeviceContextJoinMode` 509030f984aSJacob Faibussowitsch @*/ 5109371c9d4SSatish Balay PetscErrorCode PetscDeviceContextJoin(PetscDeviceContext dctx, PetscInt n, PetscDeviceContextJoinMode joinMode, PetscDeviceContext **dsub) { 511030f984aSJacob Faibussowitsch #if defined(PETSC_USE_DEBUG) && defined(PETSC_USE_INFO) 512030f984aSJacob Faibussowitsch static std::string idList; 513030f984aSJacob Faibussowitsch #endif 514030f984aSJacob Faibussowitsch 515030f984aSJacob Faibussowitsch PetscFunctionBegin; 516030f984aSJacob Faibussowitsch /* validity of dctx is checked in the wait-for loop */ 517030f984aSJacob Faibussowitsch PetscValidPointer(dsub, 4); 518bf025ffbSJacob Faibussowitsch PetscAssert(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of contexts merged %" PetscInt_FMT " < 0", n); 519030f984aSJacob Faibussowitsch #if defined(PETSC_USE_DEBUG) && defined(PETSC_USE_INFO) 520030f984aSJacob Faibussowitsch /* reserve 4 chars per id, 2 for number and 2 for ', ' separator */ 521030f984aSJacob Faibussowitsch idList.reserve(4 * n); 522030f984aSJacob Faibussowitsch #endif 523030f984aSJacob Faibussowitsch /* first dctx waits on all the incoming edges */ 524030f984aSJacob Faibussowitsch for (PetscInt i = 0; i < n; ++i) { 525030f984aSJacob Faibussowitsch PetscCheckCompatibleDeviceContexts(dctx, 1, (*dsub)[i], 4); 5269566063dSJacob Faibussowitsch PetscCall(PetscDeviceContextWaitForContext(dctx, (*dsub)[i])); 527030f984aSJacob Faibussowitsch #if defined(PETSC_USE_DEBUG) && defined(PETSC_USE_INFO) 528030f984aSJacob Faibussowitsch idList += std::to_string((*dsub)[i]->id); 529030f984aSJacob Faibussowitsch if (i + 1 < n) idList += ", "; 530030f984aSJacob Faibussowitsch #endif 531030f984aSJacob Faibussowitsch } 532030f984aSJacob Faibussowitsch 533030f984aSJacob Faibussowitsch /* now we handle the aftermath */ 534030f984aSJacob Faibussowitsch switch (joinMode) { 5359371c9d4SSatish Balay case PETSC_DEVICE_CONTEXT_JOIN_DESTROY: { 536030f984aSJacob Faibussowitsch PetscInt j = 0; 537030f984aSJacob Faibussowitsch 538bf025ffbSJacob Faibussowitsch PetscAssert(n <= dctx->numChildren, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy %" PetscInt_FMT " children of a parent context that only has %" PetscInt_FMT " children, likely trying to restore to wrong parent", n, dctx->numChildren); 539030f984aSJacob Faibussowitsch /* update child count while it's still fresh in memory */ 540030f984aSJacob Faibussowitsch dctx->numChildren -= n; 541030f984aSJacob Faibussowitsch for (PetscInt i = 0; i < dctx->maxNumChildren; ++i) { 542030f984aSJacob Faibussowitsch if (dctx->childIDs[i] && (dctx->childIDs[i] == (*dsub)[j]->id)) { 543030f984aSJacob Faibussowitsch /* child is one of ours, can destroy it */ 5449566063dSJacob Faibussowitsch PetscCall(PetscDeviceContextDestroy((*dsub) + j)); 545030f984aSJacob Faibussowitsch /* reset the child slot */ 546030f984aSJacob Faibussowitsch dctx->childIDs[i] = 0; 547030f984aSJacob Faibussowitsch if (++j == n) break; 548030f984aSJacob Faibussowitsch } 549030f984aSJacob Faibussowitsch } 550030f984aSJacob Faibussowitsch /* gone through the loop but did not find every child, if this triggers (or well, doesn't) on perf-builds we leak the remaining contexts memory */ 551bf025ffbSJacob Faibussowitsch PetscAssert(j == n, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "%" PetscInt_FMT " contexts still remain after destroy, this may be because you are trying to restore to the wrong parent context, or the device contexts are not in the same order as they were checked out out in.", n - j); 5529566063dSJacob Faibussowitsch PetscCall(PetscFree(*dsub)); 5539371c9d4SSatish Balay } break; 554030f984aSJacob Faibussowitsch case PETSC_DEVICE_CONTEXT_JOIN_SYNC: 5559566063dSJacob Faibussowitsch for (PetscInt i = 0; i < n; ++i) PetscCall(PetscDeviceContextWaitForContext((*dsub)[i], dctx)); 5569371c9d4SSatish Balay case PETSC_DEVICE_CONTEXT_JOIN_NO_SYNC: break; 5579371c9d4SSatish Balay default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown PetscDeviceContextJoinMode given"); 558030f984aSJacob Faibussowitsch } 559030f984aSJacob Faibussowitsch 560030f984aSJacob Faibussowitsch #if defined(PETSC_USE_DEBUG) && defined(PETSC_USE_INFO) 5619566063dSJacob Faibussowitsch PetscCall(PetscInfo(nullptr, "Joined %" PetscInt_FMT " ctxs to ctx %" PetscInt_FMT ", mode %s with IDs: %s\n", n, dctx->id, PetscDeviceContextJoinModes[joinMode], idList.c_str())); 562030f984aSJacob Faibussowitsch idList.clear(); 563030f984aSJacob Faibussowitsch #endif 564030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 565030f984aSJacob Faibussowitsch } 566030f984aSJacob Faibussowitsch 567030f984aSJacob Faibussowitsch /*@C 5685181c4f9SJacob Faibussowitsch PetscDeviceContextSynchronize - Block the host until all work queued on or associated with a PetscDeviceContext has finished 569030f984aSJacob Faibussowitsch 570030f984aSJacob Faibussowitsch Not Collective, Synchronous 571030f984aSJacob Faibussowitsch 572030f984aSJacob Faibussowitsch Input Parameters: 573030f984aSJacob Faibussowitsch . dctx - The PetscDeviceContext to synchronize 574030f984aSJacob Faibussowitsch 575030f984aSJacob Faibussowitsch Level: beginner 576030f984aSJacob Faibussowitsch 577db781477SPatrick Sanan .seealso: `PetscDeviceContextFork()`, `PetscDeviceContextJoin()`, `PetscDeviceContextQueryIdle()` 578030f984aSJacob Faibussowitsch @*/ 5799371c9d4SSatish Balay PetscErrorCode PetscDeviceContextSynchronize(PetscDeviceContext dctx) { 580030f984aSJacob Faibussowitsch PetscFunctionBegin; 581030f984aSJacob Faibussowitsch PetscValidDeviceContext(dctx, 1); 582030f984aSJacob Faibussowitsch /* if it isn't setup there is nothing to sync on */ 583dbbe0bcdSBarry Smith if (dctx->setup) PetscUseTypeMethod(dctx, synchronize); 584030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 585030f984aSJacob Faibussowitsch } 586030f984aSJacob Faibussowitsch 587a4af0ceeSJacob Faibussowitsch #define PETSC_DEVICE_CONTEXT_DEFAULT_DEVICE PETSC_DEVICE_DEFAULT 588a4af0ceeSJacob Faibussowitsch // REMOVE ME (change) 589a4af0ceeSJacob Faibussowitsch #define PETSC_DEVICE_CONTEXT_DEFAULT_STREAM PETSC_STREAM_GLOBAL_BLOCKING 590030f984aSJacob Faibussowitsch 591a4af0ceeSJacob Faibussowitsch static PetscDeviceType rootDeviceType = PETSC_DEVICE_CONTEXT_DEFAULT_DEVICE; 592a4af0ceeSJacob Faibussowitsch static PetscStreamType rootStreamType = PETSC_DEVICE_CONTEXT_DEFAULT_STREAM; 593bf025ffbSJacob Faibussowitsch static PetscDeviceContext globalContext = nullptr; 594a4af0ceeSJacob Faibussowitsch 595a4af0ceeSJacob Faibussowitsch /* when PetsDevice initializes PetscDeviceContext eagerly the type of device created should 596a4af0ceeSJacob Faibussowitsch * match whatever device is eagerly intialized */ 5979371c9d4SSatish Balay PetscErrorCode PetscDeviceContextSetRootDeviceType_Internal(PetscDeviceType type) { 598030f984aSJacob Faibussowitsch PetscFunctionBegin; 599a4af0ceeSJacob Faibussowitsch PetscValidDeviceType(type, 1); 600a4af0ceeSJacob Faibussowitsch rootDeviceType = type; 601030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 602030f984aSJacob Faibussowitsch } 603030f984aSJacob Faibussowitsch 604a4af0ceeSJacob Faibussowitsch #if 0 605a4af0ceeSJacob Faibussowitsch /* currently unused */ 606a4af0ceeSJacob Faibussowitsch PetscErrorCode PetscDeviceContextSetRootStreamType_Internal(PetscStreamType type) 607030f984aSJacob Faibussowitsch { 608a4af0ceeSJacob Faibussowitsch PetscFunctionBegin; 609a4af0ceeSJacob Faibussowitsch PetscValidStreamType(type,1); 610a4af0ceeSJacob Faibussowitsch rootStreamType = type; 611a4af0ceeSJacob Faibussowitsch PetscFunctionReturn(0); 612a4af0ceeSJacob Faibussowitsch } 613a4af0ceeSJacob Faibussowitsch #endif 614a4af0ceeSJacob Faibussowitsch 6159371c9d4SSatish Balay static PetscErrorCode PetscDeviceContextSetupGlobalContext_Private(void) { 616a4af0ceeSJacob Faibussowitsch static const auto PetscDeviceContextFinalizer = []() -> PetscErrorCode { 617030f984aSJacob Faibussowitsch PetscFunctionBegin; 6189566063dSJacob Faibussowitsch PetscCall(PetscDeviceContextDestroy(&globalContext)); 619a4af0ceeSJacob Faibussowitsch rootDeviceType = PETSC_DEVICE_CONTEXT_DEFAULT_DEVICE; 620a4af0ceeSJacob Faibussowitsch rootStreamType = PETSC_DEVICE_CONTEXT_DEFAULT_STREAM; 621a4af0ceeSJacob Faibussowitsch PetscFunctionReturn(0); 622a4af0ceeSJacob Faibussowitsch }; 623a4af0ceeSJacob Faibussowitsch 624a4af0ceeSJacob Faibussowitsch PetscFunctionBegin; 625a4af0ceeSJacob Faibussowitsch if (globalContext) PetscFunctionReturn(0); 626a4af0ceeSJacob Faibussowitsch /* this exists purely as a valid device check. */ 6279566063dSJacob Faibussowitsch PetscCall(PetscDeviceInitializePackage()); 6289566063dSJacob Faibussowitsch PetscCall(PetscRegisterFinalize(PetscDeviceContextFinalizer)); 6299566063dSJacob Faibussowitsch PetscCall(PetscInfo(nullptr, "Initializing global PetscDeviceContext\n")); 630a4af0ceeSJacob Faibussowitsch /* we call the allocator directly here since the ObjectPool creates a PetscContainer which 631a4af0ceeSJacob Faibussowitsch * eventually tries to call logging functions. However, this routine may be purposefully 632a4af0ceeSJacob Faibussowitsch * called __before__ logging is initialized, so the logging function would PETSCABORT */ 6339566063dSJacob Faibussowitsch PetscCall(contextPool.allocator().create(&globalContext)); 6349566063dSJacob Faibussowitsch PetscCall(PetscDeviceContextSetStreamType(globalContext, rootStreamType)); 6359566063dSJacob Faibussowitsch PetscCall(PetscDeviceContextSetDefaultDeviceForType_Internal(globalContext, rootDeviceType)); 6369566063dSJacob Faibussowitsch PetscCall(PetscDeviceContextSetUp(globalContext)); 637030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 638030f984aSJacob Faibussowitsch } 639030f984aSJacob Faibussowitsch 640030f984aSJacob Faibussowitsch /*@C 6415181c4f9SJacob Faibussowitsch PetscDeviceContextGetCurrentContext - Get the current active PetscDeviceContext 642030f984aSJacob Faibussowitsch 643030f984aSJacob Faibussowitsch Not Collective, Asynchronous 644030f984aSJacob Faibussowitsch 645030f984aSJacob Faibussowitsch Output Parameter: 646030f984aSJacob Faibussowitsch . dctx - The PetscDeviceContext 647030f984aSJacob Faibussowitsch 648030f984aSJacob Faibussowitsch Notes: 649a4af0ceeSJacob Faibussowitsch The user generally should not destroy contexts retrieved with this routine unless they 650a4af0ceeSJacob Faibussowitsch themselves have created them. There exists no protection against destroying the root 651a4af0ceeSJacob Faibussowitsch context. 652030f984aSJacob Faibussowitsch 653030f984aSJacob Faibussowitsch Developer Notes: 654a4af0ceeSJacob Faibussowitsch Unless the user has set their own, this routine creates the "root" context the first time it 655a4af0ceeSJacob Faibussowitsch is called, registering its destructor to PetscFinalize(). 656030f984aSJacob Faibussowitsch 657030f984aSJacob Faibussowitsch Level: beginner 658030f984aSJacob Faibussowitsch 659db781477SPatrick Sanan .seealso: `PetscDeviceContextSetCurrentContext()`, `PetscDeviceContextFork()`, 660db781477SPatrick Sanan `PetscDeviceContextJoin()`, `PetscDeviceContextCreate()` 661030f984aSJacob Faibussowitsch @*/ 6629371c9d4SSatish Balay PetscErrorCode PetscDeviceContextGetCurrentContext(PetscDeviceContext *dctx) { 663a4af0ceeSJacob Faibussowitsch PetscFunctionBegin; 664a4af0ceeSJacob Faibussowitsch PetscValidPointer(dctx, 1); 6659566063dSJacob Faibussowitsch PetscCall(PetscDeviceContextSetupGlobalContext_Private()); 666a4af0ceeSJacob Faibussowitsch /* while the static analyzer can find global variables, it will throw a warning about not 667a4af0ceeSJacob Faibussowitsch * being able to connect this back to the function arguments */ 668a4af0ceeSJacob Faibussowitsch PetscDisableStaticAnalyzerForExpressionUnderstandingThatThisIsDangerousAndBugprone(PetscValidDeviceContext(globalContext, -1)); 669030f984aSJacob Faibussowitsch *dctx = globalContext; 670030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 671030f984aSJacob Faibussowitsch } 672030f984aSJacob Faibussowitsch 673030f984aSJacob Faibussowitsch /*@C 6745181c4f9SJacob Faibussowitsch PetscDeviceContextSetCurrentContext - Set the current active PetscDeviceContext 675030f984aSJacob Faibussowitsch 676030f984aSJacob Faibussowitsch Not Collective, Asynchronous 677030f984aSJacob Faibussowitsch 678030f984aSJacob Faibussowitsch Input Parameter: 679030f984aSJacob Faibussowitsch . dctx - The PetscDeviceContext 680030f984aSJacob Faibussowitsch 681030f984aSJacob Faibussowitsch Notes: 682a4af0ceeSJacob Faibussowitsch This routine can be used to set the defacto "root" PetscDeviceContext to a user-defined 683a4af0ceeSJacob Faibussowitsch implementation by calling this routine immediately after PetscInitialize() and ensuring that 684a4af0ceeSJacob Faibussowitsch PetscDevice is not greedily intialized. In this case the user is responsible for destroying 685a4af0ceeSJacob Faibussowitsch their PetscDeviceContext before PetscFinalize() returns. 686a4af0ceeSJacob Faibussowitsch 687a4af0ceeSJacob Faibussowitsch The old context is not stored in any way by this routine; if one is overriding a context that 688a4af0ceeSJacob Faibussowitsch they themselves do not control, one should take care to temporarily store it by calling 689a4af0ceeSJacob Faibussowitsch PetscDeviceContextGetCurrentContext() before calling this routine. 690030f984aSJacob Faibussowitsch 691030f984aSJacob Faibussowitsch Level: beginner 692030f984aSJacob Faibussowitsch 693db781477SPatrick Sanan .seealso: `PetscDeviceContextGetCurrentContext()`, `PetscDeviceContextFork()`, 694db781477SPatrick Sanan `PetscDeviceContextJoin()`, `PetscDeviceContextCreate()` 695030f984aSJacob Faibussowitsch @*/ 6969371c9d4SSatish Balay PetscErrorCode PetscDeviceContextSetCurrentContext(PetscDeviceContext dctx) { 697030f984aSJacob Faibussowitsch PetscFunctionBegin; 698030f984aSJacob Faibussowitsch PetscValidDeviceContext(dctx, 1); 699bf025ffbSJacob Faibussowitsch PetscAssert(dctx->setup, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "PetscDeviceContext %" PetscInt_FMT " must be set up before being set as global context", dctx->id); 700030f984aSJacob Faibussowitsch globalContext = dctx; 7019566063dSJacob Faibussowitsch PetscCall(PetscInfo(nullptr, "Set global PetscDeviceContext id %" PetscInt_FMT "\n", dctx->id)); 702030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 703030f984aSJacob Faibussowitsch } 704030f984aSJacob Faibussowitsch 705030f984aSJacob Faibussowitsch /*@C 706030f984aSJacob Faibussowitsch PetscDeviceContextSetFromOptions - Configure a PetscDeviceContext from the options database 707030f984aSJacob Faibussowitsch 708030f984aSJacob Faibussowitsch Collective on comm, Asynchronous 709030f984aSJacob Faibussowitsch 710030f984aSJacob Faibussowitsch Input Parameters: 711030f984aSJacob Faibussowitsch + comm - MPI communicator on which to query the options database 712030f984aSJacob Faibussowitsch . prefix - prefix to prepend to all options database queries, NULL if not needed 713030f984aSJacob Faibussowitsch - dctx - The PetscDeviceContext to configure 714030f984aSJacob Faibussowitsch 715030f984aSJacob Faibussowitsch Output Parameter: 716030f984aSJacob Faibussowitsch . dctx - The PetscDeviceContext 717030f984aSJacob Faibussowitsch 718030f984aSJacob Faibussowitsch Options Database: 719a4af0ceeSJacob Faibussowitsch + -device_context_stream_type - type of stream to create inside the PetscDeviceContext - 720030f984aSJacob Faibussowitsch PetscDeviceContextSetStreamType() 721a4af0ceeSJacob Faibussowitsch - -device_context_device_type - the type of PetscDevice to attach by default - PetscDeviceType 722030f984aSJacob Faibussowitsch 723030f984aSJacob Faibussowitsch Level: beginner 724030f984aSJacob Faibussowitsch 725db781477SPatrick Sanan .seealso: `PetscDeviceContextSetStreamType()`, `PetscDeviceContextSetDevice()` 726030f984aSJacob Faibussowitsch @*/ 7279371c9d4SSatish Balay PetscErrorCode PetscDeviceContextSetFromOptions(MPI_Comm comm, const char prefix[], PetscDeviceContext dctx) { 728030f984aSJacob Faibussowitsch PetscBool flag; 729a4af0ceeSJacob Faibussowitsch PetscInt stype, dtype; 730030f984aSJacob Faibussowitsch 731030f984aSJacob Faibussowitsch PetscFunctionBegin; 732a4af0ceeSJacob Faibussowitsch if (prefix) PetscValidCharPointer(prefix, 2); 733030f984aSJacob Faibussowitsch PetscValidDeviceContext(dctx, 3); 734d0609cedSBarry Smith PetscOptionsBegin(comm, prefix, "PetscDeviceContext Options", "Sys"); 7359566063dSJacob Faibussowitsch PetscCall(PetscOptionsEList("-device_context_stream_type", "PetscDeviceContext PetscStreamType", "PetscDeviceContextSetStreamType", PetscStreamTypes, PETSC_STREAM_MAX, PetscStreamTypes[dctx->streamType], &stype, &flag)); 7369566063dSJacob Faibussowitsch if (flag) PetscCall(PetscDeviceContextSetStreamType(dctx, static_cast<PetscStreamType>(stype))); 7379566063dSJacob Faibussowitsch PetscCall(PetscOptionsEList("-device_context_device_type", "Underlying PetscDevice", "PetscDeviceContextSetDevice", PetscDeviceTypes + 1, PETSC_DEVICE_MAX - 1, dctx->device ? PetscDeviceTypes[dctx->device->type] : PetscDeviceTypes[PETSC_DEVICE_CONTEXT_DEFAULT_DEVICE], &dtype, &flag)); 738*48a46eb9SPierre Jolivet if (flag) PetscCall(PetscDeviceContextSetDefaultDeviceForType_Internal(dctx, static_cast<PetscDeviceType>(dtype + 1))); 739d0609cedSBarry Smith PetscOptionsEnd(); 740030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 741030f984aSJacob Faibussowitsch } 742