1030f984aSJacob Faibussowitsch #include <petsc/private/deviceimpl.h> /*I "petscdevice.h" I*/ 2030f984aSJacob Faibussowitsch #include "objpool.hpp" 3030f984aSJacob Faibussowitsch 4a4af0ceeSJacob Faibussowitsch const char *const PetscStreamTypes[] = { 5a4af0ceeSJacob Faibussowitsch "global_blocking", 6a4af0ceeSJacob Faibussowitsch "default_blocking", 7a4af0ceeSJacob Faibussowitsch "global_nonblocking", 8a4af0ceeSJacob Faibussowitsch "max", 9a4af0ceeSJacob Faibussowitsch "PetscStreamType", 10a4af0ceeSJacob Faibussowitsch "PETSC_STREAM_", 11bf025ffbSJacob Faibussowitsch nullptr 12a4af0ceeSJacob Faibussowitsch }; 13a4af0ceeSJacob Faibussowitsch 14a4af0ceeSJacob Faibussowitsch const char *const PetscDeviceContextJoinModes[] = { 15a4af0ceeSJacob Faibussowitsch "destroy", 16a4af0ceeSJacob Faibussowitsch "sync", 17a4af0ceeSJacob Faibussowitsch "no_sync", 18a4af0ceeSJacob Faibussowitsch "PetscDeviceContextJoinMode", 19a4af0ceeSJacob Faibussowitsch "PETSC_DEVICE_CONTEXT_JOIN_", 20bf025ffbSJacob Faibussowitsch nullptr 21a4af0ceeSJacob Faibussowitsch }; 22a4af0ceeSJacob Faibussowitsch 23030f984aSJacob Faibussowitsch /* Define the allocator */ 2417f48955SJacob Faibussowitsch struct PetscDeviceContextAllocator : Petsc::AllocatorBase<PetscDeviceContext> 25030f984aSJacob Faibussowitsch { 26030f984aSJacob Faibussowitsch static PetscInt PetscDeviceContextID; 27030f984aSJacob Faibussowitsch 2817f48955SJacob Faibussowitsch PETSC_NODISCARD static PetscErrorCode create(PetscDeviceContext *dctx) noexcept 29030f984aSJacob Faibussowitsch { 30030f984aSJacob Faibussowitsch PetscDeviceContext dc; 31030f984aSJacob Faibussowitsch 32030f984aSJacob Faibussowitsch PetscFunctionBegin; 339566063dSJacob Faibussowitsch PetscCall(PetscNew(&dc)); 34030f984aSJacob Faibussowitsch dc->id = PetscDeviceContextID++; 35030f984aSJacob Faibussowitsch dc->streamType = PETSC_STREAM_DEFAULT_BLOCKING; 36030f984aSJacob Faibussowitsch *dctx = dc; 37030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 38030f984aSJacob Faibussowitsch } 39030f984aSJacob Faibussowitsch 4017f48955SJacob Faibussowitsch PETSC_NODISCARD static PetscErrorCode destroy(PetscDeviceContext dctx) noexcept 41030f984aSJacob Faibussowitsch { 42030f984aSJacob Faibussowitsch PetscFunctionBegin; 43bf025ffbSJacob 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); 44*dbbe0bcdSBarry Smith PetscTryTypeMethod(dctx,destroy); 459566063dSJacob Faibussowitsch PetscCall(PetscDeviceDestroy(&dctx->device)); 469566063dSJacob Faibussowitsch PetscCall(PetscFree(dctx->childIDs)); 479566063dSJacob Faibussowitsch PetscCall(PetscFree(dctx)); 48030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 49030f984aSJacob Faibussowitsch } 50030f984aSJacob Faibussowitsch 5117f48955SJacob Faibussowitsch PETSC_NODISCARD static PetscErrorCode reset(PetscDeviceContext dctx) noexcept 52030f984aSJacob Faibussowitsch { 53030f984aSJacob Faibussowitsch PetscFunctionBegin; 54030f984aSJacob Faibussowitsch /* don't deallocate the child array, rather just zero it out */ 559566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(dctx->childIDs,dctx->maxNumChildren)); 56030f984aSJacob Faibussowitsch dctx->setup = PETSC_FALSE; 57030f984aSJacob Faibussowitsch dctx->numChildren = 0; 58030f984aSJacob Faibussowitsch dctx->streamType = PETSC_STREAM_DEFAULT_BLOCKING; 59030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 60030f984aSJacob Faibussowitsch } 61030f984aSJacob Faibussowitsch 6217f48955SJacob Faibussowitsch PETSC_NODISCARD static constexpr PetscErrorCode finalize() noexcept { return 0; } 63030f984aSJacob Faibussowitsch }; 64a4af0ceeSJacob Faibussowitsch /* an ID = 0 is invalid */ 65a4af0ceeSJacob Faibussowitsch PetscInt PetscDeviceContextAllocator::PetscDeviceContextID = 1; 66030f984aSJacob Faibussowitsch 67030f984aSJacob Faibussowitsch static Petsc::ObjectPool<PetscDeviceContext,PetscDeviceContextAllocator> contextPool; 68030f984aSJacob Faibussowitsch 69030f984aSJacob Faibussowitsch /*@C 70030f984aSJacob Faibussowitsch PetscDeviceContextCreate - Creates a PetscDeviceContext 71030f984aSJacob Faibussowitsch 72030f984aSJacob Faibussowitsch Not Collective, Asynchronous 73030f984aSJacob Faibussowitsch 7401d2d390SJose E. Roman Output Paramemter: 75030f984aSJacob Faibussowitsch . dctx - The PetscDeviceContext 76030f984aSJacob Faibussowitsch 77030f984aSJacob Faibussowitsch Notes: 78030f984aSJacob Faibussowitsch Unlike almost every other PETSc class it is advised that most users use 79030f984aSJacob Faibussowitsch PetscDeviceContextDuplicate() rather than this routine to create new contexts. Contexts 80030f984aSJacob Faibussowitsch of different types are incompatible with one another; using 81030f984aSJacob Faibussowitsch PetscDeviceContextDuplicate() ensures compatible types. 82030f984aSJacob Faibussowitsch 83030f984aSJacob Faibussowitsch Level: beginner 84030f984aSJacob Faibussowitsch 85db781477SPatrick Sanan .seealso: `PetscDeviceContextDuplicate()`, `PetscDeviceContextSetDevice()`, 86db781477SPatrick Sanan `PetscDeviceContextSetStreamType()`, `PetscDeviceContextSetUp()`, 87db781477SPatrick Sanan `PetscDeviceContextSetFromOptions()`, `PetscDeviceContextDestroy()` 88030f984aSJacob Faibussowitsch @*/ 89030f984aSJacob Faibussowitsch PetscErrorCode PetscDeviceContextCreate(PetscDeviceContext *dctx) 90030f984aSJacob Faibussowitsch { 91030f984aSJacob Faibussowitsch PetscFunctionBegin; 92030f984aSJacob Faibussowitsch PetscValidPointer(dctx,1); 939566063dSJacob Faibussowitsch PetscCall(PetscDeviceInitializePackage()); 949566063dSJacob Faibussowitsch PetscCall(contextPool.get(*dctx)); 95030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 96030f984aSJacob Faibussowitsch } 97030f984aSJacob Faibussowitsch 98030f984aSJacob Faibussowitsch /*@C 99030f984aSJacob Faibussowitsch PetscDeviceContextDestroy - Frees a PetscDeviceContext 100030f984aSJacob Faibussowitsch 101030f984aSJacob Faibussowitsch Not Collective, Asynchronous 102030f984aSJacob Faibussowitsch 103030f984aSJacob Faibussowitsch Input Parameters: 104030f984aSJacob Faibussowitsch . dctx - The PetscDeviceContext 105030f984aSJacob Faibussowitsch 106030f984aSJacob Faibussowitsch Notes: 107030f984aSJacob Faibussowitsch No implicit synchronization occurs due to this routine, all resources are released completely asynchronously 108030f984aSJacob Faibussowitsch w.r.t. the host. If one needs to guarantee access to the data produced on this contexts stream one should perform the 109030f984aSJacob Faibussowitsch appropriate synchronization before calling this routine. 110030f984aSJacob Faibussowitsch 111030f984aSJacob Faibussowitsch Developer Notes: 112030f984aSJacob Faibussowitsch The context is never actually "destroyed", only returned to an ever growing pool of 113030f984aSJacob Faibussowitsch contexts. There are currently no safeguards on the size of the pool, this should perhaps 114030f984aSJacob Faibussowitsch be implemented. 115030f984aSJacob Faibussowitsch 116030f984aSJacob Faibussowitsch Level: beginner 117030f984aSJacob Faibussowitsch 118db781477SPatrick Sanan .seealso: `PetscDeviceContextCreate()`, `PetscDeviceContextSetDevice()`, `PetscDeviceContextSetUp()`, `PetscDeviceContextSynchronize()` 119030f984aSJacob Faibussowitsch @*/ 120030f984aSJacob Faibussowitsch PetscErrorCode PetscDeviceContextDestroy(PetscDeviceContext *dctx) 121030f984aSJacob Faibussowitsch { 122030f984aSJacob Faibussowitsch PetscFunctionBegin; 123030f984aSJacob Faibussowitsch if (!*dctx) PetscFunctionReturn(0); 1249566063dSJacob Faibussowitsch PetscCall(contextPool.reclaim(std::move(*dctx))); 125bf025ffbSJacob Faibussowitsch *dctx = nullptr; 126030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 127030f984aSJacob Faibussowitsch } 128030f984aSJacob Faibussowitsch 129030f984aSJacob Faibussowitsch /*@C 130030f984aSJacob Faibussowitsch PetscDeviceContextSetStreamType - Set the implementation type of the underlying stream for a PetscDeviceContext 131030f984aSJacob Faibussowitsch 132030f984aSJacob Faibussowitsch Not Collective, Asynchronous 133030f984aSJacob Faibussowitsch 13401d2d390SJose E. Roman Input Parameters: 135030f984aSJacob Faibussowitsch + dctx - The PetscDeviceContext 136030f984aSJacob Faibussowitsch - type - The PetscStreamType 137030f984aSJacob Faibussowitsch 138030f984aSJacob Faibussowitsch Notes: 139030f984aSJacob Faibussowitsch See PetscStreamType in include/petscdevicetypes.h for more information on the available 140030f984aSJacob Faibussowitsch types and their interactions. If the PetscDeviceContext was previously set up and stream 141030f984aSJacob Faibussowitsch type was changed, you must call PetscDeviceContextSetUp() again after this routine. 142030f984aSJacob Faibussowitsch 143030f984aSJacob Faibussowitsch Level: intermediate 144030f984aSJacob Faibussowitsch 145db781477SPatrick Sanan .seealso: `PetscStreamType`, `PetscDeviceContextGetStreamType()`, `PetscDeviceContextCreate()`, `PetscDeviceContextSetUp()`, `PetscDeviceContextSetFromOptions()` 146030f984aSJacob Faibussowitsch @*/ 147030f984aSJacob Faibussowitsch PetscErrorCode PetscDeviceContextSetStreamType(PetscDeviceContext dctx, PetscStreamType type) 148030f984aSJacob Faibussowitsch { 149030f984aSJacob Faibussowitsch PetscFunctionBegin; 150030f984aSJacob Faibussowitsch PetscValidDeviceContext(dctx,1); 151030f984aSJacob Faibussowitsch PetscValidStreamType(type,2); 152030f984aSJacob Faibussowitsch /* only need to do complex swapping if the object has already been setup */ 153030f984aSJacob Faibussowitsch if (dctx->setup && (dctx->streamType != type)) { 154*dbbe0bcdSBarry Smith PetscUseTypeMethod(dctx,changestreamtype ,type); 155030f984aSJacob Faibussowitsch dctx->setup = PETSC_FALSE; 156030f984aSJacob Faibussowitsch } 157030f984aSJacob Faibussowitsch dctx->streamType = type; 158030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 159030f984aSJacob Faibussowitsch } 160030f984aSJacob Faibussowitsch 161030f984aSJacob Faibussowitsch /*@C 162030f984aSJacob Faibussowitsch PetscDeviceContextGetStreamType - Get the implementation type of the underlying stream for a PetscDeviceContext 163030f984aSJacob Faibussowitsch 164030f984aSJacob Faibussowitsch Not Collective, Asynchronous 165030f984aSJacob Faibussowitsch 16601d2d390SJose E. Roman Input Parameter: 167030f984aSJacob Faibussowitsch . dctx - The PetscDeviceContext 168030f984aSJacob Faibussowitsch 169030f984aSJacob Faibussowitsch Output Parameter: 170030f984aSJacob Faibussowitsch . type - The PetscStreamType 171030f984aSJacob Faibussowitsch 172030f984aSJacob Faibussowitsch Notes: 173030f984aSJacob Faibussowitsch See PetscStreamType in include/petscdevicetypes.h for more information on the available types and their interactions 174030f984aSJacob Faibussowitsch 175030f984aSJacob Faibussowitsch Level: intermediate 176030f984aSJacob Faibussowitsch 177db781477SPatrick Sanan .seealso: `PetscDeviceContextSetStreamType()`, `PetscDeviceContextCreate()`, `PetscDeviceContextSetFromOptions()` 178030f984aSJacob Faibussowitsch @*/ 179030f984aSJacob Faibussowitsch PetscErrorCode PetscDeviceContextGetStreamType(PetscDeviceContext dctx, PetscStreamType *type) 180030f984aSJacob Faibussowitsch { 181030f984aSJacob Faibussowitsch PetscFunctionBegin; 182030f984aSJacob Faibussowitsch PetscValidDeviceContext(dctx,1); 183030f984aSJacob Faibussowitsch PetscValidIntPointer(type,2); 184030f984aSJacob Faibussowitsch *type = dctx->streamType; 185030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 186030f984aSJacob Faibussowitsch } 187030f984aSJacob Faibussowitsch 188030f984aSJacob Faibussowitsch /*@C 189030f984aSJacob Faibussowitsch PetscDeviceContextSetDevice - Set the underlying device for the PetscDeviceContext 190030f984aSJacob Faibussowitsch 191030f984aSJacob Faibussowitsch Not Collective, Possibly Synchronous 192030f984aSJacob Faibussowitsch 19301d2d390SJose E. Roman Input Parameters: 194030f984aSJacob Faibussowitsch + dctx - The PetscDeviceContext 195030f984aSJacob Faibussowitsch - device - The PetscDevice 196030f984aSJacob Faibussowitsch 197030f984aSJacob Faibussowitsch Notes: 198030f984aSJacob Faibussowitsch This routine is effectively PetscDeviceContext's "set-type" (so every PetscDeviceContext 199030f984aSJacob Faibussowitsch must also have an attached PetscDevice). Unlike the usual set-type semantics, it is 200030f984aSJacob Faibussowitsch not stricly necessary to set a contexts device to enable usage, any created device 201030f984aSJacob Faibussowitsch contexts will always come equipped with the "default" device. 202030f984aSJacob Faibussowitsch 203a4af0ceeSJacob Faibussowitsch This routine is a no-op if dctx is already attached to device. 204a4af0ceeSJacob Faibussowitsch 2055181c4f9SJacob Faibussowitsch This routine may initialize the backend device and incur synchronization. 2065181c4f9SJacob Faibussowitsch 207030f984aSJacob Faibussowitsch Level: intermediate 208030f984aSJacob Faibussowitsch 209db781477SPatrick Sanan .seealso: `PetscDeviceCreate()`, `PetscDeviceConfigure()`, `PetscDeviceContextGetDevice()` 210030f984aSJacob Faibussowitsch @*/ 211030f984aSJacob Faibussowitsch PetscErrorCode PetscDeviceContextSetDevice(PetscDeviceContext dctx, PetscDevice device) 212030f984aSJacob Faibussowitsch { 213030f984aSJacob Faibussowitsch PetscFunctionBegin; 214030f984aSJacob Faibussowitsch PetscValidDeviceContext(dctx,1); 215030f984aSJacob Faibussowitsch PetscValidDevice(device,2); 216a4af0ceeSJacob Faibussowitsch if (dctx->device) { 217a4af0ceeSJacob Faibussowitsch /* can't do a strict pointer equality check since PetscDevice's are reused */ 218a4af0ceeSJacob Faibussowitsch if (dctx->device->ops->createcontext == device->ops->createcontext) PetscFunctionReturn(0); 219a4af0ceeSJacob Faibussowitsch } 2209566063dSJacob Faibussowitsch PetscCall(PetscDeviceDestroy(&dctx->device)); 221*dbbe0bcdSBarry Smith PetscTryTypeMethod(dctx,destroy); 2229566063dSJacob Faibussowitsch PetscCall(PetscMemzero(dctx->ops,sizeof(*dctx->ops))); 2239566063dSJacob Faibussowitsch PetscCall((*device->ops->createcontext)(dctx)); 2249566063dSJacob Faibussowitsch PetscCall(PetscDeviceReference_Internal(device)); 225a4af0ceeSJacob Faibussowitsch dctx->device = device; 226030f984aSJacob Faibussowitsch dctx->setup = PETSC_FALSE; 227030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 228030f984aSJacob Faibussowitsch } 229030f984aSJacob Faibussowitsch 230030f984aSJacob Faibussowitsch /*@C 231030f984aSJacob Faibussowitsch PetscDeviceContextGetDevice - Get the underlying PetscDevice for a PetscDeviceContext 232030f984aSJacob Faibussowitsch 233030f984aSJacob Faibussowitsch Not Collective, Asynchronous 234030f984aSJacob Faibussowitsch 235030f984aSJacob Faibussowitsch Input Parameter: 236030f984aSJacob Faibussowitsch . dctx - the PetscDeviceContext 237030f984aSJacob Faibussowitsch 238030f984aSJacob Faibussowitsch Output Parameter: 239030f984aSJacob Faibussowitsch . device - The PetscDevice 240030f984aSJacob Faibussowitsch 241030f984aSJacob Faibussowitsch Notes: 242030f984aSJacob Faibussowitsch This is a borrowed reference, the user should not destroy the device. 243030f984aSJacob Faibussowitsch 244a375dbeeSPatrick Sanan Level: intermediate 245a375dbeeSPatrick Sanan 246db781477SPatrick Sanan .seealso: `PetscDeviceContextSetDevice()`, `PetscDevice` 247030f984aSJacob Faibussowitsch @*/ 248030f984aSJacob Faibussowitsch PetscErrorCode PetscDeviceContextGetDevice(PetscDeviceContext dctx, PetscDevice *device) 249030f984aSJacob Faibussowitsch { 250030f984aSJacob Faibussowitsch PetscFunctionBegin; 251030f984aSJacob Faibussowitsch PetscValidDeviceContext(dctx,1); 252030f984aSJacob Faibussowitsch PetscValidPointer(device,2); 253bf025ffbSJacob Faibussowitsch PetscAssert(dctx->device,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"PetscDeviceContext %" PetscInt_FMT " has no attached PetscDevice to get",dctx->id); 254030f984aSJacob Faibussowitsch *device = dctx->device; 255030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 256030f984aSJacob Faibussowitsch } 257030f984aSJacob Faibussowitsch 258030f984aSJacob Faibussowitsch /*@C 259030f984aSJacob Faibussowitsch PetscDeviceContextSetUp - Prepares a PetscDeviceContext for use 260030f984aSJacob Faibussowitsch 261030f984aSJacob Faibussowitsch Not Collective, Asynchronous 262030f984aSJacob Faibussowitsch 26301d2d390SJose E. Roman Input Parameter: 264030f984aSJacob Faibussowitsch . dctx - The PetscDeviceContext 265030f984aSJacob Faibussowitsch 266030f984aSJacob Faibussowitsch Developer Notes: 267030f984aSJacob Faibussowitsch This routine is usually the stage where a PetscDeviceContext acquires device-side data structures such as streams, 268030f984aSJacob Faibussowitsch events, and (possibly) handles. 269030f984aSJacob Faibussowitsch 270030f984aSJacob Faibussowitsch Level: beginner 271030f984aSJacob Faibussowitsch 272db781477SPatrick Sanan .seealso: `PetscDeviceContextCreate()`, `PetscDeviceContextSetDevice()`, `PetscDeviceContextDestroy()`, `PetscDeviceContextSetFromOptions()` 273030f984aSJacob Faibussowitsch @*/ 274030f984aSJacob Faibussowitsch PetscErrorCode PetscDeviceContextSetUp(PetscDeviceContext dctx) 275030f984aSJacob Faibussowitsch { 276030f984aSJacob Faibussowitsch PetscFunctionBegin; 277030f984aSJacob Faibussowitsch PetscValidDeviceContext(dctx,1); 278030f984aSJacob Faibussowitsch if (!dctx->device) { 2799566063dSJacob 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])); 2809566063dSJacob Faibussowitsch PetscCall(PetscDeviceContextSetDefaultDevice_Internal(dctx)); 281030f984aSJacob Faibussowitsch } 282030f984aSJacob Faibussowitsch if (dctx->setup) PetscFunctionReturn(0); 283*dbbe0bcdSBarry Smith PetscUseTypeMethod(dctx,setup); 284030f984aSJacob Faibussowitsch dctx->setup = PETSC_TRUE; 285030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 286030f984aSJacob Faibussowitsch } 287030f984aSJacob Faibussowitsch 288030f984aSJacob Faibussowitsch /*@C 289030f984aSJacob Faibussowitsch PetscDeviceContextDuplicate - Duplicates a PetscDeviceContext object 290030f984aSJacob Faibussowitsch 291030f984aSJacob Faibussowitsch Not Collective, Asynchronous 292030f984aSJacob Faibussowitsch 293030f984aSJacob Faibussowitsch Input Parameter: 294030f984aSJacob Faibussowitsch . dctx - The PetscDeviceContext to duplicate 295030f984aSJacob Faibussowitsch 2966aad120cSJose E. Roman Output Parameter: 297050c0c3dSJacob Faibussowitsch . dctxdup - The duplicated PetscDeviceContext 298030f984aSJacob Faibussowitsch 299030f984aSJacob Faibussowitsch Notes: 300030f984aSJacob Faibussowitsch This is a shorthand method for creating a PetscDeviceContext with the exact same 301030f984aSJacob Faibussowitsch settings as another. Note however that the duplicated PetscDeviceContext does not "share" 302030f984aSJacob Faibussowitsch any of the underlying data with the original, (including its current stream-state) they 303030f984aSJacob Faibussowitsch are completely separate objects. 304030f984aSJacob Faibussowitsch 305030f984aSJacob Faibussowitsch Level: beginner 306030f984aSJacob Faibussowitsch 307db781477SPatrick Sanan .seealso: `PetscDeviceContextCreate()`, `PetscDeviceContextSetDevice()`, `PetscDeviceContextSetStreamType()` 308030f984aSJacob Faibussowitsch @*/ 309030f984aSJacob Faibussowitsch PetscErrorCode PetscDeviceContextDuplicate(PetscDeviceContext dctx, PetscDeviceContext *dctxdup) 310030f984aSJacob Faibussowitsch { 311a4af0ceeSJacob Faibussowitsch PetscDeviceContext dup; 312030f984aSJacob Faibussowitsch 313030f984aSJacob Faibussowitsch PetscFunctionBegin; 314030f984aSJacob Faibussowitsch PetscValidDeviceContext(dctx,1); 315030f984aSJacob Faibussowitsch PetscValidPointer(dctxdup,2); 3169566063dSJacob Faibussowitsch PetscCall(PetscDeviceContextCreate(&dup)); 3179566063dSJacob Faibussowitsch PetscCall(PetscDeviceContextSetStreamType(dup,dctx->streamType)); 3189566063dSJacob Faibussowitsch if (dctx->device) PetscCall(PetscDeviceContextSetDevice(dup,dctx->device)); 3199566063dSJacob Faibussowitsch PetscCall(PetscDeviceContextSetUp(dup)); 320a4af0ceeSJacob Faibussowitsch *dctxdup = dup; 321030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 322030f984aSJacob Faibussowitsch } 323030f984aSJacob Faibussowitsch 324030f984aSJacob Faibussowitsch /*@C 325030f984aSJacob Faibussowitsch PetscDeviceContextQueryIdle - Returns whether or not a PetscDeviceContext is idle 326030f984aSJacob Faibussowitsch 327030f984aSJacob Faibussowitsch Not Collective, Asynchronous 328030f984aSJacob Faibussowitsch 329030f984aSJacob Faibussowitsch Input Parameter: 330030f984aSJacob Faibussowitsch . dctx - The PetscDeviceContext object 331030f984aSJacob Faibussowitsch 332030f984aSJacob Faibussowitsch Output Parameter: 333030f984aSJacob Faibussowitsch . idle - PETSC_TRUE if PetscDeviceContext has NO work, PETSC_FALSE if it has work 334030f984aSJacob Faibussowitsch 335030f984aSJacob Faibussowitsch Notes: 336ef657721SJacob Faibussowitsch This routine only refers a singular context and does NOT take any of its children into 337ef657721SJacob Faibussowitsch account. That is, if dctx is idle but has dependents who do have work, this routine still 338ef657721SJacob Faibussowitsch returns PETSC_TRUE. 339030f984aSJacob Faibussowitsch 340030f984aSJacob Faibussowitsch Level: intermediate 341030f984aSJacob Faibussowitsch 342db781477SPatrick Sanan .seealso: `PetscDeviceContextCreate()`, `PetscDeviceContextWaitForContext()`, `PetscDeviceContextFork()` 343030f984aSJacob Faibussowitsch @*/ 344030f984aSJacob Faibussowitsch PetscErrorCode PetscDeviceContextQueryIdle(PetscDeviceContext dctx, PetscBool *idle) 345030f984aSJacob Faibussowitsch { 346030f984aSJacob Faibussowitsch PetscFunctionBegin; 347030f984aSJacob Faibussowitsch PetscValidDeviceContext(dctx,1); 348030f984aSJacob Faibussowitsch PetscValidBoolPointer(idle,2); 349*dbbe0bcdSBarry Smith PetscUseTypeMethod(dctx,query ,idle); 3509566063dSJacob Faibussowitsch PetscCall(PetscInfo(nullptr,"PetscDeviceContext id %" PetscInt_FMT " %s idle\n",dctx->id,*idle ? "was" : "was not")); 351030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 352030f984aSJacob Faibussowitsch } 353030f984aSJacob Faibussowitsch 354030f984aSJacob Faibussowitsch /*@C 355030f984aSJacob Faibussowitsch PetscDeviceContextWaitForContext - Make one context wait for another context to finish 356030f984aSJacob Faibussowitsch 357030f984aSJacob Faibussowitsch Not Collective, Asynchronous 358030f984aSJacob Faibussowitsch 359030f984aSJacob Faibussowitsch Input Parameters: 360030f984aSJacob Faibussowitsch + dctxa - The PetscDeviceContext object that is waiting 361030f984aSJacob Faibussowitsch - dctxb - The PetscDeviceContext object that is being waited on 362030f984aSJacob Faibussowitsch 363030f984aSJacob Faibussowitsch Notes: 364030f984aSJacob Faibussowitsch Serializes two PetscDeviceContexts. This routine uses only the state of dctxb at the moment this routine was 365030f984aSJacob Faibussowitsch called, so any future work queued will not affect dctxa. It is safe to pass the same context to both arguments. 366030f984aSJacob Faibussowitsch 367030f984aSJacob Faibussowitsch Level: beginner 368030f984aSJacob Faibussowitsch 369db781477SPatrick Sanan .seealso: `PetscDeviceContextCreate()`, `PetscDeviceContextQueryIdle()`, `PetscDeviceContextJoin()` 370030f984aSJacob Faibussowitsch @*/ 371030f984aSJacob Faibussowitsch PetscErrorCode PetscDeviceContextWaitForContext(PetscDeviceContext dctxa, PetscDeviceContext dctxb) 372030f984aSJacob Faibussowitsch { 373030f984aSJacob Faibussowitsch PetscFunctionBegin; 374030f984aSJacob Faibussowitsch PetscCheckCompatibleDeviceContexts(dctxa,1,dctxb,2); 375030f984aSJacob Faibussowitsch if (dctxa == dctxb) PetscFunctionReturn(0); 376*dbbe0bcdSBarry Smith PetscUseTypeMethod(dctxa,waitforcontext ,dctxb); 377030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 378030f984aSJacob Faibussowitsch } 379030f984aSJacob Faibussowitsch 380050c0c3dSJacob Faibussowitsch #define PETSC_USE_DEBUG_AND_INFO (PetscDefined(USE_DEBUG) && PetscDefined(USE_INFO)) 381050c0c3dSJacob Faibussowitsch #if PETSC_USE_DEBUG_AND_INFO 382050c0c3dSJacob Faibussowitsch #include <string> 383050c0c3dSJacob Faibussowitsch #endif 384030f984aSJacob Faibussowitsch /*@C 385030f984aSJacob Faibussowitsch PetscDeviceContextFork - Create a set of dependent child contexts from a parent context 386030f984aSJacob Faibussowitsch 387030f984aSJacob Faibussowitsch Not Collective, Asynchronous 388030f984aSJacob Faibussowitsch 389030f984aSJacob Faibussowitsch Input Parameters: 390030f984aSJacob Faibussowitsch + dctx - The parent PetscDeviceContext 391030f984aSJacob Faibussowitsch - n - The number of children to create 392030f984aSJacob Faibussowitsch 393030f984aSJacob Faibussowitsch Output Parameter: 394030f984aSJacob Faibussowitsch . dsub - The created child context(s) 395030f984aSJacob Faibussowitsch 396030f984aSJacob Faibussowitsch Notes: 397030f984aSJacob Faibussowitsch This routine creates n edges of a DAG from a source node which are causally dependent on the source node, meaning 398030f984aSJacob Faibussowitsch that work queued on child contexts will not start until the parent context finishes its work. This accounts for work 399030f984aSJacob Faibussowitsch queued on the parent up until calling this function, any subsequent work enqueued on the parent has no effect on the children. 400030f984aSJacob Faibussowitsch 401030f984aSJacob Faibussowitsch Any children created with this routine have their lifetimes bounded by the parent. That is, the parent context expects 402030f984aSJacob Faibussowitsch to free all of it's children (and ONLY its children) before itself is freed. 403030f984aSJacob Faibussowitsch 404030f984aSJacob Faibussowitsch DAG representation: 405030f984aSJacob Faibussowitsch .vb 406030f984aSJacob Faibussowitsch time -> 407030f984aSJacob Faibussowitsch 408030f984aSJacob Faibussowitsch -> dctx \----> dctx ------> 409030f984aSJacob Faibussowitsch \---> dsub[0] ---> 410030f984aSJacob Faibussowitsch \--> ... -------> 411030f984aSJacob Faibussowitsch \-> dsub[n-1] -> 412030f984aSJacob Faibussowitsch .ve 413030f984aSJacob Faibussowitsch 414030f984aSJacob Faibussowitsch Level: intermediate 415030f984aSJacob Faibussowitsch 416db781477SPatrick Sanan .seealso: `PetscDeviceContextJoin()`, `PetscDeviceContextSynchronize()`, `PetscDeviceContextQueryIdle()` 417030f984aSJacob Faibussowitsch @*/ 418030f984aSJacob Faibussowitsch PetscErrorCode PetscDeviceContextFork(PetscDeviceContext dctx, PetscInt n, PetscDeviceContext **dsub) 419030f984aSJacob Faibussowitsch { 420050c0c3dSJacob Faibussowitsch #if PETSC_USE_DEBUG_AND_INFO 421030f984aSJacob Faibussowitsch const PetscInt nBefore = n; 422030f984aSJacob Faibussowitsch static std::string idList; 423030f984aSJacob Faibussowitsch #endif 424bf025ffbSJacob Faibussowitsch PetscDeviceContext *dsubTmp = nullptr; 425030f984aSJacob Faibussowitsch PetscInt i = 0; 426030f984aSJacob Faibussowitsch 427030f984aSJacob Faibussowitsch PetscFunctionBegin; 428030f984aSJacob Faibussowitsch PetscValidDeviceContext(dctx,1); 429030f984aSJacob Faibussowitsch PetscValidPointer(dsub,3); 430bf025ffbSJacob Faibussowitsch PetscAssert(n >= 0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Number of contexts requested %" PetscInt_FMT " < 0",n); 4313ca90d2dSJacob Faibussowitsch #if PETSC_USE_DEBUG_AND_INFO 432030f984aSJacob Faibussowitsch /* reserve 4 chars per id, 2 for number and 2 for ', ' separator */ 433030f984aSJacob Faibussowitsch idList.reserve(4*n); 434030f984aSJacob Faibussowitsch #endif 435030f984aSJacob Faibussowitsch /* update child totals */ 436030f984aSJacob Faibussowitsch dctx->numChildren += n; 437030f984aSJacob Faibussowitsch /* now to find out if we have room */ 438030f984aSJacob Faibussowitsch if (dctx->numChildren > dctx->maxNumChildren) { 439030f984aSJacob Faibussowitsch /* no room, either from having too many kids or not having any */ 440030f984aSJacob Faibussowitsch if (dctx->childIDs) { 441030f984aSJacob Faibussowitsch /* have existing children, must reallocate them */ 4429566063dSJacob Faibussowitsch PetscCall(PetscRealloc(dctx->numChildren*sizeof(*dctx->childIDs),&dctx->childIDs)); 443030f984aSJacob Faibussowitsch /* clear the extra memory since realloc doesn't do it for us */ 4449566063dSJacob Faibussowitsch PetscCall(PetscArrayzero((dctx->childIDs)+(dctx->maxNumChildren),(dctx->numChildren)-(dctx->maxNumChildren))); 445030f984aSJacob Faibussowitsch } else { 446030f984aSJacob Faibussowitsch /* have no children */ 4479566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(dctx->numChildren,&dctx->childIDs)); 448030f984aSJacob Faibussowitsch } 449030f984aSJacob Faibussowitsch /* update total number of children */ 450030f984aSJacob Faibussowitsch dctx->maxNumChildren = dctx->numChildren; 451030f984aSJacob Faibussowitsch } 4529566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n,&dsubTmp)); 453030f984aSJacob Faibussowitsch while (n) { 454030f984aSJacob Faibussowitsch /* empty child slot */ 455030f984aSJacob Faibussowitsch if (!(dctx->childIDs[i])) { 456030f984aSJacob Faibussowitsch /* create the child context in the image of its parent */ 4579566063dSJacob Faibussowitsch PetscCall(PetscDeviceContextDuplicate(dctx,dsubTmp+i)); 4589566063dSJacob Faibussowitsch PetscCall(PetscDeviceContextWaitForContext(dsubTmp[i],dctx)); 459030f984aSJacob Faibussowitsch /* register the child with its parent */ 460030f984aSJacob Faibussowitsch dctx->childIDs[i] = dsubTmp[i]->id; 461050c0c3dSJacob Faibussowitsch #if PETSC_USE_DEBUG_AND_INFO 462030f984aSJacob Faibussowitsch idList += std::to_string(dsubTmp[i]->id); 463030f984aSJacob Faibussowitsch if (n != 1) idList += ", "; 464030f984aSJacob Faibussowitsch #endif 465030f984aSJacob Faibussowitsch --n; 466030f984aSJacob Faibussowitsch } 467030f984aSJacob Faibussowitsch ++i; 468030f984aSJacob Faibussowitsch } 4693ca90d2dSJacob Faibussowitsch #if PETSC_USE_DEBUG_AND_INFO 4709566063dSJacob Faibussowitsch PetscCall(PetscInfo(nullptr,"Forked %" PetscInt_FMT " children from parent %" PetscInt_FMT " with IDs: %s\n",nBefore,dctx->id,idList.c_str())); 471030f984aSJacob Faibussowitsch /* resets the size but doesn't deallocate the memory */ 472030f984aSJacob Faibussowitsch idList.clear(); 473030f984aSJacob Faibussowitsch #endif 474030f984aSJacob Faibussowitsch /* pass the children back to caller */ 475030f984aSJacob Faibussowitsch *dsub = dsubTmp; 476030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 477030f984aSJacob Faibussowitsch } 478030f984aSJacob Faibussowitsch 479030f984aSJacob Faibussowitsch /*@C 4805181c4f9SJacob Faibussowitsch PetscDeviceContextJoin - Converge a set of child contexts 481030f984aSJacob Faibussowitsch 482030f984aSJacob Faibussowitsch Not Collective, Asynchronous 483030f984aSJacob Faibussowitsch 484030f984aSJacob Faibussowitsch Input Parameters: 485030f984aSJacob Faibussowitsch + dctx - A PetscDeviceContext to converge on 486030f984aSJacob Faibussowitsch . n - The number of sub contexts to converge 487030f984aSJacob Faibussowitsch . joinMode - The type of join to perform 488030f984aSJacob Faibussowitsch - dsub - The sub contexts to converge 489030f984aSJacob Faibussowitsch 490030f984aSJacob Faibussowitsch Notes: 491030f984aSJacob Faibussowitsch If PetscDeviceContextFork() creates n edges from a source node which all depend on the 492030f984aSJacob Faibussowitsch source node, then this routine is the exact mirror. That is, it creates a node 493030f984aSJacob Faibussowitsch (represented in dctx) which recieves n edges (and optionally destroys them) which is 494030f984aSJacob Faibussowitsch dependent on the completion of all incoming edges. 495030f984aSJacob Faibussowitsch 496030f984aSJacob Faibussowitsch If joinMode is PETSC_DEVICE_CONTEXT_JOIN_DESTROY all contexts in dsub will be destroyed 497030f984aSJacob Faibussowitsch by this routine. Thus all sub contexts must have been created with the dctx passed to 498030f984aSJacob Faibussowitsch this routine. 499030f984aSJacob Faibussowitsch 500030f984aSJacob Faibussowitsch if joinMode is PETSC_DEVICE_CONTEXT_JOIN_NO_SYNC dctx waits for all sub contexts but the 501030f984aSJacob Faibussowitsch sub contexts do not wait for one another afterwards. 502030f984aSJacob Faibussowitsch 503030f984aSJacob Faibussowitsch If joinMode is PETSC_DEVICE_CONTEXT_JOIN_SYNC all sub contexts will additionally 504030f984aSJacob Faibussowitsch wait on dctx after converging. This has the effect of "synchronizing" the outgoing 505030f984aSJacob Faibussowitsch edges. 506030f984aSJacob Faibussowitsch 507030f984aSJacob Faibussowitsch DAG representations: 508030f984aSJacob Faibussowitsch If joinMode is PETSC_DEVICE_CONTEXT_JOIN_DESTROY 509030f984aSJacob Faibussowitsch .vb 510030f984aSJacob Faibussowitsch time -> 511030f984aSJacob Faibussowitsch 512030f984aSJacob Faibussowitsch -> dctx ---------/- dctx -> 513030f984aSJacob Faibussowitsch -> dsub[0] -----/ 514030f984aSJacob Faibussowitsch -> ... -------/ 515030f984aSJacob Faibussowitsch -> dsub[n-1] -/ 516030f984aSJacob Faibussowitsch .ve 517030f984aSJacob Faibussowitsch If joinMode is PETSC_DEVICE_CONTEXT_JOIN_NO_SYNC 518030f984aSJacob Faibussowitsch .vb 519030f984aSJacob Faibussowitsch time -> 520030f984aSJacob Faibussowitsch 521030f984aSJacob Faibussowitsch -> dctx ---------/- dctx -> 522030f984aSJacob Faibussowitsch -> dsub[0] -----/---------> 523030f984aSJacob Faibussowitsch -> ... -------/----------> 524030f984aSJacob Faibussowitsch -> dsub[n-1] -/-----------> 525030f984aSJacob Faibussowitsch .ve 526030f984aSJacob Faibussowitsch If joinMode is PETSC_DEVICE_CONTEXT_JOIN_SYNC 527030f984aSJacob Faibussowitsch .vb 528030f984aSJacob Faibussowitsch time -> 529030f984aSJacob Faibussowitsch 530030f984aSJacob Faibussowitsch -> dctx ---------/- dctx -\----> dctx ------> 531030f984aSJacob Faibussowitsch -> dsub[0] -----/ \---> dsub[0] ---> 532030f984aSJacob Faibussowitsch -> ... -------/ \--> ... -------> 533030f984aSJacob Faibussowitsch -> dsub[n-1] -/ \-> dsub[n-1] -> 534030f984aSJacob Faibussowitsch .ve 535030f984aSJacob Faibussowitsch 536030f984aSJacob Faibussowitsch Level: intermediate 537030f984aSJacob Faibussowitsch 538db781477SPatrick Sanan .seealso: `PetscDeviceContextFork()`, `PetscDeviceContextSynchronize()`, `PetscDeviceContextJoinMode` 539030f984aSJacob Faibussowitsch @*/ 540030f984aSJacob Faibussowitsch PetscErrorCode PetscDeviceContextJoin(PetscDeviceContext dctx, PetscInt n, PetscDeviceContextJoinMode joinMode, PetscDeviceContext **dsub) 541030f984aSJacob Faibussowitsch { 542030f984aSJacob Faibussowitsch #if defined(PETSC_USE_DEBUG) && defined(PETSC_USE_INFO) 543030f984aSJacob Faibussowitsch static std::string idList; 544030f984aSJacob Faibussowitsch #endif 545030f984aSJacob Faibussowitsch 546030f984aSJacob Faibussowitsch PetscFunctionBegin; 547030f984aSJacob Faibussowitsch /* validity of dctx is checked in the wait-for loop */ 548030f984aSJacob Faibussowitsch PetscValidPointer(dsub,4); 549bf025ffbSJacob Faibussowitsch PetscAssert(n >= 0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Number of contexts merged %" PetscInt_FMT " < 0",n); 550030f984aSJacob Faibussowitsch #if defined(PETSC_USE_DEBUG) && defined(PETSC_USE_INFO) 551030f984aSJacob Faibussowitsch /* reserve 4 chars per id, 2 for number and 2 for ', ' separator */ 552030f984aSJacob Faibussowitsch idList.reserve(4*n); 553030f984aSJacob Faibussowitsch #endif 554030f984aSJacob Faibussowitsch /* first dctx waits on all the incoming edges */ 555030f984aSJacob Faibussowitsch for (PetscInt i = 0; i < n; ++i) { 556030f984aSJacob Faibussowitsch PetscCheckCompatibleDeviceContexts(dctx,1,(*dsub)[i],4); 5579566063dSJacob Faibussowitsch PetscCall(PetscDeviceContextWaitForContext(dctx,(*dsub)[i])); 558030f984aSJacob Faibussowitsch #if defined(PETSC_USE_DEBUG) && defined(PETSC_USE_INFO) 559030f984aSJacob Faibussowitsch idList += std::to_string((*dsub)[i]->id); 560030f984aSJacob Faibussowitsch if (i+1 < n) idList += ", "; 561030f984aSJacob Faibussowitsch #endif 562030f984aSJacob Faibussowitsch } 563030f984aSJacob Faibussowitsch 564030f984aSJacob Faibussowitsch /* now we handle the aftermath */ 565030f984aSJacob Faibussowitsch switch (joinMode) { 566030f984aSJacob Faibussowitsch case PETSC_DEVICE_CONTEXT_JOIN_DESTROY: 567030f984aSJacob Faibussowitsch { 568030f984aSJacob Faibussowitsch PetscInt j = 0; 569030f984aSJacob Faibussowitsch 570bf025ffbSJacob 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); 571030f984aSJacob Faibussowitsch /* update child count while it's still fresh in memory */ 572030f984aSJacob Faibussowitsch dctx->numChildren -= n; 573030f984aSJacob Faibussowitsch for (PetscInt i = 0; i < dctx->maxNumChildren; ++i) { 574030f984aSJacob Faibussowitsch if (dctx->childIDs[i] && (dctx->childIDs[i] == (*dsub)[j]->id)) { 575030f984aSJacob Faibussowitsch /* child is one of ours, can destroy it */ 5769566063dSJacob Faibussowitsch PetscCall(PetscDeviceContextDestroy((*dsub)+j)); 577030f984aSJacob Faibussowitsch /* reset the child slot */ 578030f984aSJacob Faibussowitsch dctx->childIDs[i] = 0; 579030f984aSJacob Faibussowitsch if (++j == n) break; 580030f984aSJacob Faibussowitsch } 581030f984aSJacob Faibussowitsch } 582030f984aSJacob 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 */ 583bf025ffbSJacob 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); 5849566063dSJacob Faibussowitsch PetscCall(PetscFree(*dsub)); 585030f984aSJacob Faibussowitsch } 586030f984aSJacob Faibussowitsch break; 587030f984aSJacob Faibussowitsch case PETSC_DEVICE_CONTEXT_JOIN_SYNC: 5889566063dSJacob Faibussowitsch for (PetscInt i = 0; i < n; ++i) PetscCall(PetscDeviceContextWaitForContext((*dsub)[i],dctx)); 589030f984aSJacob Faibussowitsch case PETSC_DEVICE_CONTEXT_JOIN_NO_SYNC: 590030f984aSJacob Faibussowitsch break; 591030f984aSJacob Faibussowitsch default: 592030f984aSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Unknown PetscDeviceContextJoinMode given"); 593030f984aSJacob Faibussowitsch } 594030f984aSJacob Faibussowitsch 595030f984aSJacob Faibussowitsch #if defined(PETSC_USE_DEBUG) && defined(PETSC_USE_INFO) 5969566063dSJacob 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())); 597030f984aSJacob Faibussowitsch idList.clear(); 598030f984aSJacob Faibussowitsch #endif 599030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 600030f984aSJacob Faibussowitsch } 601030f984aSJacob Faibussowitsch 602030f984aSJacob Faibussowitsch /*@C 6035181c4f9SJacob Faibussowitsch PetscDeviceContextSynchronize - Block the host until all work queued on or associated with a PetscDeviceContext has finished 604030f984aSJacob Faibussowitsch 605030f984aSJacob Faibussowitsch Not Collective, Synchronous 606030f984aSJacob Faibussowitsch 607030f984aSJacob Faibussowitsch Input Parameters: 608030f984aSJacob Faibussowitsch . dctx - The PetscDeviceContext to synchronize 609030f984aSJacob Faibussowitsch 610030f984aSJacob Faibussowitsch Level: beginner 611030f984aSJacob Faibussowitsch 612db781477SPatrick Sanan .seealso: `PetscDeviceContextFork()`, `PetscDeviceContextJoin()`, `PetscDeviceContextQueryIdle()` 613030f984aSJacob Faibussowitsch @*/ 614030f984aSJacob Faibussowitsch PetscErrorCode PetscDeviceContextSynchronize(PetscDeviceContext dctx) 615030f984aSJacob Faibussowitsch { 616030f984aSJacob Faibussowitsch PetscFunctionBegin; 617030f984aSJacob Faibussowitsch PetscValidDeviceContext(dctx,1); 618030f984aSJacob Faibussowitsch /* if it isn't setup there is nothing to sync on */ 619*dbbe0bcdSBarry Smith if (dctx->setup) PetscUseTypeMethod(dctx,synchronize); 620030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 621030f984aSJacob Faibussowitsch } 622030f984aSJacob Faibussowitsch 623a4af0ceeSJacob Faibussowitsch #define PETSC_DEVICE_CONTEXT_DEFAULT_DEVICE PETSC_DEVICE_DEFAULT 624a4af0ceeSJacob Faibussowitsch // REMOVE ME (change) 625a4af0ceeSJacob Faibussowitsch #define PETSC_DEVICE_CONTEXT_DEFAULT_STREAM PETSC_STREAM_GLOBAL_BLOCKING 626030f984aSJacob Faibussowitsch 627a4af0ceeSJacob Faibussowitsch static PetscDeviceType rootDeviceType = PETSC_DEVICE_CONTEXT_DEFAULT_DEVICE; 628a4af0ceeSJacob Faibussowitsch static PetscStreamType rootStreamType = PETSC_DEVICE_CONTEXT_DEFAULT_STREAM; 629bf025ffbSJacob Faibussowitsch static PetscDeviceContext globalContext = nullptr; 630a4af0ceeSJacob Faibussowitsch 631a4af0ceeSJacob Faibussowitsch /* when PetsDevice initializes PetscDeviceContext eagerly the type of device created should 632a4af0ceeSJacob Faibussowitsch * match whatever device is eagerly intialized */ 633a4af0ceeSJacob Faibussowitsch PetscErrorCode PetscDeviceContextSetRootDeviceType_Internal(PetscDeviceType type) 634030f984aSJacob Faibussowitsch { 635030f984aSJacob Faibussowitsch PetscFunctionBegin; 636a4af0ceeSJacob Faibussowitsch PetscValidDeviceType(type,1); 637a4af0ceeSJacob Faibussowitsch rootDeviceType = type; 638030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 639030f984aSJacob Faibussowitsch } 640030f984aSJacob Faibussowitsch 641a4af0ceeSJacob Faibussowitsch #if 0 642a4af0ceeSJacob Faibussowitsch /* currently unused */ 643a4af0ceeSJacob Faibussowitsch PetscErrorCode PetscDeviceContextSetRootStreamType_Internal(PetscStreamType type) 644030f984aSJacob Faibussowitsch { 645a4af0ceeSJacob Faibussowitsch PetscFunctionBegin; 646a4af0ceeSJacob Faibussowitsch PetscValidStreamType(type,1); 647a4af0ceeSJacob Faibussowitsch rootStreamType = type; 648a4af0ceeSJacob Faibussowitsch PetscFunctionReturn(0); 649a4af0ceeSJacob Faibussowitsch } 650a4af0ceeSJacob Faibussowitsch #endif 651a4af0ceeSJacob Faibussowitsch 652a4af0ceeSJacob Faibussowitsch static PetscErrorCode PetscDeviceContextSetupGlobalContext_Private(void) 653a4af0ceeSJacob Faibussowitsch { 654a4af0ceeSJacob Faibussowitsch static const auto PetscDeviceContextFinalizer = []() -> PetscErrorCode { 655030f984aSJacob Faibussowitsch 656030f984aSJacob Faibussowitsch PetscFunctionBegin; 6579566063dSJacob Faibussowitsch PetscCall(PetscDeviceContextDestroy(&globalContext)); 658a4af0ceeSJacob Faibussowitsch rootDeviceType = PETSC_DEVICE_CONTEXT_DEFAULT_DEVICE; 659a4af0ceeSJacob Faibussowitsch rootStreamType = PETSC_DEVICE_CONTEXT_DEFAULT_STREAM; 660a4af0ceeSJacob Faibussowitsch PetscFunctionReturn(0); 661a4af0ceeSJacob Faibussowitsch }; 662a4af0ceeSJacob Faibussowitsch 663a4af0ceeSJacob Faibussowitsch PetscFunctionBegin; 664a4af0ceeSJacob Faibussowitsch if (globalContext) PetscFunctionReturn(0); 665a4af0ceeSJacob Faibussowitsch /* this exists purely as a valid device check. */ 6669566063dSJacob Faibussowitsch PetscCall(PetscDeviceInitializePackage()); 6679566063dSJacob Faibussowitsch PetscCall(PetscRegisterFinalize(PetscDeviceContextFinalizer)); 6689566063dSJacob Faibussowitsch PetscCall(PetscInfo(nullptr,"Initializing global PetscDeviceContext\n")); 669a4af0ceeSJacob Faibussowitsch /* we call the allocator directly here since the ObjectPool creates a PetscContainer which 670a4af0ceeSJacob Faibussowitsch * eventually tries to call logging functions. However, this routine may be purposefully 671a4af0ceeSJacob Faibussowitsch * called __before__ logging is initialized, so the logging function would PETSCABORT */ 6729566063dSJacob Faibussowitsch PetscCall(contextPool.allocator().create(&globalContext)); 6739566063dSJacob Faibussowitsch PetscCall(PetscDeviceContextSetStreamType(globalContext,rootStreamType)); 6749566063dSJacob Faibussowitsch PetscCall(PetscDeviceContextSetDefaultDeviceForType_Internal(globalContext,rootDeviceType)); 6759566063dSJacob Faibussowitsch PetscCall(PetscDeviceContextSetUp(globalContext)); 676030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 677030f984aSJacob Faibussowitsch } 678030f984aSJacob Faibussowitsch 679030f984aSJacob Faibussowitsch /*@C 6805181c4f9SJacob Faibussowitsch PetscDeviceContextGetCurrentContext - Get the current active PetscDeviceContext 681030f984aSJacob Faibussowitsch 682030f984aSJacob Faibussowitsch Not Collective, Asynchronous 683030f984aSJacob Faibussowitsch 684030f984aSJacob Faibussowitsch Output Parameter: 685030f984aSJacob Faibussowitsch . dctx - The PetscDeviceContext 686030f984aSJacob Faibussowitsch 687030f984aSJacob Faibussowitsch Notes: 688a4af0ceeSJacob Faibussowitsch The user generally should not destroy contexts retrieved with this routine unless they 689a4af0ceeSJacob Faibussowitsch themselves have created them. There exists no protection against destroying the root 690a4af0ceeSJacob Faibussowitsch context. 691030f984aSJacob Faibussowitsch 692030f984aSJacob Faibussowitsch Developer Notes: 693a4af0ceeSJacob Faibussowitsch Unless the user has set their own, this routine creates the "root" context the first time it 694a4af0ceeSJacob Faibussowitsch is called, registering its destructor to PetscFinalize(). 695030f984aSJacob Faibussowitsch 696030f984aSJacob Faibussowitsch Level: beginner 697030f984aSJacob Faibussowitsch 698db781477SPatrick Sanan .seealso: `PetscDeviceContextSetCurrentContext()`, `PetscDeviceContextFork()`, 699db781477SPatrick Sanan `PetscDeviceContextJoin()`, `PetscDeviceContextCreate()` 700030f984aSJacob Faibussowitsch @*/ 701030f984aSJacob Faibussowitsch PetscErrorCode PetscDeviceContextGetCurrentContext(PetscDeviceContext *dctx) 702030f984aSJacob Faibussowitsch { 703a4af0ceeSJacob Faibussowitsch PetscFunctionBegin; 704a4af0ceeSJacob Faibussowitsch PetscValidPointer(dctx,1); 7059566063dSJacob Faibussowitsch PetscCall(PetscDeviceContextSetupGlobalContext_Private()); 706a4af0ceeSJacob Faibussowitsch /* while the static analyzer can find global variables, it will throw a warning about not 707a4af0ceeSJacob Faibussowitsch * being able to connect this back to the function arguments */ 708a4af0ceeSJacob Faibussowitsch PetscDisableStaticAnalyzerForExpressionUnderstandingThatThisIsDangerousAndBugprone(PetscValidDeviceContext(globalContext,-1)); 709030f984aSJacob Faibussowitsch *dctx = globalContext; 710030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 711030f984aSJacob Faibussowitsch } 712030f984aSJacob Faibussowitsch 713030f984aSJacob Faibussowitsch /*@C 7145181c4f9SJacob Faibussowitsch PetscDeviceContextSetCurrentContext - Set the current active PetscDeviceContext 715030f984aSJacob Faibussowitsch 716030f984aSJacob Faibussowitsch Not Collective, Asynchronous 717030f984aSJacob Faibussowitsch 718030f984aSJacob Faibussowitsch Input Parameter: 719030f984aSJacob Faibussowitsch . dctx - The PetscDeviceContext 720030f984aSJacob Faibussowitsch 721030f984aSJacob Faibussowitsch Notes: 722a4af0ceeSJacob Faibussowitsch This routine can be used to set the defacto "root" PetscDeviceContext to a user-defined 723a4af0ceeSJacob Faibussowitsch implementation by calling this routine immediately after PetscInitialize() and ensuring that 724a4af0ceeSJacob Faibussowitsch PetscDevice is not greedily intialized. In this case the user is responsible for destroying 725a4af0ceeSJacob Faibussowitsch their PetscDeviceContext before PetscFinalize() returns. 726a4af0ceeSJacob Faibussowitsch 727a4af0ceeSJacob Faibussowitsch The old context is not stored in any way by this routine; if one is overriding a context that 728a4af0ceeSJacob Faibussowitsch they themselves do not control, one should take care to temporarily store it by calling 729a4af0ceeSJacob Faibussowitsch PetscDeviceContextGetCurrentContext() before calling this routine. 730030f984aSJacob Faibussowitsch 731030f984aSJacob Faibussowitsch Level: beginner 732030f984aSJacob Faibussowitsch 733db781477SPatrick Sanan .seealso: `PetscDeviceContextGetCurrentContext()`, `PetscDeviceContextFork()`, 734db781477SPatrick Sanan `PetscDeviceContextJoin()`, `PetscDeviceContextCreate()` 735030f984aSJacob Faibussowitsch @*/ 736030f984aSJacob Faibussowitsch PetscErrorCode PetscDeviceContextSetCurrentContext(PetscDeviceContext dctx) 737030f984aSJacob Faibussowitsch { 738030f984aSJacob Faibussowitsch PetscFunctionBegin; 739030f984aSJacob Faibussowitsch PetscValidDeviceContext(dctx,1); 740bf025ffbSJacob 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); 741030f984aSJacob Faibussowitsch globalContext = dctx; 7429566063dSJacob Faibussowitsch PetscCall(PetscInfo(nullptr,"Set global PetscDeviceContext id %" PetscInt_FMT "\n",dctx->id)); 743030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 744030f984aSJacob Faibussowitsch } 745030f984aSJacob Faibussowitsch 746030f984aSJacob Faibussowitsch /*@C 747030f984aSJacob Faibussowitsch PetscDeviceContextSetFromOptions - Configure a PetscDeviceContext from the options database 748030f984aSJacob Faibussowitsch 749030f984aSJacob Faibussowitsch Collective on comm, Asynchronous 750030f984aSJacob Faibussowitsch 751030f984aSJacob Faibussowitsch Input Parameters: 752030f984aSJacob Faibussowitsch + comm - MPI communicator on which to query the options database 753030f984aSJacob Faibussowitsch . prefix - prefix to prepend to all options database queries, NULL if not needed 754030f984aSJacob Faibussowitsch - dctx - The PetscDeviceContext to configure 755030f984aSJacob Faibussowitsch 756030f984aSJacob Faibussowitsch Output Parameter: 757030f984aSJacob Faibussowitsch . dctx - The PetscDeviceContext 758030f984aSJacob Faibussowitsch 759030f984aSJacob Faibussowitsch Options Database: 760a4af0ceeSJacob Faibussowitsch + -device_context_stream_type - type of stream to create inside the PetscDeviceContext - 761030f984aSJacob Faibussowitsch PetscDeviceContextSetStreamType() 762a4af0ceeSJacob Faibussowitsch - -device_context_device_type - the type of PetscDevice to attach by default - PetscDeviceType 763030f984aSJacob Faibussowitsch 764030f984aSJacob Faibussowitsch Level: beginner 765030f984aSJacob Faibussowitsch 766db781477SPatrick Sanan .seealso: `PetscDeviceContextSetStreamType()`, `PetscDeviceContextSetDevice()` 767030f984aSJacob Faibussowitsch @*/ 768030f984aSJacob Faibussowitsch PetscErrorCode PetscDeviceContextSetFromOptions(MPI_Comm comm, const char prefix[], PetscDeviceContext dctx) 769030f984aSJacob Faibussowitsch { 770030f984aSJacob Faibussowitsch PetscBool flag; 771a4af0ceeSJacob Faibussowitsch PetscInt stype,dtype; 772030f984aSJacob Faibussowitsch 773030f984aSJacob Faibussowitsch PetscFunctionBegin; 774a4af0ceeSJacob Faibussowitsch if (prefix) PetscValidCharPointer(prefix,2); 775030f984aSJacob Faibussowitsch PetscValidDeviceContext(dctx,3); 776d0609cedSBarry Smith PetscOptionsBegin(comm,prefix,"PetscDeviceContext Options","Sys"); 7779566063dSJacob Faibussowitsch PetscCall(PetscOptionsEList("-device_context_stream_type","PetscDeviceContext PetscStreamType","PetscDeviceContextSetStreamType",PetscStreamTypes,PETSC_STREAM_MAX,PetscStreamTypes[dctx->streamType],&stype,&flag)); 7789566063dSJacob Faibussowitsch if (flag) PetscCall(PetscDeviceContextSetStreamType(dctx,static_cast<PetscStreamType>(stype))); 7799566063dSJacob 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)); 780030f984aSJacob Faibussowitsch if (flag) { 7819566063dSJacob Faibussowitsch PetscCall(PetscDeviceContextSetDefaultDeviceForType_Internal(dctx,static_cast<PetscDeviceType>(dtype+1))); 782a4af0ceeSJacob Faibussowitsch } 783d0609cedSBarry Smith PetscOptionsEnd(); 784030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 785030f984aSJacob Faibussowitsch } 786