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_", 11a4af0ceeSJacob Faibussowitsch PETSC_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_", 20a4af0ceeSJacob Faibussowitsch PETSC_NULLPTR 21a4af0ceeSJacob Faibussowitsch }; 22a4af0ceeSJacob Faibussowitsch 23030f984aSJacob Faibussowitsch /* Define the allocator */ 24*17f48955SJacob Faibussowitsch struct PetscDeviceContextAllocator : Petsc::AllocatorBase<PetscDeviceContext> 25030f984aSJacob Faibussowitsch { 26030f984aSJacob Faibussowitsch static PetscInt PetscDeviceContextID; 27030f984aSJacob Faibussowitsch 28*17f48955SJacob Faibussowitsch PETSC_NODISCARD static PetscErrorCode create(PetscDeviceContext *dctx) noexcept 29030f984aSJacob Faibussowitsch { 30030f984aSJacob Faibussowitsch PetscDeviceContext dc; 31030f984aSJacob Faibussowitsch PetscErrorCode ierr; 32030f984aSJacob Faibussowitsch 33030f984aSJacob Faibussowitsch PetscFunctionBegin; 34030f984aSJacob Faibussowitsch ierr = PetscNew(&dc);CHKERRQ(ierr); 35030f984aSJacob Faibussowitsch dc->id = PetscDeviceContextID++; 36030f984aSJacob Faibussowitsch dc->idle = PETSC_TRUE; 37030f984aSJacob Faibussowitsch dc->streamType = PETSC_STREAM_DEFAULT_BLOCKING; 38030f984aSJacob Faibussowitsch *dctx = dc; 39030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 40030f984aSJacob Faibussowitsch } 41030f984aSJacob Faibussowitsch 42*17f48955SJacob Faibussowitsch PETSC_NODISCARD static PetscErrorCode destroy(PetscDeviceContext dctx) noexcept 43030f984aSJacob Faibussowitsch { 44030f984aSJacob Faibussowitsch PetscErrorCode ierr; 45030f984aSJacob Faibussowitsch 46030f984aSJacob Faibussowitsch PetscFunctionBegin; 473ca90d2dSJacob Faibussowitsch if (PetscUnlikelyDebug(dctx->numChildren)) SETERRQ1(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); 48030f984aSJacob Faibussowitsch if (dctx->ops->destroy) {ierr = (*dctx->ops->destroy)(dctx);CHKERRQ(ierr);} 49030f984aSJacob Faibussowitsch ierr = PetscDeviceDestroy(&dctx->device);CHKERRQ(ierr); 50030f984aSJacob Faibussowitsch ierr = PetscFree(dctx->childIDs);CHKERRQ(ierr); 51030f984aSJacob Faibussowitsch ierr = PetscFree(dctx);CHKERRQ(ierr); 52030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 53030f984aSJacob Faibussowitsch } 54030f984aSJacob Faibussowitsch 55*17f48955SJacob Faibussowitsch PETSC_NODISCARD static PetscErrorCode reset(PetscDeviceContext dctx) noexcept 56030f984aSJacob Faibussowitsch { 57030f984aSJacob Faibussowitsch PetscErrorCode ierr; 58030f984aSJacob Faibussowitsch 59030f984aSJacob Faibussowitsch PetscFunctionBegin; 60030f984aSJacob Faibussowitsch /* don't deallocate the child array, rather just zero it out */ 61030f984aSJacob Faibussowitsch ierr = PetscArrayzero(dctx->childIDs,dctx->maxNumChildren);CHKERRQ(ierr); 62030f984aSJacob Faibussowitsch dctx->setup = PETSC_FALSE; 63030f984aSJacob Faibussowitsch dctx->numChildren = 0; 64030f984aSJacob Faibussowitsch dctx->idle = PETSC_TRUE; 65030f984aSJacob Faibussowitsch dctx->streamType = PETSC_STREAM_DEFAULT_BLOCKING; 66030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 67030f984aSJacob Faibussowitsch } 68030f984aSJacob Faibussowitsch 69*17f48955SJacob Faibussowitsch PETSC_NODISCARD static constexpr PetscErrorCode finalize() noexcept { return 0; } 70030f984aSJacob Faibussowitsch }; 71a4af0ceeSJacob Faibussowitsch /* an ID = 0 is invalid */ 72a4af0ceeSJacob Faibussowitsch PetscInt PetscDeviceContextAllocator::PetscDeviceContextID = 1; 73030f984aSJacob Faibussowitsch 74030f984aSJacob Faibussowitsch static Petsc::ObjectPool<PetscDeviceContext,PetscDeviceContextAllocator> contextPool; 75030f984aSJacob Faibussowitsch 76030f984aSJacob Faibussowitsch /*@C 77030f984aSJacob Faibussowitsch PetscDeviceContextCreate - Creates a PetscDeviceContext 78030f984aSJacob Faibussowitsch 79030f984aSJacob Faibussowitsch Not Collective, Asynchronous 80030f984aSJacob Faibussowitsch 8101d2d390SJose E. Roman Output Paramemter: 82030f984aSJacob Faibussowitsch . dctx - The PetscDeviceContext 83030f984aSJacob Faibussowitsch 84030f984aSJacob Faibussowitsch Notes: 85030f984aSJacob Faibussowitsch Unlike almost every other PETSc class it is advised that most users use 86030f984aSJacob Faibussowitsch PetscDeviceContextDuplicate() rather than this routine to create new contexts. Contexts 87030f984aSJacob Faibussowitsch of different types are incompatible with one another; using 88030f984aSJacob Faibussowitsch PetscDeviceContextDuplicate() ensures compatible types. 89030f984aSJacob Faibussowitsch 90030f984aSJacob Faibussowitsch Level: beginner 91030f984aSJacob Faibussowitsch 92030f984aSJacob Faibussowitsch .seealso: PetscDeviceContextDuplicate(), PetscDeviceContextSetDevice(), 935181c4f9SJacob Faibussowitsch PetscDeviceContextSetStreamType(), PetscDeviceContextSetUp(), 945181c4f9SJacob Faibussowitsch PetscDeviceContextSetFromOptions(), PetscDeviceContextDestroy() 95030f984aSJacob Faibussowitsch @*/ 96030f984aSJacob Faibussowitsch PetscErrorCode PetscDeviceContextCreate(PetscDeviceContext *dctx) 97030f984aSJacob Faibussowitsch { 98030f984aSJacob Faibussowitsch PetscErrorCode ierr; 99030f984aSJacob Faibussowitsch 100030f984aSJacob Faibussowitsch PetscFunctionBegin; 101030f984aSJacob Faibussowitsch PetscValidPointer(dctx,1); 102030f984aSJacob Faibussowitsch ierr = PetscDeviceInitializePackage();CHKERRQ(ierr); 103030f984aSJacob Faibussowitsch ierr = contextPool.get(*dctx);CHKERRQ(ierr); 104030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 105030f984aSJacob Faibussowitsch } 106030f984aSJacob Faibussowitsch 107030f984aSJacob Faibussowitsch /*@C 108030f984aSJacob Faibussowitsch PetscDeviceContextDestroy - Frees a PetscDeviceContext 109030f984aSJacob Faibussowitsch 110030f984aSJacob Faibussowitsch Not Collective, Asynchronous 111030f984aSJacob Faibussowitsch 112030f984aSJacob Faibussowitsch Input Parameters: 113030f984aSJacob Faibussowitsch . dctx - The PetscDeviceContext 114030f984aSJacob Faibussowitsch 115030f984aSJacob Faibussowitsch Notes: 116030f984aSJacob Faibussowitsch No implicit synchronization occurs due to this routine, all resources are released completely asynchronously 117030f984aSJacob Faibussowitsch w.r.t. the host. If one needs to guarantee access to the data produced on this contexts stream one should perform the 118030f984aSJacob Faibussowitsch appropriate synchronization before calling this routine. 119030f984aSJacob Faibussowitsch 120030f984aSJacob Faibussowitsch Developer Notes: 121030f984aSJacob Faibussowitsch The context is never actually "destroyed", only returned to an ever growing pool of 122030f984aSJacob Faibussowitsch contexts. There are currently no safeguards on the size of the pool, this should perhaps 123030f984aSJacob Faibussowitsch be implemented. 124030f984aSJacob Faibussowitsch 125030f984aSJacob Faibussowitsch Level: beginner 126030f984aSJacob Faibussowitsch 127030f984aSJacob Faibussowitsch .seealso: PetscDeviceContextCreate(), PetscDeviceContextSetDevice(), PetscDeviceContextSetUp(), PetscDeviceContextSynchronize() 128030f984aSJacob Faibussowitsch @*/ 129030f984aSJacob Faibussowitsch PetscErrorCode PetscDeviceContextDestroy(PetscDeviceContext *dctx) 130030f984aSJacob Faibussowitsch { 131030f984aSJacob Faibussowitsch PetscErrorCode ierr; 132030f984aSJacob Faibussowitsch 133030f984aSJacob Faibussowitsch PetscFunctionBegin; 134030f984aSJacob Faibussowitsch if (!*dctx) PetscFunctionReturn(0); 135030f984aSJacob Faibussowitsch ierr = contextPool.reclaim(std::move(*dctx));CHKERRQ(ierr); 136a4af0ceeSJacob Faibussowitsch *dctx = PETSC_NULLPTR; 137030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 138030f984aSJacob Faibussowitsch } 139030f984aSJacob Faibussowitsch 140030f984aSJacob Faibussowitsch /*@C 141030f984aSJacob Faibussowitsch PetscDeviceContextSetStreamType - Set the implementation type of the underlying stream for a PetscDeviceContext 142030f984aSJacob Faibussowitsch 143030f984aSJacob Faibussowitsch Not Collective, Asynchronous 144030f984aSJacob Faibussowitsch 14501d2d390SJose E. Roman Input Parameters: 146030f984aSJacob Faibussowitsch + dctx - The PetscDeviceContext 147030f984aSJacob Faibussowitsch - type - The PetscStreamType 148030f984aSJacob Faibussowitsch 149030f984aSJacob Faibussowitsch Notes: 150030f984aSJacob Faibussowitsch See PetscStreamType in include/petscdevicetypes.h for more information on the available 151030f984aSJacob Faibussowitsch types and their interactions. If the PetscDeviceContext was previously set up and stream 152030f984aSJacob Faibussowitsch type was changed, you must call PetscDeviceContextSetUp() again after this routine. 153030f984aSJacob Faibussowitsch 154030f984aSJacob Faibussowitsch Level: intermediate 155030f984aSJacob Faibussowitsch 1565181c4f9SJacob Faibussowitsch .seealso: PetscDeviceContextGetStreamType(), PetscDeviceContextCreate(), PetscDeviceContextSetUp(), PetscDeviceContextSetFromOptions() 157030f984aSJacob Faibussowitsch @*/ 158030f984aSJacob Faibussowitsch PetscErrorCode PetscDeviceContextSetStreamType(PetscDeviceContext dctx, PetscStreamType type) 159030f984aSJacob Faibussowitsch { 160030f984aSJacob Faibussowitsch PetscFunctionBegin; 161030f984aSJacob Faibussowitsch PetscValidDeviceContext(dctx,1); 162030f984aSJacob Faibussowitsch PetscValidStreamType(type,2); 163030f984aSJacob Faibussowitsch /* only need to do complex swapping if the object has already been setup */ 164030f984aSJacob Faibussowitsch if (dctx->setup && (dctx->streamType != type)) { 165030f984aSJacob Faibussowitsch PetscErrorCode ierr; 166030f984aSJacob Faibussowitsch 167030f984aSJacob Faibussowitsch ierr = (*dctx->ops->changestreamtype)(dctx,type);CHKERRQ(ierr); 168030f984aSJacob Faibussowitsch dctx->setup = PETSC_FALSE; 169030f984aSJacob Faibussowitsch } 170030f984aSJacob Faibussowitsch dctx->streamType = type; 171030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 172030f984aSJacob Faibussowitsch } 173030f984aSJacob Faibussowitsch 174030f984aSJacob Faibussowitsch /*@C 175030f984aSJacob Faibussowitsch PetscDeviceContextGetStreamType - Get the implementation type of the underlying stream for a PetscDeviceContext 176030f984aSJacob Faibussowitsch 177030f984aSJacob Faibussowitsch Not Collective, Asynchronous 178030f984aSJacob Faibussowitsch 17901d2d390SJose E. Roman Input Parameter: 180030f984aSJacob Faibussowitsch . dctx - The PetscDeviceContext 181030f984aSJacob Faibussowitsch 182030f984aSJacob Faibussowitsch Output Parameter: 183030f984aSJacob Faibussowitsch . type - The PetscStreamType 184030f984aSJacob Faibussowitsch 185030f984aSJacob Faibussowitsch Notes: 186030f984aSJacob Faibussowitsch See PetscStreamType in include/petscdevicetypes.h for more information on the available types and their interactions 187030f984aSJacob Faibussowitsch 188030f984aSJacob Faibussowitsch Level: intermediate 189030f984aSJacob Faibussowitsch 1905181c4f9SJacob Faibussowitsch .seealso: PetscDeviceContextSetStreamType(), PetscDeviceContextCreate(), PetscDeviceContextSetFromOptions() 191030f984aSJacob Faibussowitsch @*/ 192030f984aSJacob Faibussowitsch PetscErrorCode PetscDeviceContextGetStreamType(PetscDeviceContext dctx, PetscStreamType *type) 193030f984aSJacob Faibussowitsch { 194030f984aSJacob Faibussowitsch PetscFunctionBegin; 195030f984aSJacob Faibussowitsch PetscValidDeviceContext(dctx,1); 196030f984aSJacob Faibussowitsch PetscValidIntPointer(type,2); 197030f984aSJacob Faibussowitsch *type = dctx->streamType; 198030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 199030f984aSJacob Faibussowitsch } 200030f984aSJacob Faibussowitsch 201030f984aSJacob Faibussowitsch /*@C 202030f984aSJacob Faibussowitsch PetscDeviceContextSetDevice - Set the underlying device for the PetscDeviceContext 203030f984aSJacob Faibussowitsch 204030f984aSJacob Faibussowitsch Not Collective, Possibly Synchronous 205030f984aSJacob Faibussowitsch 20601d2d390SJose E. Roman Input Parameters: 207030f984aSJacob Faibussowitsch + dctx - The PetscDeviceContext 208030f984aSJacob Faibussowitsch - device - The PetscDevice 209030f984aSJacob Faibussowitsch 210030f984aSJacob Faibussowitsch Notes: 211030f984aSJacob Faibussowitsch This routine is effectively PetscDeviceContext's "set-type" (so every PetscDeviceContext 212030f984aSJacob Faibussowitsch must also have an attached PetscDevice). Unlike the usual set-type semantics, it is 213030f984aSJacob Faibussowitsch not stricly necessary to set a contexts device to enable usage, any created device 214030f984aSJacob Faibussowitsch contexts will always come equipped with the "default" device. 215030f984aSJacob Faibussowitsch 216a4af0ceeSJacob Faibussowitsch This routine is a no-op if dctx is already attached to device. 217a4af0ceeSJacob Faibussowitsch 2185181c4f9SJacob Faibussowitsch This routine may initialize the backend device and incur synchronization. 2195181c4f9SJacob Faibussowitsch 220030f984aSJacob Faibussowitsch Level: intermediate 221030f984aSJacob Faibussowitsch 2225181c4f9SJacob Faibussowitsch .seealso: PetscDeviceCreate(), PetscDeviceConfigure(), PetscDeviceContextGetDevice() 223030f984aSJacob Faibussowitsch @*/ 224030f984aSJacob Faibussowitsch PetscErrorCode PetscDeviceContextSetDevice(PetscDeviceContext dctx, PetscDevice device) 225030f984aSJacob Faibussowitsch { 226030f984aSJacob Faibussowitsch PetscErrorCode ierr; 227030f984aSJacob Faibussowitsch 228030f984aSJacob Faibussowitsch PetscFunctionBegin; 229030f984aSJacob Faibussowitsch PetscValidDeviceContext(dctx,1); 230030f984aSJacob Faibussowitsch PetscValidDevice(device,2); 231a4af0ceeSJacob Faibussowitsch if (dctx->device) { 232a4af0ceeSJacob Faibussowitsch /* can't do a strict pointer equality check since PetscDevice's are reused */ 233a4af0ceeSJacob Faibussowitsch if (dctx->device->ops->createcontext == device->ops->createcontext) PetscFunctionReturn(0); 234a4af0ceeSJacob Faibussowitsch } 235030f984aSJacob Faibussowitsch ierr = PetscDeviceDestroy(&dctx->device);CHKERRQ(ierr); 236a4af0ceeSJacob Faibussowitsch if (dctx->ops->destroy) {ierr = (*dctx->ops->destroy)(dctx);CHKERRQ(ierr);} 237030f984aSJacob Faibussowitsch ierr = PetscMemzero(dctx->ops,sizeof(*dctx->ops));CHKERRQ(ierr); 238030f984aSJacob Faibussowitsch ierr = (*device->ops->createcontext)(dctx);CHKERRQ(ierr); 239a4af0ceeSJacob Faibussowitsch ierr = PetscDeviceReference_Internal(device);CHKERRQ(ierr); 240a4af0ceeSJacob Faibussowitsch dctx->device = device; 241030f984aSJacob Faibussowitsch dctx->setup = PETSC_FALSE; 242030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 243030f984aSJacob Faibussowitsch } 244030f984aSJacob Faibussowitsch 245030f984aSJacob Faibussowitsch /*@C 246030f984aSJacob Faibussowitsch PetscDeviceContextGetDevice - Get the underlying PetscDevice for a PetscDeviceContext 247030f984aSJacob Faibussowitsch 248030f984aSJacob Faibussowitsch Not Collective, Asynchronous 249030f984aSJacob Faibussowitsch 250030f984aSJacob Faibussowitsch Input Parameter: 251030f984aSJacob Faibussowitsch . dctx - the PetscDeviceContext 252030f984aSJacob Faibussowitsch 253030f984aSJacob Faibussowitsch Output Parameter: 254030f984aSJacob Faibussowitsch . device - The PetscDevice 255030f984aSJacob Faibussowitsch 256030f984aSJacob Faibussowitsch Notes: 257030f984aSJacob Faibussowitsch This is a borrowed reference, the user should not destroy the device. 258030f984aSJacob Faibussowitsch 259a375dbeeSPatrick Sanan Level: intermediate 260a375dbeeSPatrick Sanan 261030f984aSJacob Faibussowitsch .seealso: PetscDeviceContextSetDevice(), PetscDevice 262030f984aSJacob Faibussowitsch @*/ 263030f984aSJacob Faibussowitsch PetscErrorCode PetscDeviceContextGetDevice(PetscDeviceContext dctx, PetscDevice *device) 264030f984aSJacob Faibussowitsch { 265030f984aSJacob Faibussowitsch PetscFunctionBegin; 266030f984aSJacob Faibussowitsch PetscValidDeviceContext(dctx,1); 267030f984aSJacob Faibussowitsch PetscValidPointer(device,2); 2683ca90d2dSJacob Faibussowitsch if (PetscUnlikelyDebug(!dctx->device)) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"PetscDeviceContext %" PetscInt_FMT " has no attached PetscDevice to get",dctx->id); 269030f984aSJacob Faibussowitsch *device = dctx->device; 270030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 271030f984aSJacob Faibussowitsch } 272030f984aSJacob Faibussowitsch 273030f984aSJacob Faibussowitsch /*@C 274030f984aSJacob Faibussowitsch PetscDeviceContextSetUp - Prepares a PetscDeviceContext for use 275030f984aSJacob Faibussowitsch 276030f984aSJacob Faibussowitsch Not Collective, Asynchronous 277030f984aSJacob Faibussowitsch 27801d2d390SJose E. Roman Input Parameter: 279030f984aSJacob Faibussowitsch . dctx - The PetscDeviceContext 280030f984aSJacob Faibussowitsch 281030f984aSJacob Faibussowitsch Developer Notes: 282030f984aSJacob Faibussowitsch This routine is usually the stage where a PetscDeviceContext acquires device-side data structures such as streams, 283030f984aSJacob Faibussowitsch events, and (possibly) handles. 284030f984aSJacob Faibussowitsch 285030f984aSJacob Faibussowitsch Level: beginner 286030f984aSJacob Faibussowitsch 2875181c4f9SJacob Faibussowitsch .seealso: PetscDeviceContextCreate(), PetscDeviceContextSetDevice(), PetscDeviceContextDestroy(), PetscDeviceContextSetFromOptions() 288030f984aSJacob Faibussowitsch @*/ 289030f984aSJacob Faibussowitsch PetscErrorCode PetscDeviceContextSetUp(PetscDeviceContext dctx) 290030f984aSJacob Faibussowitsch { 291030f984aSJacob Faibussowitsch PetscErrorCode ierr; 292030f984aSJacob Faibussowitsch 293030f984aSJacob Faibussowitsch PetscFunctionBegin; 294030f984aSJacob Faibussowitsch PetscValidDeviceContext(dctx,1); 295030f984aSJacob Faibussowitsch if (!dctx->device) { 2963ca90d2dSJacob Faibussowitsch ierr = PetscInfo2(PETSC_NULLPTR,"PetscDeviceContext %" PetscInt_FMT " did not have an explicitly attached PetscDevice, using default with type %s\n",dctx->id,PetscDeviceTypes[PETSC_DEVICE_DEFAULT]);CHKERRQ(ierr); 297a4af0ceeSJacob Faibussowitsch ierr = PetscDeviceContextSetDefaultDevice_Internal(dctx);CHKERRQ(ierr); 298030f984aSJacob Faibussowitsch } 299030f984aSJacob Faibussowitsch if (dctx->setup) PetscFunctionReturn(0); 300030f984aSJacob Faibussowitsch ierr = (*dctx->ops->setup)(dctx);CHKERRQ(ierr); 301030f984aSJacob Faibussowitsch dctx->setup = PETSC_TRUE; 302030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 303030f984aSJacob Faibussowitsch } 304030f984aSJacob Faibussowitsch 305030f984aSJacob Faibussowitsch /*@C 306030f984aSJacob Faibussowitsch PetscDeviceContextDuplicate - Duplicates a PetscDeviceContext object 307030f984aSJacob Faibussowitsch 308030f984aSJacob Faibussowitsch Not Collective, Asynchronous 309030f984aSJacob Faibussowitsch 310030f984aSJacob Faibussowitsch Input Parameter: 311030f984aSJacob Faibussowitsch . dctx - The PetscDeviceContext to duplicate 312030f984aSJacob Faibussowitsch 313030f984aSJacob Faibussowitsch Output Paramter: 314050c0c3dSJacob Faibussowitsch . dctxdup - The duplicated PetscDeviceContext 315030f984aSJacob Faibussowitsch 316030f984aSJacob Faibussowitsch Notes: 317030f984aSJacob Faibussowitsch This is a shorthand method for creating a PetscDeviceContext with the exact same 318030f984aSJacob Faibussowitsch settings as another. Note however that the duplicated PetscDeviceContext does not "share" 319030f984aSJacob Faibussowitsch any of the underlying data with the original, (including its current stream-state) they 320030f984aSJacob Faibussowitsch are completely separate objects. 321030f984aSJacob Faibussowitsch 322030f984aSJacob Faibussowitsch Level: beginner 323030f984aSJacob Faibussowitsch 324030f984aSJacob Faibussowitsch .seealso: PetscDeviceContextCreate(), PetscDeviceContextSetDevice(), PetscDeviceContextSetStreamType() 325030f984aSJacob Faibussowitsch @*/ 326030f984aSJacob Faibussowitsch PetscErrorCode PetscDeviceContextDuplicate(PetscDeviceContext dctx, PetscDeviceContext *dctxdup) 327030f984aSJacob Faibussowitsch { 328a4af0ceeSJacob Faibussowitsch PetscDeviceContext dup; 329030f984aSJacob Faibussowitsch PetscErrorCode ierr; 330030f984aSJacob Faibussowitsch 331030f984aSJacob Faibussowitsch PetscFunctionBegin; 332030f984aSJacob Faibussowitsch PetscValidDeviceContext(dctx,1); 333030f984aSJacob Faibussowitsch PetscValidPointer(dctxdup,2); 334a4af0ceeSJacob Faibussowitsch ierr = PetscDeviceContextCreate(&dup);CHKERRQ(ierr); 335a4af0ceeSJacob Faibussowitsch ierr = PetscDeviceContextSetStreamType(dup,dctx->streamType);CHKERRQ(ierr); 336a4af0ceeSJacob Faibussowitsch if (dctx->device) {ierr = PetscDeviceContextSetDevice(dup,dctx->device);CHKERRQ(ierr);} 337a4af0ceeSJacob Faibussowitsch ierr = PetscDeviceContextSetUp(dup);CHKERRQ(ierr); 338a4af0ceeSJacob Faibussowitsch *dctxdup = dup; 339030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 340030f984aSJacob Faibussowitsch } 341030f984aSJacob Faibussowitsch 342030f984aSJacob Faibussowitsch /*@C 343030f984aSJacob Faibussowitsch PetscDeviceContextQueryIdle - Returns whether or not a PetscDeviceContext is idle 344030f984aSJacob Faibussowitsch 345030f984aSJacob Faibussowitsch Not Collective, Asynchronous 346030f984aSJacob Faibussowitsch 347030f984aSJacob Faibussowitsch Input Parameter: 348030f984aSJacob Faibussowitsch . dctx - The PetscDeviceContext object 349030f984aSJacob Faibussowitsch 350030f984aSJacob Faibussowitsch Output Parameter: 351030f984aSJacob Faibussowitsch . idle - PETSC_TRUE if PetscDeviceContext has NO work, PETSC_FALSE if it has work 352030f984aSJacob Faibussowitsch 353030f984aSJacob Faibussowitsch Notes: 354030f984aSJacob Faibussowitsch This routine only refers a singular context and does NOT take any of its children into account. That is, if dctx is 355030f984aSJacob Faibussowitsch idle but has dependents who do have work, this routine still returns PETSC_TRUE. 356030f984aSJacob Faibussowitsch 357030f984aSJacob Faibussowitsch Results of PetscDeviceContextQueryIdle() are cached on return, allowing this function to be called repeatedly in an 358030f984aSJacob Faibussowitsch efficient manner. When debug mode is enabled this cache is verified on every call to 359030f984aSJacob Faibussowitsch this routine, but is blindly believed when debugging is disabled. 360030f984aSJacob Faibussowitsch 361030f984aSJacob Faibussowitsch Level: intermediate 362030f984aSJacob Faibussowitsch 363030f984aSJacob Faibussowitsch .seealso: PetscDeviceContextCreate(), PetscDeviceContextWaitForContext(), PetscDeviceContextFork() 364030f984aSJacob Faibussowitsch @*/ 365030f984aSJacob Faibussowitsch PetscErrorCode PetscDeviceContextQueryIdle(PetscDeviceContext dctx, PetscBool *idle) 366030f984aSJacob Faibussowitsch { 367030f984aSJacob Faibussowitsch PetscErrorCode ierr; 368030f984aSJacob Faibussowitsch 369030f984aSJacob Faibussowitsch PetscFunctionBegin; 370030f984aSJacob Faibussowitsch PetscValidDeviceContext(dctx,1); 371030f984aSJacob Faibussowitsch PetscValidBoolPointer(idle,2); 372030f984aSJacob Faibussowitsch if (dctx->idle) { 373030f984aSJacob Faibussowitsch *idle = PETSC_TRUE; 374030f984aSJacob Faibussowitsch ierr = PetscDeviceContextValidateIdle_Internal(dctx);CHKERRQ(ierr); 375030f984aSJacob Faibussowitsch } else { 376030f984aSJacob Faibussowitsch ierr = (*dctx->ops->query)(dctx,idle);CHKERRQ(ierr); 377030f984aSJacob Faibussowitsch dctx->idle = *idle; 378030f984aSJacob Faibussowitsch } 379030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 380030f984aSJacob Faibussowitsch } 381030f984aSJacob Faibussowitsch 382030f984aSJacob Faibussowitsch /*@C 383030f984aSJacob Faibussowitsch PetscDeviceContextWaitForContext - Make one context wait for another context to finish 384030f984aSJacob Faibussowitsch 385030f984aSJacob Faibussowitsch Not Collective, Asynchronous 386030f984aSJacob Faibussowitsch 387030f984aSJacob Faibussowitsch Input Parameters: 388030f984aSJacob Faibussowitsch + dctxa - The PetscDeviceContext object that is waiting 389030f984aSJacob Faibussowitsch - dctxb - The PetscDeviceContext object that is being waited on 390030f984aSJacob Faibussowitsch 391030f984aSJacob Faibussowitsch Notes: 392030f984aSJacob Faibussowitsch Serializes two PetscDeviceContexts. This routine uses only the state of dctxb at the moment this routine was 393030f984aSJacob Faibussowitsch called, so any future work queued will not affect dctxa. It is safe to pass the same context to both arguments. 394030f984aSJacob Faibussowitsch 395030f984aSJacob Faibussowitsch Level: beginner 396030f984aSJacob Faibussowitsch 397030f984aSJacob Faibussowitsch .seealso: PetscDeviceContextCreate(), PetscDeviceContextQueryIdle(), PetscDeviceContextJoin() 398030f984aSJacob Faibussowitsch @*/ 399030f984aSJacob Faibussowitsch PetscErrorCode PetscDeviceContextWaitForContext(PetscDeviceContext dctxa, PetscDeviceContext dctxb) 400030f984aSJacob Faibussowitsch { 401030f984aSJacob Faibussowitsch PetscErrorCode ierr; 402030f984aSJacob Faibussowitsch 403030f984aSJacob Faibussowitsch PetscFunctionBegin; 404030f984aSJacob Faibussowitsch PetscCheckCompatibleDeviceContexts(dctxa,1,dctxb,2); 405030f984aSJacob Faibussowitsch if (dctxa == dctxb) PetscFunctionReturn(0); 406030f984aSJacob Faibussowitsch if (dctxb->idle) { 407030f984aSJacob Faibussowitsch /* No need to do the extra function lookup and event record if the stream were waiting on isn't doing anything */ 408030f984aSJacob Faibussowitsch ierr = PetscDeviceContextValidateIdle_Internal(dctxb);CHKERRQ(ierr); 409030f984aSJacob Faibussowitsch } else { 410*17f48955SJacob Faibussowitsch ierr = (*dctxa->ops->waitforcontext)(dctxa,dctxb);CHKERRQ(ierr); 411030f984aSJacob Faibussowitsch } 412030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 413030f984aSJacob Faibussowitsch } 414030f984aSJacob Faibussowitsch 415050c0c3dSJacob Faibussowitsch #define PETSC_USE_DEBUG_AND_INFO (PetscDefined(USE_DEBUG) && PetscDefined(USE_INFO)) 416050c0c3dSJacob Faibussowitsch #if PETSC_USE_DEBUG_AND_INFO 417050c0c3dSJacob Faibussowitsch #include <string> 418050c0c3dSJacob Faibussowitsch #endif 419030f984aSJacob Faibussowitsch /*@C 420030f984aSJacob Faibussowitsch PetscDeviceContextFork - Create a set of dependent child contexts from a parent context 421030f984aSJacob Faibussowitsch 422030f984aSJacob Faibussowitsch Not Collective, Asynchronous 423030f984aSJacob Faibussowitsch 424030f984aSJacob Faibussowitsch Input Parameters: 425030f984aSJacob Faibussowitsch + dctx - The parent PetscDeviceContext 426030f984aSJacob Faibussowitsch - n - The number of children to create 427030f984aSJacob Faibussowitsch 428030f984aSJacob Faibussowitsch Output Parameter: 429030f984aSJacob Faibussowitsch . dsub - The created child context(s) 430030f984aSJacob Faibussowitsch 431030f984aSJacob Faibussowitsch Notes: 432030f984aSJacob Faibussowitsch This routine creates n edges of a DAG from a source node which are causally dependent on the source node, meaning 433030f984aSJacob Faibussowitsch that work queued on child contexts will not start until the parent context finishes its work. This accounts for work 434030f984aSJacob Faibussowitsch queued on the parent up until calling this function, any subsequent work enqueued on the parent has no effect on the children. 435030f984aSJacob Faibussowitsch 436030f984aSJacob Faibussowitsch Any children created with this routine have their lifetimes bounded by the parent. That is, the parent context expects 437030f984aSJacob Faibussowitsch to free all of it's children (and ONLY its children) before itself is freed. 438030f984aSJacob Faibussowitsch 439030f984aSJacob Faibussowitsch DAG representation: 440030f984aSJacob Faibussowitsch .vb 441030f984aSJacob Faibussowitsch time -> 442030f984aSJacob Faibussowitsch 443030f984aSJacob Faibussowitsch -> dctx \----> dctx ------> 444030f984aSJacob Faibussowitsch \---> dsub[0] ---> 445030f984aSJacob Faibussowitsch \--> ... -------> 446030f984aSJacob Faibussowitsch \-> dsub[n-1] -> 447030f984aSJacob Faibussowitsch .ve 448030f984aSJacob Faibussowitsch 449030f984aSJacob Faibussowitsch Level: intermediate 450030f984aSJacob Faibussowitsch 451030f984aSJacob Faibussowitsch .seealso: PetscDeviceContextJoin(), PetscDeviceContextSynchronize(), PetscDeviceContextQueryIdle() 452030f984aSJacob Faibussowitsch @*/ 453030f984aSJacob Faibussowitsch PetscErrorCode PetscDeviceContextFork(PetscDeviceContext dctx, PetscInt n, PetscDeviceContext **dsub) 454030f984aSJacob Faibussowitsch { 455050c0c3dSJacob Faibussowitsch #if PETSC_USE_DEBUG_AND_INFO 456030f984aSJacob Faibussowitsch const PetscInt nBefore = n; 457030f984aSJacob Faibussowitsch static std::string idList; 458030f984aSJacob Faibussowitsch #endif 459a4af0ceeSJacob Faibussowitsch PetscDeviceContext *dsubTmp = PETSC_NULLPTR; 460030f984aSJacob Faibussowitsch PetscInt i = 0; 461030f984aSJacob Faibussowitsch PetscErrorCode ierr; 462030f984aSJacob Faibussowitsch 463030f984aSJacob Faibussowitsch PetscFunctionBegin; 464030f984aSJacob Faibussowitsch PetscValidDeviceContext(dctx,1); 465030f984aSJacob Faibussowitsch PetscValidPointer(dsub,3); 4663ca90d2dSJacob Faibussowitsch if (PetscUnlikelyDebug(n < 0)) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Number of contexts requested %" PetscInt_FMT " < 0",n); 4673ca90d2dSJacob Faibussowitsch #if PETSC_USE_DEBUG_AND_INFO 468030f984aSJacob Faibussowitsch /* reserve 4 chars per id, 2 for number and 2 for ', ' separator */ 469030f984aSJacob Faibussowitsch idList.reserve(4*n); 470030f984aSJacob Faibussowitsch #endif 471030f984aSJacob Faibussowitsch /* update child totals */ 472030f984aSJacob Faibussowitsch dctx->numChildren += n; 473030f984aSJacob Faibussowitsch /* now to find out if we have room */ 474030f984aSJacob Faibussowitsch if (dctx->numChildren > dctx->maxNumChildren) { 475030f984aSJacob Faibussowitsch /* no room, either from having too many kids or not having any */ 476030f984aSJacob Faibussowitsch if (dctx->childIDs) { 477030f984aSJacob Faibussowitsch /* have existing children, must reallocate them */ 478030f984aSJacob Faibussowitsch ierr = PetscRealloc(dctx->numChildren*sizeof(*dctx->childIDs),&dctx->childIDs);CHKERRQ(ierr); 479030f984aSJacob Faibussowitsch /* clear the extra memory since realloc doesn't do it for us */ 480030f984aSJacob Faibussowitsch ierr = PetscArrayzero((dctx->childIDs)+(dctx->maxNumChildren),(dctx->numChildren)-(dctx->maxNumChildren));CHKERRQ(ierr); 481030f984aSJacob Faibussowitsch } else { 482030f984aSJacob Faibussowitsch /* have no children */ 483030f984aSJacob Faibussowitsch ierr = PetscCalloc1(dctx->numChildren,&dctx->childIDs);CHKERRQ(ierr); 484030f984aSJacob Faibussowitsch } 485030f984aSJacob Faibussowitsch /* update total number of children */ 486030f984aSJacob Faibussowitsch dctx->maxNumChildren = dctx->numChildren; 487030f984aSJacob Faibussowitsch } 488030f984aSJacob Faibussowitsch ierr = PetscMalloc1(n,&dsubTmp);CHKERRQ(ierr); 489030f984aSJacob Faibussowitsch while (n) { 490030f984aSJacob Faibussowitsch /* empty child slot */ 491030f984aSJacob Faibussowitsch if (!(dctx->childIDs[i])) { 492030f984aSJacob Faibussowitsch /* create the child context in the image of its parent */ 493030f984aSJacob Faibussowitsch ierr = PetscDeviceContextDuplicate(dctx,dsubTmp+i);CHKERRQ(ierr); 494030f984aSJacob Faibussowitsch ierr = PetscDeviceContextWaitForContext(dsubTmp[i],dctx);CHKERRQ(ierr); 495030f984aSJacob Faibussowitsch /* register the child with its parent */ 496030f984aSJacob Faibussowitsch dctx->childIDs[i] = dsubTmp[i]->id; 497050c0c3dSJacob Faibussowitsch #if PETSC_USE_DEBUG_AND_INFO 498030f984aSJacob Faibussowitsch idList += std::to_string(dsubTmp[i]->id); 499030f984aSJacob Faibussowitsch if (n != 1) idList += ", "; 500030f984aSJacob Faibussowitsch #endif 501030f984aSJacob Faibussowitsch --n; 502030f984aSJacob Faibussowitsch } 503030f984aSJacob Faibussowitsch ++i; 504030f984aSJacob Faibussowitsch } 5053ca90d2dSJacob Faibussowitsch #if PETSC_USE_DEBUG_AND_INFO 5063ca90d2dSJacob Faibussowitsch ierr = PetscInfo3(PETSC_NULLPTR,"Forked %" PetscInt_FMT " children from parent %" PetscInt_FMT " with IDs: %s\n",nBefore,dctx->id,idList.c_str());CHKERRQ(ierr); 507030f984aSJacob Faibussowitsch /* resets the size but doesn't deallocate the memory */ 508030f984aSJacob Faibussowitsch idList.clear(); 509030f984aSJacob Faibussowitsch #endif 510030f984aSJacob Faibussowitsch /* pass the children back to caller */ 511030f984aSJacob Faibussowitsch *dsub = dsubTmp; 512030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 513030f984aSJacob Faibussowitsch } 514030f984aSJacob Faibussowitsch 515030f984aSJacob Faibussowitsch /*@C 5165181c4f9SJacob Faibussowitsch PetscDeviceContextJoin - Converge a set of child contexts 517030f984aSJacob Faibussowitsch 518030f984aSJacob Faibussowitsch Not Collective, Asynchronous 519030f984aSJacob Faibussowitsch 520030f984aSJacob Faibussowitsch Input Parameters: 521030f984aSJacob Faibussowitsch + dctx - A PetscDeviceContext to converge on 522030f984aSJacob Faibussowitsch . n - The number of sub contexts to converge 523030f984aSJacob Faibussowitsch . joinMode - The type of join to perform 524030f984aSJacob Faibussowitsch - dsub - The sub contexts to converge 525030f984aSJacob Faibussowitsch 526030f984aSJacob Faibussowitsch Notes: 527030f984aSJacob Faibussowitsch If PetscDeviceContextFork() creates n edges from a source node which all depend on the 528030f984aSJacob Faibussowitsch source node, then this routine is the exact mirror. That is, it creates a node 529030f984aSJacob Faibussowitsch (represented in dctx) which recieves n edges (and optionally destroys them) which is 530030f984aSJacob Faibussowitsch dependent on the completion of all incoming edges. 531030f984aSJacob Faibussowitsch 532030f984aSJacob Faibussowitsch If joinMode is PETSC_DEVICE_CONTEXT_JOIN_DESTROY all contexts in dsub will be destroyed 533030f984aSJacob Faibussowitsch by this routine. Thus all sub contexts must have been created with the dctx passed to 534030f984aSJacob Faibussowitsch this routine. 535030f984aSJacob Faibussowitsch 536030f984aSJacob Faibussowitsch if joinMode is PETSC_DEVICE_CONTEXT_JOIN_NO_SYNC dctx waits for all sub contexts but the 537030f984aSJacob Faibussowitsch sub contexts do not wait for one another afterwards. 538030f984aSJacob Faibussowitsch 539030f984aSJacob Faibussowitsch If joinMode is PETSC_DEVICE_CONTEXT_JOIN_SYNC all sub contexts will additionally 540030f984aSJacob Faibussowitsch wait on dctx after converging. This has the effect of "synchronizing" the outgoing 541030f984aSJacob Faibussowitsch edges. 542030f984aSJacob Faibussowitsch 543030f984aSJacob Faibussowitsch DAG representations: 544030f984aSJacob Faibussowitsch If joinMode is PETSC_DEVICE_CONTEXT_JOIN_DESTROY 545030f984aSJacob Faibussowitsch .vb 546030f984aSJacob Faibussowitsch time -> 547030f984aSJacob Faibussowitsch 548030f984aSJacob Faibussowitsch -> dctx ---------/- dctx -> 549030f984aSJacob Faibussowitsch -> dsub[0] -----/ 550030f984aSJacob Faibussowitsch -> ... -------/ 551030f984aSJacob Faibussowitsch -> dsub[n-1] -/ 552030f984aSJacob Faibussowitsch .ve 553030f984aSJacob Faibussowitsch If joinMode is PETSC_DEVICE_CONTEXT_JOIN_NO_SYNC 554030f984aSJacob Faibussowitsch .vb 555030f984aSJacob Faibussowitsch time -> 556030f984aSJacob Faibussowitsch 557030f984aSJacob Faibussowitsch -> dctx ---------/- dctx -> 558030f984aSJacob Faibussowitsch -> dsub[0] -----/---------> 559030f984aSJacob Faibussowitsch -> ... -------/----------> 560030f984aSJacob Faibussowitsch -> dsub[n-1] -/-----------> 561030f984aSJacob Faibussowitsch .ve 562030f984aSJacob Faibussowitsch If joinMode is PETSC_DEVICE_CONTEXT_JOIN_SYNC 563030f984aSJacob Faibussowitsch .vb 564030f984aSJacob Faibussowitsch time -> 565030f984aSJacob Faibussowitsch 566030f984aSJacob Faibussowitsch -> dctx ---------/- dctx -\----> dctx ------> 567030f984aSJacob Faibussowitsch -> dsub[0] -----/ \---> dsub[0] ---> 568030f984aSJacob Faibussowitsch -> ... -------/ \--> ... -------> 569030f984aSJacob Faibussowitsch -> dsub[n-1] -/ \-> dsub[n-1] -> 570030f984aSJacob Faibussowitsch .ve 571030f984aSJacob Faibussowitsch 572030f984aSJacob Faibussowitsch Level: intermediate 573030f984aSJacob Faibussowitsch 574030f984aSJacob Faibussowitsch .seealso: PetscDeviceContextFork(), PetscDeviceContextSynchronize(), PetscDeviceContextJoinMode 575030f984aSJacob Faibussowitsch @*/ 576030f984aSJacob Faibussowitsch PetscErrorCode PetscDeviceContextJoin(PetscDeviceContext dctx, PetscInt n, PetscDeviceContextJoinMode joinMode, PetscDeviceContext **dsub) 577030f984aSJacob Faibussowitsch { 578030f984aSJacob Faibussowitsch #if defined(PETSC_USE_DEBUG) && defined(PETSC_USE_INFO) 579030f984aSJacob Faibussowitsch static std::string idList; 580030f984aSJacob Faibussowitsch #endif 581030f984aSJacob Faibussowitsch PetscErrorCode ierr; 582030f984aSJacob Faibussowitsch 583030f984aSJacob Faibussowitsch PetscFunctionBegin; 584030f984aSJacob Faibussowitsch /* validity of dctx is checked in the wait-for loop */ 585030f984aSJacob Faibussowitsch PetscValidPointer(dsub,4); 5863ca90d2dSJacob Faibussowitsch if (PetscUnlikelyDebug(n < 0)) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Number of contexts merged %" PetscInt_FMT " < 0",n); 587030f984aSJacob Faibussowitsch #if defined(PETSC_USE_DEBUG) && defined(PETSC_USE_INFO) 588030f984aSJacob Faibussowitsch /* reserve 4 chars per id, 2 for number and 2 for ', ' separator */ 589030f984aSJacob Faibussowitsch idList.reserve(4*n); 590030f984aSJacob Faibussowitsch #endif 591030f984aSJacob Faibussowitsch /* first dctx waits on all the incoming edges */ 592030f984aSJacob Faibussowitsch for (PetscInt i = 0; i < n; ++i) { 593030f984aSJacob Faibussowitsch PetscCheckCompatibleDeviceContexts(dctx,1,(*dsub)[i],4); 594030f984aSJacob Faibussowitsch ierr = PetscDeviceContextWaitForContext(dctx,(*dsub)[i]);CHKERRQ(ierr); 595030f984aSJacob Faibussowitsch #if defined(PETSC_USE_DEBUG) && defined(PETSC_USE_INFO) 596030f984aSJacob Faibussowitsch idList += std::to_string((*dsub)[i]->id); 597030f984aSJacob Faibussowitsch if (i+1 < n) idList += ", "; 598030f984aSJacob Faibussowitsch #endif 599030f984aSJacob Faibussowitsch } 600030f984aSJacob Faibussowitsch 601030f984aSJacob Faibussowitsch /* now we handle the aftermath */ 602030f984aSJacob Faibussowitsch switch (joinMode) { 603030f984aSJacob Faibussowitsch case PETSC_DEVICE_CONTEXT_JOIN_DESTROY: 604030f984aSJacob Faibussowitsch { 605030f984aSJacob Faibussowitsch PetscInt j = 0; 606030f984aSJacob Faibussowitsch 6073ca90d2dSJacob Faibussowitsch if (PetscUnlikelyDebug(n > dctx->numChildren)) SETERRQ2(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); 608030f984aSJacob Faibussowitsch /* update child count while it's still fresh in memory */ 609030f984aSJacob Faibussowitsch dctx->numChildren -= n; 610030f984aSJacob Faibussowitsch for (PetscInt i = 0; i < dctx->maxNumChildren; ++i) { 611030f984aSJacob Faibussowitsch if (dctx->childIDs[i] && (dctx->childIDs[i] == (*dsub)[j]->id)) { 612030f984aSJacob Faibussowitsch /* child is one of ours, can destroy it */ 613030f984aSJacob Faibussowitsch ierr = PetscDeviceContextDestroy((*dsub)+j);CHKERRQ(ierr); 614030f984aSJacob Faibussowitsch /* reset the child slot */ 615030f984aSJacob Faibussowitsch dctx->childIDs[i] = 0; 616030f984aSJacob Faibussowitsch if (++j == n) break; 617030f984aSJacob Faibussowitsch } 618030f984aSJacob Faibussowitsch } 619030f984aSJacob 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 */ 6203ca90d2dSJacob Faibussowitsch if (PetscUnlikelyDebug(j != n)) SETERRQ1(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); 621030f984aSJacob Faibussowitsch ierr = PetscFree(*dsub);CHKERRQ(ierr); 622030f984aSJacob Faibussowitsch } 623030f984aSJacob Faibussowitsch break; 624030f984aSJacob Faibussowitsch case PETSC_DEVICE_CONTEXT_JOIN_SYNC: 625030f984aSJacob Faibussowitsch for (PetscInt i = 0; i < n; ++i) { 626030f984aSJacob Faibussowitsch ierr = PetscDeviceContextWaitForContext((*dsub)[i],dctx);CHKERRQ(ierr); 627030f984aSJacob Faibussowitsch } 628030f984aSJacob Faibussowitsch case PETSC_DEVICE_CONTEXT_JOIN_NO_SYNC: 629030f984aSJacob Faibussowitsch break; 630030f984aSJacob Faibussowitsch default: 631030f984aSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Unknown PetscDeviceContextJoinMode given"); 632030f984aSJacob Faibussowitsch } 633030f984aSJacob Faibussowitsch 634030f984aSJacob Faibussowitsch #if defined(PETSC_USE_DEBUG) && defined(PETSC_USE_INFO) 6353ca90d2dSJacob Faibussowitsch ierr = PetscInfo4(PETSC_NULLPTR,"Joined %" PetscInt_FMT " ctxs to ctx %" PetscInt_FMT ", mode %s with IDs: %s\n",n,dctx->id,PetscDeviceContextJoinModes[joinMode],idList.c_str());CHKERRQ(ierr); 636030f984aSJacob Faibussowitsch idList.clear(); 637030f984aSJacob Faibussowitsch #endif 638030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 639030f984aSJacob Faibussowitsch } 640030f984aSJacob Faibussowitsch 641030f984aSJacob Faibussowitsch /*@C 6425181c4f9SJacob Faibussowitsch PetscDeviceContextSynchronize - Block the host until all work queued on or associated with a PetscDeviceContext has finished 643030f984aSJacob Faibussowitsch 644030f984aSJacob Faibussowitsch Not Collective, Synchronous 645030f984aSJacob Faibussowitsch 646030f984aSJacob Faibussowitsch Input Parameters: 647030f984aSJacob Faibussowitsch . dctx - The PetscDeviceContext to synchronize 648030f984aSJacob Faibussowitsch 649030f984aSJacob Faibussowitsch Level: beginner 650030f984aSJacob Faibussowitsch 651030f984aSJacob Faibussowitsch .seealso: PetscDeviceContextFork(), PetscDeviceContextJoin(), PetscDeviceContextQueryIdle() 652030f984aSJacob Faibussowitsch @*/ 653030f984aSJacob Faibussowitsch PetscErrorCode PetscDeviceContextSynchronize(PetscDeviceContext dctx) 654030f984aSJacob Faibussowitsch { 655030f984aSJacob Faibussowitsch PetscErrorCode ierr; 656030f984aSJacob Faibussowitsch 657030f984aSJacob Faibussowitsch PetscFunctionBegin; 658030f984aSJacob Faibussowitsch PetscValidDeviceContext(dctx,1); 659030f984aSJacob Faibussowitsch /* if it isn't setup there is nothing to sync on */ 660030f984aSJacob Faibussowitsch if (dctx->setup) {ierr = (*dctx->ops->synchronize)(dctx);CHKERRQ(ierr);} 661030f984aSJacob Faibussowitsch dctx->idle = PETSC_TRUE; 662030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 663030f984aSJacob Faibussowitsch } 664030f984aSJacob Faibussowitsch 665a4af0ceeSJacob Faibussowitsch #define PETSC_DEVICE_CONTEXT_DEFAULT_DEVICE PETSC_DEVICE_DEFAULT 666a4af0ceeSJacob Faibussowitsch // REMOVE ME (change) 667a4af0ceeSJacob Faibussowitsch #define PETSC_DEVICE_CONTEXT_DEFAULT_STREAM PETSC_STREAM_GLOBAL_BLOCKING 668030f984aSJacob Faibussowitsch 669a4af0ceeSJacob Faibussowitsch static PetscDeviceType rootDeviceType = PETSC_DEVICE_CONTEXT_DEFAULT_DEVICE; 670a4af0ceeSJacob Faibussowitsch static PetscStreamType rootStreamType = PETSC_DEVICE_CONTEXT_DEFAULT_STREAM; 671a4af0ceeSJacob Faibussowitsch static PetscDeviceContext globalContext = PETSC_NULLPTR; 672a4af0ceeSJacob Faibussowitsch 673a4af0ceeSJacob Faibussowitsch /* when PetsDevice initializes PetscDeviceContext eagerly the type of device created should 674a4af0ceeSJacob Faibussowitsch * match whatever device is eagerly intialized */ 675a4af0ceeSJacob Faibussowitsch PetscErrorCode PetscDeviceContextSetRootDeviceType_Internal(PetscDeviceType type) 676030f984aSJacob Faibussowitsch { 677030f984aSJacob Faibussowitsch PetscFunctionBegin; 678a4af0ceeSJacob Faibussowitsch PetscValidDeviceType(type,1); 679a4af0ceeSJacob Faibussowitsch rootDeviceType = type; 680030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 681030f984aSJacob Faibussowitsch } 682030f984aSJacob Faibussowitsch 683a4af0ceeSJacob Faibussowitsch #if 0 684a4af0ceeSJacob Faibussowitsch /* currently unused */ 685a4af0ceeSJacob Faibussowitsch PetscErrorCode PetscDeviceContextSetRootStreamType_Internal(PetscStreamType type) 686030f984aSJacob Faibussowitsch { 687a4af0ceeSJacob Faibussowitsch PetscFunctionBegin; 688a4af0ceeSJacob Faibussowitsch PetscValidStreamType(type,1); 689a4af0ceeSJacob Faibussowitsch rootStreamType = type; 690a4af0ceeSJacob Faibussowitsch PetscFunctionReturn(0); 691a4af0ceeSJacob Faibussowitsch } 692a4af0ceeSJacob Faibussowitsch #endif 693a4af0ceeSJacob Faibussowitsch 694a4af0ceeSJacob Faibussowitsch static PetscErrorCode PetscDeviceContextSetupGlobalContext_Private(void) 695a4af0ceeSJacob Faibussowitsch { 696a4af0ceeSJacob Faibussowitsch PetscErrorCode ierr; 697a4af0ceeSJacob Faibussowitsch static const auto PetscDeviceContextFinalizer = []() -> PetscErrorCode { 698030f984aSJacob Faibussowitsch PetscErrorCode ierr; 699030f984aSJacob Faibussowitsch 700030f984aSJacob Faibussowitsch PetscFunctionBegin; 701a4af0ceeSJacob Faibussowitsch ierr = PetscDeviceContextDestroy(&globalContext);CHKERRQ(ierr); 702a4af0ceeSJacob Faibussowitsch rootDeviceType = PETSC_DEVICE_CONTEXT_DEFAULT_DEVICE; 703a4af0ceeSJacob Faibussowitsch rootStreamType = PETSC_DEVICE_CONTEXT_DEFAULT_STREAM; 704a4af0ceeSJacob Faibussowitsch PetscFunctionReturn(0); 705a4af0ceeSJacob Faibussowitsch }; 706a4af0ceeSJacob Faibussowitsch 707a4af0ceeSJacob Faibussowitsch PetscFunctionBegin; 708a4af0ceeSJacob Faibussowitsch if (globalContext) PetscFunctionReturn(0); 709a4af0ceeSJacob Faibussowitsch /* this exists purely as a valid device check. */ 710a4af0ceeSJacob Faibussowitsch ierr = PetscDeviceInitializePackage();CHKERRQ(ierr); 711a4af0ceeSJacob Faibussowitsch ierr = PetscRegisterFinalize(PetscDeviceContextFinalizer);CHKERRQ(ierr); 712a4af0ceeSJacob Faibussowitsch ierr = PetscInfo(PETSC_NULLPTR,"Initializing global PetscDeviceContext\n");CHKERRQ(ierr); 713a4af0ceeSJacob Faibussowitsch /* we call the allocator directly here since the ObjectPool creates a PetscContainer which 714a4af0ceeSJacob Faibussowitsch * eventually tries to call logging functions. However, this routine may be purposefully 715a4af0ceeSJacob Faibussowitsch * called __before__ logging is initialized, so the logging function would PETSCABORT */ 716*17f48955SJacob Faibussowitsch ierr = contextPool.allocator().create(&globalContext);CHKERRQ(ierr); 717a4af0ceeSJacob Faibussowitsch ierr = PetscDeviceContextSetStreamType(globalContext,rootStreamType);CHKERRQ(ierr); 718a4af0ceeSJacob Faibussowitsch ierr = PetscDeviceContextSetDefaultDeviceForType_Internal(globalContext,rootDeviceType);CHKERRQ(ierr); 719a4af0ceeSJacob Faibussowitsch ierr = PetscDeviceContextSetUp(globalContext);CHKERRQ(ierr); 720030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 721030f984aSJacob Faibussowitsch } 722030f984aSJacob Faibussowitsch 723030f984aSJacob Faibussowitsch /*@C 7245181c4f9SJacob Faibussowitsch PetscDeviceContextGetCurrentContext - Get the current active PetscDeviceContext 725030f984aSJacob Faibussowitsch 726030f984aSJacob Faibussowitsch Not Collective, Asynchronous 727030f984aSJacob Faibussowitsch 728030f984aSJacob Faibussowitsch Output Parameter: 729030f984aSJacob Faibussowitsch . dctx - The PetscDeviceContext 730030f984aSJacob Faibussowitsch 731030f984aSJacob Faibussowitsch Notes: 732a4af0ceeSJacob Faibussowitsch The user generally should not destroy contexts retrieved with this routine unless they 733a4af0ceeSJacob Faibussowitsch themselves have created them. There exists no protection against destroying the root 734a4af0ceeSJacob Faibussowitsch context. 735030f984aSJacob Faibussowitsch 736030f984aSJacob Faibussowitsch Developer Notes: 737a4af0ceeSJacob Faibussowitsch Unless the user has set their own, this routine creates the "root" context the first time it 738a4af0ceeSJacob Faibussowitsch is called, registering its destructor to PetscFinalize(). 739030f984aSJacob Faibussowitsch 740030f984aSJacob Faibussowitsch Level: beginner 741030f984aSJacob Faibussowitsch 742030f984aSJacob Faibussowitsch .seealso: PetscDeviceContextSetCurrentContext(), PetscDeviceContextFork(), 743030f984aSJacob Faibussowitsch PetscDeviceContextJoin(), PetscDeviceContextCreate() 744030f984aSJacob Faibussowitsch @*/ 745030f984aSJacob Faibussowitsch PetscErrorCode PetscDeviceContextGetCurrentContext(PetscDeviceContext *dctx) 746030f984aSJacob Faibussowitsch { 747030f984aSJacob Faibussowitsch PetscErrorCode ierr; 748030f984aSJacob Faibussowitsch 749a4af0ceeSJacob Faibussowitsch PetscFunctionBegin; 750a4af0ceeSJacob Faibussowitsch PetscValidPointer(dctx,1); 751a4af0ceeSJacob Faibussowitsch ierr = PetscDeviceContextSetupGlobalContext_Private();CHKERRQ(ierr); 752a4af0ceeSJacob Faibussowitsch /* while the static analyzer can find global variables, it will throw a warning about not 753a4af0ceeSJacob Faibussowitsch * being able to connect this back to the function arguments */ 754a4af0ceeSJacob Faibussowitsch PetscDisableStaticAnalyzerForExpressionUnderstandingThatThisIsDangerousAndBugprone(PetscValidDeviceContext(globalContext,-1)); 755030f984aSJacob Faibussowitsch *dctx = globalContext; 756030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 757030f984aSJacob Faibussowitsch } 758030f984aSJacob Faibussowitsch 759030f984aSJacob Faibussowitsch /*@C 7605181c4f9SJacob Faibussowitsch PetscDeviceContextSetCurrentContext - Set the current active PetscDeviceContext 761030f984aSJacob Faibussowitsch 762030f984aSJacob Faibussowitsch Not Collective, Asynchronous 763030f984aSJacob Faibussowitsch 764030f984aSJacob Faibussowitsch Input Parameter: 765030f984aSJacob Faibussowitsch . dctx - The PetscDeviceContext 766030f984aSJacob Faibussowitsch 767030f984aSJacob Faibussowitsch Notes: 768a4af0ceeSJacob Faibussowitsch This routine can be used to set the defacto "root" PetscDeviceContext to a user-defined 769a4af0ceeSJacob Faibussowitsch implementation by calling this routine immediately after PetscInitialize() and ensuring that 770a4af0ceeSJacob Faibussowitsch PetscDevice is not greedily intialized. In this case the user is responsible for destroying 771a4af0ceeSJacob Faibussowitsch their PetscDeviceContext before PetscFinalize() returns. 772a4af0ceeSJacob Faibussowitsch 773a4af0ceeSJacob Faibussowitsch The old context is not stored in any way by this routine; if one is overriding a context that 774a4af0ceeSJacob Faibussowitsch they themselves do not control, one should take care to temporarily store it by calling 775a4af0ceeSJacob Faibussowitsch PetscDeviceContextGetCurrentContext() before calling this routine. 776030f984aSJacob Faibussowitsch 777030f984aSJacob Faibussowitsch Level: beginner 778030f984aSJacob Faibussowitsch 779030f984aSJacob Faibussowitsch .seealso: PetscDeviceContextGetCurrentContext(), PetscDeviceContextFork(), 780030f984aSJacob Faibussowitsch PetscDeviceContextJoin(), PetscDeviceContextCreate() 781030f984aSJacob Faibussowitsch @*/ 782030f984aSJacob Faibussowitsch PetscErrorCode PetscDeviceContextSetCurrentContext(PetscDeviceContext dctx) 783030f984aSJacob Faibussowitsch { 784030f984aSJacob Faibussowitsch PetscErrorCode ierr; 785030f984aSJacob Faibussowitsch 786030f984aSJacob Faibussowitsch PetscFunctionBegin; 787030f984aSJacob Faibussowitsch PetscValidDeviceContext(dctx,1); 7883ca90d2dSJacob Faibussowitsch if (PetscUnlikelyDebug(!dctx->setup)) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"PetscDeviceContext %" PetscInt_FMT " must be set up before being set as global context",dctx->id); 789030f984aSJacob Faibussowitsch globalContext = dctx; 7903ca90d2dSJacob Faibussowitsch ierr = PetscInfo1(PETSC_NULLPTR,"Set global PetscDeviceContext id %" PetscInt_FMT "\n",dctx->id);CHKERRQ(ierr); 791030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 792030f984aSJacob Faibussowitsch } 793030f984aSJacob Faibussowitsch 794030f984aSJacob Faibussowitsch /*@C 795030f984aSJacob Faibussowitsch PetscDeviceContextSetFromOptions - Configure a PetscDeviceContext from the options database 796030f984aSJacob Faibussowitsch 797030f984aSJacob Faibussowitsch Collective on comm, Asynchronous 798030f984aSJacob Faibussowitsch 799030f984aSJacob Faibussowitsch Input Parameters: 800030f984aSJacob Faibussowitsch + comm - MPI communicator on which to query the options database 801030f984aSJacob Faibussowitsch . prefix - prefix to prepend to all options database queries, NULL if not needed 802030f984aSJacob Faibussowitsch - dctx - The PetscDeviceContext to configure 803030f984aSJacob Faibussowitsch 804030f984aSJacob Faibussowitsch Output Parameter: 805030f984aSJacob Faibussowitsch . dctx - The PetscDeviceContext 806030f984aSJacob Faibussowitsch 807030f984aSJacob Faibussowitsch Options Database: 808a4af0ceeSJacob Faibussowitsch + -device_context_stream_type - type of stream to create inside the PetscDeviceContext - 809030f984aSJacob Faibussowitsch PetscDeviceContextSetStreamType() 810a4af0ceeSJacob Faibussowitsch - -device_context_device_type - the type of PetscDevice to attach by default - PetscDeviceType 811030f984aSJacob Faibussowitsch 812030f984aSJacob Faibussowitsch Level: beginner 813030f984aSJacob Faibussowitsch 8145181c4f9SJacob Faibussowitsch .seealso: PetscDeviceContextSetStreamType(), PetscDeviceContextSetDevice() 815030f984aSJacob Faibussowitsch @*/ 816030f984aSJacob Faibussowitsch PetscErrorCode PetscDeviceContextSetFromOptions(MPI_Comm comm, const char prefix[], PetscDeviceContext dctx) 817030f984aSJacob Faibussowitsch { 818030f984aSJacob Faibussowitsch PetscBool flag; 819a4af0ceeSJacob Faibussowitsch PetscInt stype,dtype; 820030f984aSJacob Faibussowitsch PetscErrorCode ierr; 821030f984aSJacob Faibussowitsch 822030f984aSJacob Faibussowitsch PetscFunctionBegin; 823a4af0ceeSJacob Faibussowitsch if (prefix) PetscValidCharPointer(prefix,2); 824030f984aSJacob Faibussowitsch PetscValidDeviceContext(dctx,3); 825030f984aSJacob Faibussowitsch ierr = PetscOptionsBegin(comm,prefix,"PetscDeviceContext Options","Sys");CHKERRQ(ierr); 826a4af0ceeSJacob Faibussowitsch ierr = PetscOptionsEList("-device_context_stream_type","PetscDeviceContext PetscStreamType","PetscDeviceContextSetStreamType",PetscStreamTypes,PETSC_STREAM_MAX,PetscStreamTypes[dctx->streamType],&stype,&flag);CHKERRQ(ierr); 827030f984aSJacob Faibussowitsch if (flag) { 828030f984aSJacob Faibussowitsch ierr = PetscDeviceContextSetStreamType(dctx,static_cast<PetscStreamType>(stype));CHKERRQ(ierr); 829030f984aSJacob Faibussowitsch } 830a4af0ceeSJacob Faibussowitsch ierr = 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);CHKERRQ(ierr); 831a4af0ceeSJacob Faibussowitsch if (flag) { 832a4af0ceeSJacob Faibussowitsch ierr = PetscDeviceContextSetDefaultDeviceForType_Internal(dctx,static_cast<PetscDeviceType>(dtype+1));CHKERRQ(ierr); 833a4af0ceeSJacob Faibussowitsch } 834030f984aSJacob Faibussowitsch ierr = PetscOptionsEnd();CHKERRQ(ierr); 835030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 836030f984aSJacob Faibussowitsch } 837