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 51*811af0c4SBarry Smith PetscDeviceContextCreate - Creates a `PetscDeviceContext` 52030f984aSJacob Faibussowitsch 53030f984aSJacob Faibussowitsch Not Collective, Asynchronous 54030f984aSJacob Faibussowitsch 5501d2d390SJose E. Roman Output Paramemter: 56*811af0c4SBarry Smith . dctx - The `PetscDeviceContext` 57030f984aSJacob Faibussowitsch 58*811af0c4SBarry Smith Note: 59030f984aSJacob Faibussowitsch Unlike almost every other PETSc class it is advised that most users use 60*811af0c4SBarry Smith `PetscDeviceContextDuplicate()` rather than this routine to create new contexts. Contexts 61030f984aSJacob Faibussowitsch of different types are incompatible with one another; using 62*811af0c4SBarry Smith `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 79*811af0c4SBarry Smith PetscDeviceContextDestroy - Frees a `PetscDeviceContext` 80030f984aSJacob Faibussowitsch 81030f984aSJacob Faibussowitsch Not Collective, Asynchronous 82030f984aSJacob Faibussowitsch 83030f984aSJacob Faibussowitsch Input Parameters: 84*811af0c4SBarry Smith . dctx - The `PetscDeviceContext` 85030f984aSJacob Faibussowitsch 86*811af0c4SBarry Smith Note: 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 91*811af0c4SBarry Smith Developer Note: 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 109*811af0c4SBarry Smith 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: 114*811af0c4SBarry Smith + dctx - The `PetscDeviceContext` 115*811af0c4SBarry Smith - type - The `PetscStreamType` 116030f984aSJacob Faibussowitsch 117030f984aSJacob Faibussowitsch Notes: 118*811af0c4SBarry Smith See `PetscStreamType` in `include/petscdevicetypes.h` for more information on the available 119*811af0c4SBarry Smith types and their interactions. 120*811af0c4SBarry Smith 121*811af0c4SBarry Smith If the `PetscDeviceContext` was previously set up and stream 122*811af0c4SBarry Smith type was changed, you must call `PetscDeviceContextSetUp()` again after this routine. 123030f984aSJacob Faibussowitsch 124030f984aSJacob Faibussowitsch Level: intermediate 125030f984aSJacob Faibussowitsch 126db781477SPatrick Sanan .seealso: `PetscStreamType`, `PetscDeviceContextGetStreamType()`, `PetscDeviceContextCreate()`, `PetscDeviceContextSetUp()`, `PetscDeviceContextSetFromOptions()` 127030f984aSJacob Faibussowitsch @*/ 1289371c9d4SSatish Balay PetscErrorCode PetscDeviceContextSetStreamType(PetscDeviceContext dctx, PetscStreamType type) { 129030f984aSJacob Faibussowitsch PetscFunctionBegin; 130030f984aSJacob Faibussowitsch PetscValidDeviceContext(dctx, 1); 131030f984aSJacob Faibussowitsch PetscValidStreamType(type, 2); 132030f984aSJacob Faibussowitsch /* only need to do complex swapping if the object has already been setup */ 133030f984aSJacob Faibussowitsch if (dctx->setup && (dctx->streamType != type)) { 134dbbe0bcdSBarry Smith PetscUseTypeMethod(dctx, changestreamtype, type); 135030f984aSJacob Faibussowitsch dctx->setup = PETSC_FALSE; 136030f984aSJacob Faibussowitsch } 137030f984aSJacob Faibussowitsch dctx->streamType = type; 138030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 139030f984aSJacob Faibussowitsch } 140030f984aSJacob Faibussowitsch 141030f984aSJacob Faibussowitsch /*@C 142*811af0c4SBarry Smith PetscDeviceContextGetStreamType - Get the implementation type of the underlying stream for a `PetscDeviceContext` 143030f984aSJacob Faibussowitsch 144030f984aSJacob Faibussowitsch Not Collective, Asynchronous 145030f984aSJacob Faibussowitsch 14601d2d390SJose E. Roman Input Parameter: 147*811af0c4SBarry Smith . dctx - The `PetscDeviceContext` 148030f984aSJacob Faibussowitsch 149030f984aSJacob Faibussowitsch Output Parameter: 150*811af0c4SBarry Smith . type - The `PetscStreamType` 151030f984aSJacob Faibussowitsch 152*811af0c4SBarry Smith Note: 153*811af0c4SBarry Smith See `PetscStreamType` in `include/petscdevicetypes.h` for more information on the available types and their interactions 154030f984aSJacob Faibussowitsch 155030f984aSJacob Faibussowitsch Level: intermediate 156030f984aSJacob Faibussowitsch 157db781477SPatrick Sanan .seealso: `PetscDeviceContextSetStreamType()`, `PetscDeviceContextCreate()`, `PetscDeviceContextSetFromOptions()` 158030f984aSJacob Faibussowitsch @*/ 1599371c9d4SSatish Balay PetscErrorCode PetscDeviceContextGetStreamType(PetscDeviceContext dctx, PetscStreamType *type) { 160030f984aSJacob Faibussowitsch PetscFunctionBegin; 161030f984aSJacob Faibussowitsch PetscValidDeviceContext(dctx, 1); 162030f984aSJacob Faibussowitsch PetscValidIntPointer(type, 2); 163030f984aSJacob Faibussowitsch *type = dctx->streamType; 164030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 165030f984aSJacob Faibussowitsch } 166030f984aSJacob Faibussowitsch 167030f984aSJacob Faibussowitsch /*@C 168*811af0c4SBarry Smith PetscDeviceContextSetDevice - Set the underlying device for the `PetscDeviceContext` 169030f984aSJacob Faibussowitsch 170030f984aSJacob Faibussowitsch Not Collective, Possibly Synchronous 171030f984aSJacob Faibussowitsch 17201d2d390SJose E. Roman Input Parameters: 173*811af0c4SBarry Smith + dctx - The `PetscDeviceContext` 174*811af0c4SBarry Smith - device - The `PetscDevice` 175030f984aSJacob Faibussowitsch 176030f984aSJacob Faibussowitsch Notes: 177*811af0c4SBarry Smith This routine is effectively `PetscDeviceContext`'s "set-type" (so every `PetscDeviceContext` 178*811af0c4SBarry Smith must also have an attached `PetscDevice`). Unlike the usual set-type semantics, it is 179030f984aSJacob Faibussowitsch not stricly necessary to set a contexts device to enable usage, any created device 180030f984aSJacob Faibussowitsch contexts will always come equipped with the "default" device. 181030f984aSJacob Faibussowitsch 182a4af0ceeSJacob Faibussowitsch This routine is a no-op if dctx is already attached to device. 183a4af0ceeSJacob Faibussowitsch 1845181c4f9SJacob Faibussowitsch This routine may initialize the backend device and incur synchronization. 1855181c4f9SJacob Faibussowitsch 186030f984aSJacob Faibussowitsch Level: intermediate 187030f984aSJacob Faibussowitsch 188db781477SPatrick Sanan .seealso: `PetscDeviceCreate()`, `PetscDeviceConfigure()`, `PetscDeviceContextGetDevice()` 189030f984aSJacob Faibussowitsch @*/ 1909371c9d4SSatish Balay PetscErrorCode PetscDeviceContextSetDevice(PetscDeviceContext dctx, PetscDevice device) { 191030f984aSJacob Faibussowitsch PetscFunctionBegin; 192030f984aSJacob Faibussowitsch PetscValidDeviceContext(dctx, 1); 193030f984aSJacob Faibussowitsch PetscValidDevice(device, 2); 194a4af0ceeSJacob Faibussowitsch if (dctx->device) { 195a4af0ceeSJacob Faibussowitsch /* can't do a strict pointer equality check since PetscDevice's are reused */ 196a4af0ceeSJacob Faibussowitsch if (dctx->device->ops->createcontext == device->ops->createcontext) PetscFunctionReturn(0); 197a4af0ceeSJacob Faibussowitsch } 1989566063dSJacob Faibussowitsch PetscCall(PetscDeviceDestroy(&dctx->device)); 199dbbe0bcdSBarry Smith PetscTryTypeMethod(dctx, destroy); 2009566063dSJacob Faibussowitsch PetscCall(PetscMemzero(dctx->ops, sizeof(*dctx->ops))); 2019566063dSJacob Faibussowitsch PetscCall((*device->ops->createcontext)(dctx)); 2029566063dSJacob Faibussowitsch PetscCall(PetscDeviceReference_Internal(device)); 203a4af0ceeSJacob Faibussowitsch dctx->device = device; 204030f984aSJacob Faibussowitsch dctx->setup = PETSC_FALSE; 205030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 206030f984aSJacob Faibussowitsch } 207030f984aSJacob Faibussowitsch 208030f984aSJacob Faibussowitsch /*@C 209*811af0c4SBarry Smith PetscDeviceContextGetDevice - Get the underlying `PetscDevice` for a `PetscDeviceContext` 210030f984aSJacob Faibussowitsch 211030f984aSJacob Faibussowitsch Not Collective, Asynchronous 212030f984aSJacob Faibussowitsch 213030f984aSJacob Faibussowitsch Input Parameter: 214*811af0c4SBarry Smith . dctx - the `PetscDeviceContext` 215030f984aSJacob Faibussowitsch 216030f984aSJacob Faibussowitsch Output Parameter: 217*811af0c4SBarry Smith . device - The `PetscDevice` 218030f984aSJacob Faibussowitsch 219*811af0c4SBarry Smith Note: 220*811af0c4SBarry Smith This is a borrowed reference, the user should not destroy `device`. 221030f984aSJacob Faibussowitsch 222a375dbeeSPatrick Sanan Level: intermediate 223a375dbeeSPatrick Sanan 224db781477SPatrick Sanan .seealso: `PetscDeviceContextSetDevice()`, `PetscDevice` 225030f984aSJacob Faibussowitsch @*/ 2269371c9d4SSatish Balay PetscErrorCode PetscDeviceContextGetDevice(PetscDeviceContext dctx, PetscDevice *device) { 227030f984aSJacob Faibussowitsch PetscFunctionBegin; 228030f984aSJacob Faibussowitsch PetscValidDeviceContext(dctx, 1); 229030f984aSJacob Faibussowitsch PetscValidPointer(device, 2); 230bf025ffbSJacob Faibussowitsch PetscAssert(dctx->device, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "PetscDeviceContext %" PetscInt_FMT " has no attached PetscDevice to get", dctx->id); 231030f984aSJacob Faibussowitsch *device = dctx->device; 232030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 233030f984aSJacob Faibussowitsch } 234030f984aSJacob Faibussowitsch 235030f984aSJacob Faibussowitsch /*@C 236*811af0c4SBarry Smith PetscDeviceContextSetUp - Prepares a `PetscDeviceContext` for use 237030f984aSJacob Faibussowitsch 238030f984aSJacob Faibussowitsch Not Collective, Asynchronous 239030f984aSJacob Faibussowitsch 24001d2d390SJose E. Roman Input Parameter: 241*811af0c4SBarry Smith . dctx - The `PetscDeviceContext` 242030f984aSJacob Faibussowitsch 243*811af0c4SBarry Smith Developer Note: 244*811af0c4SBarry Smith This routine is usually the stage where a `PetscDeviceContext` acquires device-side data structures such as streams, 245030f984aSJacob Faibussowitsch events, and (possibly) handles. 246030f984aSJacob Faibussowitsch 247030f984aSJacob Faibussowitsch Level: beginner 248030f984aSJacob Faibussowitsch 249db781477SPatrick Sanan .seealso: `PetscDeviceContextCreate()`, `PetscDeviceContextSetDevice()`, `PetscDeviceContextDestroy()`, `PetscDeviceContextSetFromOptions()` 250030f984aSJacob Faibussowitsch @*/ 2519371c9d4SSatish Balay PetscErrorCode PetscDeviceContextSetUp(PetscDeviceContext dctx) { 252030f984aSJacob Faibussowitsch PetscFunctionBegin; 253030f984aSJacob Faibussowitsch PetscValidDeviceContext(dctx, 1); 254030f984aSJacob Faibussowitsch if (!dctx->device) { 2559566063dSJacob 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])); 2569566063dSJacob Faibussowitsch PetscCall(PetscDeviceContextSetDefaultDevice_Internal(dctx)); 257030f984aSJacob Faibussowitsch } 258030f984aSJacob Faibussowitsch if (dctx->setup) PetscFunctionReturn(0); 259dbbe0bcdSBarry Smith PetscUseTypeMethod(dctx, setup); 260030f984aSJacob Faibussowitsch dctx->setup = PETSC_TRUE; 261030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 262030f984aSJacob Faibussowitsch } 263030f984aSJacob Faibussowitsch 264030f984aSJacob Faibussowitsch /*@C 265*811af0c4SBarry Smith PetscDeviceContextDuplicate - Duplicates a `PetscDeviceContext` object 266030f984aSJacob Faibussowitsch 267030f984aSJacob Faibussowitsch Not Collective, Asynchronous 268030f984aSJacob Faibussowitsch 269030f984aSJacob Faibussowitsch Input Parameter: 270*811af0c4SBarry Smith . dctx - The `PetscDeviceContext` to duplicate 271030f984aSJacob Faibussowitsch 2726aad120cSJose E. Roman Output Parameter: 273*811af0c4SBarry Smith . dctxdup - The duplicated `PetscDeviceContext` 274030f984aSJacob Faibussowitsch 275*811af0c4SBarry Smith Note: 276*811af0c4SBarry Smith This is a shorthand method for creating a `PetscDeviceContext` with the exact same 277*811af0c4SBarry Smith settings as another. However the `dctxdup` does not "share" 278030f984aSJacob Faibussowitsch any of the underlying data with the original, (including its current stream-state) they 279030f984aSJacob Faibussowitsch are completely separate objects. 280030f984aSJacob Faibussowitsch 281030f984aSJacob Faibussowitsch Level: beginner 282030f984aSJacob Faibussowitsch 283db781477SPatrick Sanan .seealso: `PetscDeviceContextCreate()`, `PetscDeviceContextSetDevice()`, `PetscDeviceContextSetStreamType()` 284030f984aSJacob Faibussowitsch @*/ 2859371c9d4SSatish Balay PetscErrorCode PetscDeviceContextDuplicate(PetscDeviceContext dctx, PetscDeviceContext *dctxdup) { 286a4af0ceeSJacob Faibussowitsch PetscDeviceContext dup; 287030f984aSJacob Faibussowitsch 288030f984aSJacob Faibussowitsch PetscFunctionBegin; 289030f984aSJacob Faibussowitsch PetscValidDeviceContext(dctx, 1); 290030f984aSJacob Faibussowitsch PetscValidPointer(dctxdup, 2); 2919566063dSJacob Faibussowitsch PetscCall(PetscDeviceContextCreate(&dup)); 2929566063dSJacob Faibussowitsch PetscCall(PetscDeviceContextSetStreamType(dup, dctx->streamType)); 2939566063dSJacob Faibussowitsch if (dctx->device) PetscCall(PetscDeviceContextSetDevice(dup, dctx->device)); 2949566063dSJacob Faibussowitsch PetscCall(PetscDeviceContextSetUp(dup)); 295a4af0ceeSJacob Faibussowitsch *dctxdup = dup; 296030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 297030f984aSJacob Faibussowitsch } 298030f984aSJacob Faibussowitsch 299030f984aSJacob Faibussowitsch /*@C 300*811af0c4SBarry Smith PetscDeviceContextQueryIdle - Returns whether or not a `PetscDeviceContext` is idle 301030f984aSJacob Faibussowitsch 302030f984aSJacob Faibussowitsch Not Collective, Asynchronous 303030f984aSJacob Faibussowitsch 304030f984aSJacob Faibussowitsch Input Parameter: 305*811af0c4SBarry Smith . dctx - The `PetscDeviceContext` object 306030f984aSJacob Faibussowitsch 307030f984aSJacob Faibussowitsch Output Parameter: 308*811af0c4SBarry Smith . idle - `PETSC_TRUE` if `PetscDeviceContext` has NO work, `PETSC_FALSE` if it has work 309030f984aSJacob Faibussowitsch 310*811af0c4SBarry Smith Note: 311ef657721SJacob Faibussowitsch This routine only refers a singular context and does NOT take any of its children into 312*811af0c4SBarry Smith account. That is, if `dctx` is idle but has dependents who do have work, this routine still 313*811af0c4SBarry Smith returns `PETSC_TRUE`. 314030f984aSJacob Faibussowitsch 315030f984aSJacob Faibussowitsch Level: intermediate 316030f984aSJacob Faibussowitsch 317db781477SPatrick Sanan .seealso: `PetscDeviceContextCreate()`, `PetscDeviceContextWaitForContext()`, `PetscDeviceContextFork()` 318030f984aSJacob Faibussowitsch @*/ 3199371c9d4SSatish Balay PetscErrorCode PetscDeviceContextQueryIdle(PetscDeviceContext dctx, PetscBool *idle) { 320030f984aSJacob Faibussowitsch PetscFunctionBegin; 321030f984aSJacob Faibussowitsch PetscValidDeviceContext(dctx, 1); 322030f984aSJacob Faibussowitsch PetscValidBoolPointer(idle, 2); 323dbbe0bcdSBarry Smith PetscUseTypeMethod(dctx, query, idle); 3249566063dSJacob Faibussowitsch PetscCall(PetscInfo(nullptr, "PetscDeviceContext id %" PetscInt_FMT " %s idle\n", dctx->id, *idle ? "was" : "was not")); 325030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 326030f984aSJacob Faibussowitsch } 327030f984aSJacob Faibussowitsch 328030f984aSJacob Faibussowitsch /*@C 329030f984aSJacob Faibussowitsch PetscDeviceContextWaitForContext - Make one context wait for another context to finish 330030f984aSJacob Faibussowitsch 331030f984aSJacob Faibussowitsch Not Collective, Asynchronous 332030f984aSJacob Faibussowitsch 333030f984aSJacob Faibussowitsch Input Parameters: 334*811af0c4SBarry Smith + dctxa - The `PetscDeviceContext` object that is waiting 335*811af0c4SBarry Smith - dctxb - The `PetscDeviceContext` object that is being waited on 336030f984aSJacob Faibussowitsch 337030f984aSJacob Faibussowitsch Notes: 338*811af0c4SBarry Smith Serializes two `PetscDeviceContexts`. This routine uses only the state of `dctxb` at the moment this routine was 339*811af0c4SBarry Smith called, so any future work queued will not affect `dctxa`. 340*811af0c4SBarry Smith 341*811af0c4SBarry Smith It is safe to pass the same context to both arguments. 342030f984aSJacob Faibussowitsch 343030f984aSJacob Faibussowitsch Level: beginner 344030f984aSJacob Faibussowitsch 345db781477SPatrick Sanan .seealso: `PetscDeviceContextCreate()`, `PetscDeviceContextQueryIdle()`, `PetscDeviceContextJoin()` 346030f984aSJacob Faibussowitsch @*/ 3479371c9d4SSatish Balay PetscErrorCode PetscDeviceContextWaitForContext(PetscDeviceContext dctxa, PetscDeviceContext dctxb) { 348030f984aSJacob Faibussowitsch PetscFunctionBegin; 349030f984aSJacob Faibussowitsch PetscCheckCompatibleDeviceContexts(dctxa, 1, dctxb, 2); 350030f984aSJacob Faibussowitsch if (dctxa == dctxb) PetscFunctionReturn(0); 351dbbe0bcdSBarry Smith PetscUseTypeMethod(dctxa, waitforcontext, dctxb); 352030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 353030f984aSJacob Faibussowitsch } 354030f984aSJacob Faibussowitsch 355050c0c3dSJacob Faibussowitsch #define PETSC_USE_DEBUG_AND_INFO (PetscDefined(USE_DEBUG) && PetscDefined(USE_INFO)) 356050c0c3dSJacob Faibussowitsch #if PETSC_USE_DEBUG_AND_INFO 357050c0c3dSJacob Faibussowitsch #include <string> 358050c0c3dSJacob Faibussowitsch #endif 359030f984aSJacob Faibussowitsch /*@C 360030f984aSJacob Faibussowitsch PetscDeviceContextFork - Create a set of dependent child contexts from a parent context 361030f984aSJacob Faibussowitsch 362030f984aSJacob Faibussowitsch Not Collective, Asynchronous 363030f984aSJacob Faibussowitsch 364030f984aSJacob Faibussowitsch Input Parameters: 365*811af0c4SBarry Smith + dctx - The parent `PetscDeviceContext` 366030f984aSJacob Faibussowitsch - n - The number of children to create 367030f984aSJacob Faibussowitsch 368030f984aSJacob Faibussowitsch Output Parameter: 369030f984aSJacob Faibussowitsch . dsub - The created child context(s) 370030f984aSJacob Faibussowitsch 371030f984aSJacob Faibussowitsch Notes: 372030f984aSJacob Faibussowitsch This routine creates n edges of a DAG from a source node which are causally dependent on the source node, meaning 373030f984aSJacob Faibussowitsch that work queued on child contexts will not start until the parent context finishes its work. This accounts for work 374030f984aSJacob Faibussowitsch queued on the parent up until calling this function, any subsequent work enqueued on the parent has no effect on the children. 375030f984aSJacob Faibussowitsch 376030f984aSJacob Faibussowitsch Any children created with this routine have their lifetimes bounded by the parent. That is, the parent context expects 377030f984aSJacob Faibussowitsch to free all of it's children (and ONLY its children) before itself is freed. 378030f984aSJacob Faibussowitsch 379030f984aSJacob Faibussowitsch DAG representation: 380030f984aSJacob Faibussowitsch .vb 381030f984aSJacob Faibussowitsch time -> 382030f984aSJacob Faibussowitsch 383030f984aSJacob Faibussowitsch -> dctx \----> dctx ------> 384030f984aSJacob Faibussowitsch \---> dsub[0] ---> 385030f984aSJacob Faibussowitsch \--> ... -------> 386030f984aSJacob Faibussowitsch \-> dsub[n-1] -> 387030f984aSJacob Faibussowitsch .ve 388030f984aSJacob Faibussowitsch 389030f984aSJacob Faibussowitsch Level: intermediate 390030f984aSJacob Faibussowitsch 391db781477SPatrick Sanan .seealso: `PetscDeviceContextJoin()`, `PetscDeviceContextSynchronize()`, `PetscDeviceContextQueryIdle()` 392030f984aSJacob Faibussowitsch @*/ 3939371c9d4SSatish Balay PetscErrorCode PetscDeviceContextFork(PetscDeviceContext dctx, PetscInt n, PetscDeviceContext **dsub) { 394050c0c3dSJacob Faibussowitsch #if PETSC_USE_DEBUG_AND_INFO 395030f984aSJacob Faibussowitsch const PetscInt nBefore = n; 396030f984aSJacob Faibussowitsch static std::string idList; 397030f984aSJacob Faibussowitsch #endif 398bf025ffbSJacob Faibussowitsch PetscDeviceContext *dsubTmp = nullptr; 399030f984aSJacob Faibussowitsch PetscInt i = 0; 400030f984aSJacob Faibussowitsch 401030f984aSJacob Faibussowitsch PetscFunctionBegin; 402030f984aSJacob Faibussowitsch PetscValidDeviceContext(dctx, 1); 403030f984aSJacob Faibussowitsch PetscValidPointer(dsub, 3); 404bf025ffbSJacob Faibussowitsch PetscAssert(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of contexts requested %" PetscInt_FMT " < 0", n); 4053ca90d2dSJacob Faibussowitsch #if PETSC_USE_DEBUG_AND_INFO 406030f984aSJacob Faibussowitsch /* reserve 4 chars per id, 2 for number and 2 for ', ' separator */ 407030f984aSJacob Faibussowitsch idList.reserve(4 * n); 408030f984aSJacob Faibussowitsch #endif 409030f984aSJacob Faibussowitsch /* update child totals */ 410030f984aSJacob Faibussowitsch dctx->numChildren += n; 411030f984aSJacob Faibussowitsch /* now to find out if we have room */ 412030f984aSJacob Faibussowitsch if (dctx->numChildren > dctx->maxNumChildren) { 413030f984aSJacob Faibussowitsch /* no room, either from having too many kids or not having any */ 414030f984aSJacob Faibussowitsch if (dctx->childIDs) { 415030f984aSJacob Faibussowitsch /* have existing children, must reallocate them */ 4169566063dSJacob Faibussowitsch PetscCall(PetscRealloc(dctx->numChildren * sizeof(*dctx->childIDs), &dctx->childIDs)); 417030f984aSJacob Faibussowitsch /* clear the extra memory since realloc doesn't do it for us */ 4189566063dSJacob Faibussowitsch PetscCall(PetscArrayzero((dctx->childIDs) + (dctx->maxNumChildren), (dctx->numChildren) - (dctx->maxNumChildren))); 419030f984aSJacob Faibussowitsch } else { 420030f984aSJacob Faibussowitsch /* have no children */ 4219566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(dctx->numChildren, &dctx->childIDs)); 422030f984aSJacob Faibussowitsch } 423030f984aSJacob Faibussowitsch /* update total number of children */ 424030f984aSJacob Faibussowitsch dctx->maxNumChildren = dctx->numChildren; 425030f984aSJacob Faibussowitsch } 4269566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n, &dsubTmp)); 427030f984aSJacob Faibussowitsch while (n) { 428030f984aSJacob Faibussowitsch /* empty child slot */ 429030f984aSJacob Faibussowitsch if (!(dctx->childIDs[i])) { 430030f984aSJacob Faibussowitsch /* create the child context in the image of its parent */ 4319566063dSJacob Faibussowitsch PetscCall(PetscDeviceContextDuplicate(dctx, dsubTmp + i)); 4329566063dSJacob Faibussowitsch PetscCall(PetscDeviceContextWaitForContext(dsubTmp[i], dctx)); 433030f984aSJacob Faibussowitsch /* register the child with its parent */ 434030f984aSJacob Faibussowitsch dctx->childIDs[i] = dsubTmp[i]->id; 435050c0c3dSJacob Faibussowitsch #if PETSC_USE_DEBUG_AND_INFO 436030f984aSJacob Faibussowitsch idList += std::to_string(dsubTmp[i]->id); 437030f984aSJacob Faibussowitsch if (n != 1) idList += ", "; 438030f984aSJacob Faibussowitsch #endif 439030f984aSJacob Faibussowitsch --n; 440030f984aSJacob Faibussowitsch } 441030f984aSJacob Faibussowitsch ++i; 442030f984aSJacob Faibussowitsch } 4433ca90d2dSJacob Faibussowitsch #if PETSC_USE_DEBUG_AND_INFO 4449566063dSJacob Faibussowitsch PetscCall(PetscInfo(nullptr, "Forked %" PetscInt_FMT " children from parent %" PetscInt_FMT " with IDs: %s\n", nBefore, dctx->id, idList.c_str())); 445030f984aSJacob Faibussowitsch /* resets the size but doesn't deallocate the memory */ 446030f984aSJacob Faibussowitsch idList.clear(); 447030f984aSJacob Faibussowitsch #endif 448030f984aSJacob Faibussowitsch /* pass the children back to caller */ 449030f984aSJacob Faibussowitsch *dsub = dsubTmp; 450030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 451030f984aSJacob Faibussowitsch } 452030f984aSJacob Faibussowitsch 453030f984aSJacob Faibussowitsch /*@C 4545181c4f9SJacob Faibussowitsch PetscDeviceContextJoin - Converge a set of child contexts 455030f984aSJacob Faibussowitsch 456030f984aSJacob Faibussowitsch Not Collective, Asynchronous 457030f984aSJacob Faibussowitsch 458030f984aSJacob Faibussowitsch Input Parameters: 459*811af0c4SBarry Smith + dctx - A `PetscDeviceContext` to converge on 460030f984aSJacob Faibussowitsch . n - The number of sub contexts to converge 461030f984aSJacob Faibussowitsch . joinMode - The type of join to perform 462030f984aSJacob Faibussowitsch - dsub - The sub contexts to converge 463030f984aSJacob Faibussowitsch 464030f984aSJacob Faibussowitsch Notes: 465*811af0c4SBarry Smith If `PetscDeviceContextFork()` creates `n` edges from a source node which all depend on the 466030f984aSJacob Faibussowitsch source node, then this routine is the exact mirror. That is, it creates a node 467*811af0c4SBarry Smith (represented in `dctx`) which receives `n` edges (and optionally destroys them) which is 468030f984aSJacob Faibussowitsch dependent on the completion of all incoming edges. 469030f984aSJacob Faibussowitsch 470*811af0c4SBarry Smith If `joinMode` is `PETSC_DEVICE_CONTEXT_JOIN_DESTROY` all contexts in `dsub` will be destroyed 471*811af0c4SBarry Smith by this routine. Thus all sub contexts must have been created with the `dctx` passed to 472030f984aSJacob Faibussowitsch this routine. 473030f984aSJacob Faibussowitsch 474*811af0c4SBarry Smith if `joinMode` is `PETSC_DEVICE_CONTEXT_JOIN_NO_SYNC` `dctx` waits for all sub contexts but the 475030f984aSJacob Faibussowitsch sub contexts do not wait for one another afterwards. 476030f984aSJacob Faibussowitsch 477*811af0c4SBarry Smith If `joinMode` is `PETSC_DEVICE_CONTEXT_JOIN_SYNC` all sub contexts will additionally 478*811af0c4SBarry Smith wait on `dctx` after converging. This has the effect of "synchronizing" the outgoing 479030f984aSJacob Faibussowitsch edges. 480030f984aSJacob Faibussowitsch 481030f984aSJacob Faibussowitsch DAG representations: 482*811af0c4SBarry Smith If `joinMode` is `PETSC_DEVICE_CONTEXT_JOIN_DESTROY` 483030f984aSJacob Faibussowitsch .vb 484030f984aSJacob Faibussowitsch time -> 485030f984aSJacob Faibussowitsch 486030f984aSJacob Faibussowitsch -> dctx ---------/- dctx -> 487030f984aSJacob Faibussowitsch -> dsub[0] -----/ 488030f984aSJacob Faibussowitsch -> ... -------/ 489030f984aSJacob Faibussowitsch -> dsub[n-1] -/ 490030f984aSJacob Faibussowitsch .ve 491*811af0c4SBarry Smith If `joinMode` is `PETSC_DEVICE_CONTEXT_JOIN_NO_SYNC` 492030f984aSJacob Faibussowitsch .vb 493030f984aSJacob Faibussowitsch time -> 494030f984aSJacob Faibussowitsch 495030f984aSJacob Faibussowitsch -> dctx ---------/- dctx -> 496030f984aSJacob Faibussowitsch -> dsub[0] -----/---------> 497030f984aSJacob Faibussowitsch -> ... -------/----------> 498030f984aSJacob Faibussowitsch -> dsub[n-1] -/-----------> 499030f984aSJacob Faibussowitsch .ve 500*811af0c4SBarry Smith If `joinMode` is `PETSC_DEVICE_CONTEXT_JOIN_SYNC` 501030f984aSJacob Faibussowitsch .vb 502030f984aSJacob Faibussowitsch time -> 503030f984aSJacob Faibussowitsch 504030f984aSJacob Faibussowitsch -> dctx ---------/- dctx -\----> dctx ------> 505030f984aSJacob Faibussowitsch -> dsub[0] -----/ \---> dsub[0] ---> 506030f984aSJacob Faibussowitsch -> ... -------/ \--> ... -------> 507030f984aSJacob Faibussowitsch -> dsub[n-1] -/ \-> dsub[n-1] -> 508030f984aSJacob Faibussowitsch .ve 509030f984aSJacob Faibussowitsch 510030f984aSJacob Faibussowitsch Level: intermediate 511030f984aSJacob Faibussowitsch 512db781477SPatrick Sanan .seealso: `PetscDeviceContextFork()`, `PetscDeviceContextSynchronize()`, `PetscDeviceContextJoinMode` 513030f984aSJacob Faibussowitsch @*/ 5149371c9d4SSatish Balay PetscErrorCode PetscDeviceContextJoin(PetscDeviceContext dctx, PetscInt n, PetscDeviceContextJoinMode joinMode, PetscDeviceContext **dsub) { 515030f984aSJacob Faibussowitsch #if defined(PETSC_USE_DEBUG) && defined(PETSC_USE_INFO) 516030f984aSJacob Faibussowitsch static std::string idList; 517030f984aSJacob Faibussowitsch #endif 518030f984aSJacob Faibussowitsch 519030f984aSJacob Faibussowitsch PetscFunctionBegin; 520030f984aSJacob Faibussowitsch /* validity of dctx is checked in the wait-for loop */ 521030f984aSJacob Faibussowitsch PetscValidPointer(dsub, 4); 522bf025ffbSJacob Faibussowitsch PetscAssert(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of contexts merged %" PetscInt_FMT " < 0", n); 523030f984aSJacob Faibussowitsch #if defined(PETSC_USE_DEBUG) && defined(PETSC_USE_INFO) 524030f984aSJacob Faibussowitsch /* reserve 4 chars per id, 2 for number and 2 for ', ' separator */ 525030f984aSJacob Faibussowitsch idList.reserve(4 * n); 526030f984aSJacob Faibussowitsch #endif 527030f984aSJacob Faibussowitsch /* first dctx waits on all the incoming edges */ 528030f984aSJacob Faibussowitsch for (PetscInt i = 0; i < n; ++i) { 529030f984aSJacob Faibussowitsch PetscCheckCompatibleDeviceContexts(dctx, 1, (*dsub)[i], 4); 5309566063dSJacob Faibussowitsch PetscCall(PetscDeviceContextWaitForContext(dctx, (*dsub)[i])); 531030f984aSJacob Faibussowitsch #if defined(PETSC_USE_DEBUG) && defined(PETSC_USE_INFO) 532030f984aSJacob Faibussowitsch idList += std::to_string((*dsub)[i]->id); 533030f984aSJacob Faibussowitsch if (i + 1 < n) idList += ", "; 534030f984aSJacob Faibussowitsch #endif 535030f984aSJacob Faibussowitsch } 536030f984aSJacob Faibussowitsch 537030f984aSJacob Faibussowitsch /* now we handle the aftermath */ 538030f984aSJacob Faibussowitsch switch (joinMode) { 5399371c9d4SSatish Balay case PETSC_DEVICE_CONTEXT_JOIN_DESTROY: { 540030f984aSJacob Faibussowitsch PetscInt j = 0; 541030f984aSJacob Faibussowitsch 542bf025ffbSJacob 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); 543030f984aSJacob Faibussowitsch /* update child count while it's still fresh in memory */ 544030f984aSJacob Faibussowitsch dctx->numChildren -= n; 545030f984aSJacob Faibussowitsch for (PetscInt i = 0; i < dctx->maxNumChildren; ++i) { 546030f984aSJacob Faibussowitsch if (dctx->childIDs[i] && (dctx->childIDs[i] == (*dsub)[j]->id)) { 547030f984aSJacob Faibussowitsch /* child is one of ours, can destroy it */ 5489566063dSJacob Faibussowitsch PetscCall(PetscDeviceContextDestroy((*dsub) + j)); 549030f984aSJacob Faibussowitsch /* reset the child slot */ 550030f984aSJacob Faibussowitsch dctx->childIDs[i] = 0; 551030f984aSJacob Faibussowitsch if (++j == n) break; 552030f984aSJacob Faibussowitsch } 553030f984aSJacob Faibussowitsch } 554030f984aSJacob 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 */ 555bf025ffbSJacob 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); 5569566063dSJacob Faibussowitsch PetscCall(PetscFree(*dsub)); 5579371c9d4SSatish Balay } break; 558030f984aSJacob Faibussowitsch case PETSC_DEVICE_CONTEXT_JOIN_SYNC: 5599566063dSJacob Faibussowitsch for (PetscInt i = 0; i < n; ++i) PetscCall(PetscDeviceContextWaitForContext((*dsub)[i], dctx)); 5609371c9d4SSatish Balay case PETSC_DEVICE_CONTEXT_JOIN_NO_SYNC: break; 5619371c9d4SSatish Balay default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown PetscDeviceContextJoinMode given"); 562030f984aSJacob Faibussowitsch } 563030f984aSJacob Faibussowitsch 564030f984aSJacob Faibussowitsch #if defined(PETSC_USE_DEBUG) && defined(PETSC_USE_INFO) 5659566063dSJacob 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())); 566030f984aSJacob Faibussowitsch idList.clear(); 567030f984aSJacob Faibussowitsch #endif 568030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 569030f984aSJacob Faibussowitsch } 570030f984aSJacob Faibussowitsch 571030f984aSJacob Faibussowitsch /*@C 572*811af0c4SBarry Smith PetscDeviceContextSynchronize - Block the host until all work queued on or associated with a `PetscDeviceContext` has finished 573030f984aSJacob Faibussowitsch 574030f984aSJacob Faibussowitsch Not Collective, Synchronous 575030f984aSJacob Faibussowitsch 576030f984aSJacob Faibussowitsch Input Parameters: 577*811af0c4SBarry Smith . dctx - The `PetscDeviceContext` to synchronize 578030f984aSJacob Faibussowitsch 579030f984aSJacob Faibussowitsch Level: beginner 580030f984aSJacob Faibussowitsch 581db781477SPatrick Sanan .seealso: `PetscDeviceContextFork()`, `PetscDeviceContextJoin()`, `PetscDeviceContextQueryIdle()` 582030f984aSJacob Faibussowitsch @*/ 5839371c9d4SSatish Balay PetscErrorCode PetscDeviceContextSynchronize(PetscDeviceContext dctx) { 584030f984aSJacob Faibussowitsch PetscFunctionBegin; 585030f984aSJacob Faibussowitsch PetscValidDeviceContext(dctx, 1); 586030f984aSJacob Faibussowitsch /* if it isn't setup there is nothing to sync on */ 587dbbe0bcdSBarry Smith if (dctx->setup) PetscUseTypeMethod(dctx, synchronize); 588030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 589030f984aSJacob Faibussowitsch } 590030f984aSJacob Faibussowitsch 591a4af0ceeSJacob Faibussowitsch #define PETSC_DEVICE_CONTEXT_DEFAULT_DEVICE PETSC_DEVICE_DEFAULT 592a4af0ceeSJacob Faibussowitsch // REMOVE ME (change) 593a4af0ceeSJacob Faibussowitsch #define PETSC_DEVICE_CONTEXT_DEFAULT_STREAM PETSC_STREAM_GLOBAL_BLOCKING 594030f984aSJacob Faibussowitsch 595a4af0ceeSJacob Faibussowitsch static PetscDeviceType rootDeviceType = PETSC_DEVICE_CONTEXT_DEFAULT_DEVICE; 596a4af0ceeSJacob Faibussowitsch static PetscStreamType rootStreamType = PETSC_DEVICE_CONTEXT_DEFAULT_STREAM; 597bf025ffbSJacob Faibussowitsch static PetscDeviceContext globalContext = nullptr; 598a4af0ceeSJacob Faibussowitsch 599a4af0ceeSJacob Faibussowitsch /* when PetsDevice initializes PetscDeviceContext eagerly the type of device created should 600a4af0ceeSJacob Faibussowitsch * match whatever device is eagerly intialized */ 6019371c9d4SSatish Balay PetscErrorCode PetscDeviceContextSetRootDeviceType_Internal(PetscDeviceType type) { 602030f984aSJacob Faibussowitsch PetscFunctionBegin; 603a4af0ceeSJacob Faibussowitsch PetscValidDeviceType(type, 1); 604a4af0ceeSJacob Faibussowitsch rootDeviceType = type; 605030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 606030f984aSJacob Faibussowitsch } 607030f984aSJacob Faibussowitsch 608a4af0ceeSJacob Faibussowitsch #if 0 609a4af0ceeSJacob Faibussowitsch /* currently unused */ 610a4af0ceeSJacob Faibussowitsch PetscErrorCode PetscDeviceContextSetRootStreamType_Internal(PetscStreamType type) 611030f984aSJacob Faibussowitsch { 612a4af0ceeSJacob Faibussowitsch PetscFunctionBegin; 613a4af0ceeSJacob Faibussowitsch PetscValidStreamType(type,1); 614a4af0ceeSJacob Faibussowitsch rootStreamType = type; 615a4af0ceeSJacob Faibussowitsch PetscFunctionReturn(0); 616a4af0ceeSJacob Faibussowitsch } 617a4af0ceeSJacob Faibussowitsch #endif 618a4af0ceeSJacob Faibussowitsch 6199371c9d4SSatish Balay static PetscErrorCode PetscDeviceContextSetupGlobalContext_Private(void) { 620a4af0ceeSJacob Faibussowitsch static const auto PetscDeviceContextFinalizer = []() -> PetscErrorCode { 621030f984aSJacob Faibussowitsch PetscFunctionBegin; 6229566063dSJacob Faibussowitsch PetscCall(PetscDeviceContextDestroy(&globalContext)); 623a4af0ceeSJacob Faibussowitsch rootDeviceType = PETSC_DEVICE_CONTEXT_DEFAULT_DEVICE; 624a4af0ceeSJacob Faibussowitsch rootStreamType = PETSC_DEVICE_CONTEXT_DEFAULT_STREAM; 625a4af0ceeSJacob Faibussowitsch PetscFunctionReturn(0); 626a4af0ceeSJacob Faibussowitsch }; 627a4af0ceeSJacob Faibussowitsch 628a4af0ceeSJacob Faibussowitsch PetscFunctionBegin; 629a4af0ceeSJacob Faibussowitsch if (globalContext) PetscFunctionReturn(0); 630a4af0ceeSJacob Faibussowitsch /* this exists purely as a valid device check. */ 6319566063dSJacob Faibussowitsch PetscCall(PetscDeviceInitializePackage()); 6329566063dSJacob Faibussowitsch PetscCall(PetscRegisterFinalize(PetscDeviceContextFinalizer)); 6339566063dSJacob Faibussowitsch PetscCall(PetscInfo(nullptr, "Initializing global PetscDeviceContext\n")); 634a4af0ceeSJacob Faibussowitsch /* we call the allocator directly here since the ObjectPool creates a PetscContainer which 635a4af0ceeSJacob Faibussowitsch * eventually tries to call logging functions. However, this routine may be purposefully 636a4af0ceeSJacob Faibussowitsch * called __before__ logging is initialized, so the logging function would PETSCABORT */ 6379566063dSJacob Faibussowitsch PetscCall(contextPool.allocator().create(&globalContext)); 6389566063dSJacob Faibussowitsch PetscCall(PetscDeviceContextSetStreamType(globalContext, rootStreamType)); 6399566063dSJacob Faibussowitsch PetscCall(PetscDeviceContextSetDefaultDeviceForType_Internal(globalContext, rootDeviceType)); 6409566063dSJacob Faibussowitsch PetscCall(PetscDeviceContextSetUp(globalContext)); 641030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 642030f984aSJacob Faibussowitsch } 643030f984aSJacob Faibussowitsch 644030f984aSJacob Faibussowitsch /*@C 645*811af0c4SBarry Smith PetscDeviceContextGetCurrentContext - Get the current active `PetscDeviceContext` 646030f984aSJacob Faibussowitsch 647030f984aSJacob Faibussowitsch Not Collective, Asynchronous 648030f984aSJacob Faibussowitsch 649030f984aSJacob Faibussowitsch Output Parameter: 650*811af0c4SBarry Smith . dctx - The `PetscDeviceContext` 651030f984aSJacob Faibussowitsch 652*811af0c4SBarry Smith Note: 653a4af0ceeSJacob Faibussowitsch The user generally should not destroy contexts retrieved with this routine unless they 654a4af0ceeSJacob Faibussowitsch themselves have created them. There exists no protection against destroying the root 655a4af0ceeSJacob Faibussowitsch context. 656030f984aSJacob Faibussowitsch 657*811af0c4SBarry Smith Developer Note: 658a4af0ceeSJacob Faibussowitsch Unless the user has set their own, this routine creates the "root" context the first time it 659*811af0c4SBarry Smith is called, registering its destructor to `PetscFinalize()`. 660030f984aSJacob Faibussowitsch 661030f984aSJacob Faibussowitsch Level: beginner 662030f984aSJacob Faibussowitsch 663db781477SPatrick Sanan .seealso: `PetscDeviceContextSetCurrentContext()`, `PetscDeviceContextFork()`, 664db781477SPatrick Sanan `PetscDeviceContextJoin()`, `PetscDeviceContextCreate()` 665030f984aSJacob Faibussowitsch @*/ 6669371c9d4SSatish Balay PetscErrorCode PetscDeviceContextGetCurrentContext(PetscDeviceContext *dctx) { 667a4af0ceeSJacob Faibussowitsch PetscFunctionBegin; 668a4af0ceeSJacob Faibussowitsch PetscValidPointer(dctx, 1); 6699566063dSJacob Faibussowitsch PetscCall(PetscDeviceContextSetupGlobalContext_Private()); 670a4af0ceeSJacob Faibussowitsch /* while the static analyzer can find global variables, it will throw a warning about not 671a4af0ceeSJacob Faibussowitsch * being able to connect this back to the function arguments */ 672a4af0ceeSJacob Faibussowitsch PetscDisableStaticAnalyzerForExpressionUnderstandingThatThisIsDangerousAndBugprone(PetscValidDeviceContext(globalContext, -1)); 673030f984aSJacob Faibussowitsch *dctx = globalContext; 674030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 675030f984aSJacob Faibussowitsch } 676030f984aSJacob Faibussowitsch 677030f984aSJacob Faibussowitsch /*@C 678*811af0c4SBarry Smith PetscDeviceContextSetCurrentContext - Set the current active `PetscDeviceContext` 679030f984aSJacob Faibussowitsch 680030f984aSJacob Faibussowitsch Not Collective, Asynchronous 681030f984aSJacob Faibussowitsch 682030f984aSJacob Faibussowitsch Input Parameter: 683*811af0c4SBarry Smith . dctx - The `PetscDeviceContext` 684030f984aSJacob Faibussowitsch 685030f984aSJacob Faibussowitsch Notes: 686*811af0c4SBarry Smith This routine can be used to set the defacto "root" `PetscDeviceContext` to a user-defined 687*811af0c4SBarry Smith implementation by calling this routine immediately after `PetscInitialize()` and ensuring that 688*811af0c4SBarry Smith `PetscDevice` is not eagerly initialized. In this case the user is responsible for destroying 689*811af0c4SBarry Smith their `PetscDeviceContext` before `PetscFinalize()` returns. 690a4af0ceeSJacob Faibussowitsch 691a4af0ceeSJacob Faibussowitsch The old context is not stored in any way by this routine; if one is overriding a context that 692a4af0ceeSJacob Faibussowitsch they themselves do not control, one should take care to temporarily store it by calling 693*811af0c4SBarry Smith `PetscDeviceContextGetCurrentContext()` before calling this routine. 694030f984aSJacob Faibussowitsch 695030f984aSJacob Faibussowitsch Level: beginner 696030f984aSJacob Faibussowitsch 697db781477SPatrick Sanan .seealso: `PetscDeviceContextGetCurrentContext()`, `PetscDeviceContextFork()`, 698db781477SPatrick Sanan `PetscDeviceContextJoin()`, `PetscDeviceContextCreate()` 699030f984aSJacob Faibussowitsch @*/ 7009371c9d4SSatish Balay PetscErrorCode PetscDeviceContextSetCurrentContext(PetscDeviceContext dctx) { 701030f984aSJacob Faibussowitsch PetscFunctionBegin; 702030f984aSJacob Faibussowitsch PetscValidDeviceContext(dctx, 1); 703bf025ffbSJacob 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); 704030f984aSJacob Faibussowitsch globalContext = dctx; 7059566063dSJacob Faibussowitsch PetscCall(PetscInfo(nullptr, "Set global PetscDeviceContext id %" PetscInt_FMT "\n", dctx->id)); 706030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 707030f984aSJacob Faibussowitsch } 708030f984aSJacob Faibussowitsch 709030f984aSJacob Faibussowitsch /*@C 710*811af0c4SBarry Smith PetscDeviceContextSetFromOptions - Configure a `PetscDeviceContext` from the options database 711030f984aSJacob Faibussowitsch 712030f984aSJacob Faibussowitsch Collective on comm, Asynchronous 713030f984aSJacob Faibussowitsch 714030f984aSJacob Faibussowitsch Input Parameters: 715030f984aSJacob Faibussowitsch + comm - MPI communicator on which to query the options database 716030f984aSJacob Faibussowitsch . prefix - prefix to prepend to all options database queries, NULL if not needed 717*811af0c4SBarry Smith - dctx - The `PetscDeviceContext` to configure 718030f984aSJacob Faibussowitsch 719030f984aSJacob Faibussowitsch Output Parameter: 720*811af0c4SBarry Smith . dctx - The `PetscDeviceContext` 721030f984aSJacob Faibussowitsch 722*811af0c4SBarry Smith Options Database Keys: 723*811af0c4SBarry Smith + -device_context_stream_type - type of stream to create inside the `PetscDeviceContext` - `PetscDeviceContextSetStreamType()` 724*811af0c4SBarry Smith - -device_context_device_type - the type of `PetscDevice` to attach by default - `PetscDeviceType` 725030f984aSJacob Faibussowitsch 726030f984aSJacob Faibussowitsch Level: beginner 727030f984aSJacob Faibussowitsch 728db781477SPatrick Sanan .seealso: `PetscDeviceContextSetStreamType()`, `PetscDeviceContextSetDevice()` 729030f984aSJacob Faibussowitsch @*/ 7309371c9d4SSatish Balay PetscErrorCode PetscDeviceContextSetFromOptions(MPI_Comm comm, const char prefix[], PetscDeviceContext dctx) { 731030f984aSJacob Faibussowitsch PetscBool flag; 732a4af0ceeSJacob Faibussowitsch PetscInt stype, dtype; 733030f984aSJacob Faibussowitsch 734030f984aSJacob Faibussowitsch PetscFunctionBegin; 735a4af0ceeSJacob Faibussowitsch if (prefix) PetscValidCharPointer(prefix, 2); 736030f984aSJacob Faibussowitsch PetscValidDeviceContext(dctx, 3); 737d0609cedSBarry Smith PetscOptionsBegin(comm, prefix, "PetscDeviceContext Options", "Sys"); 7389566063dSJacob Faibussowitsch PetscCall(PetscOptionsEList("-device_context_stream_type", "PetscDeviceContext PetscStreamType", "PetscDeviceContextSetStreamType", PetscStreamTypes, PETSC_STREAM_MAX, PetscStreamTypes[dctx->streamType], &stype, &flag)); 7399566063dSJacob Faibussowitsch if (flag) PetscCall(PetscDeviceContextSetStreamType(dctx, static_cast<PetscStreamType>(stype))); 7409566063dSJacob 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)); 74148a46eb9SPierre Jolivet if (flag) PetscCall(PetscDeviceContextSetDefaultDeviceForType_Internal(dctx, static_cast<PetscDeviceType>(dtype + 1))); 742d0609cedSBarry Smith PetscOptionsEnd(); 743030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 744030f984aSJacob Faibussowitsch } 745