1*030f984aSJacob Faibussowitsch #include <petsc/private/deviceimpl.h> /*I "petscdevice.h" I*/ 2*030f984aSJacob Faibussowitsch #include "objpool.hpp" 3*030f984aSJacob Faibussowitsch 4*030f984aSJacob Faibussowitsch /* Define the allocator */ 5*030f984aSJacob Faibussowitsch struct PetscDeviceContextAllocator : Petsc::Allocator<PetscDeviceContext> 6*030f984aSJacob Faibussowitsch { 7*030f984aSJacob Faibussowitsch static PetscInt PetscDeviceContextID; 8*030f984aSJacob Faibussowitsch 9*030f984aSJacob Faibussowitsch PETSC_NODISCARD PetscErrorCode create(PetscDeviceContext *dctx) noexcept 10*030f984aSJacob Faibussowitsch { 11*030f984aSJacob Faibussowitsch PetscDeviceContext dc; 12*030f984aSJacob Faibussowitsch PetscErrorCode ierr; 13*030f984aSJacob Faibussowitsch 14*030f984aSJacob Faibussowitsch PetscFunctionBegin; 15*030f984aSJacob Faibussowitsch ierr = PetscNew(&dc);CHKERRQ(ierr); 16*030f984aSJacob Faibussowitsch dc->id = PetscDeviceContextID++; 17*030f984aSJacob Faibussowitsch dc->idle = PETSC_TRUE; 18*030f984aSJacob Faibussowitsch dc->streamType = PETSC_STREAM_DEFAULT_BLOCKING; 19*030f984aSJacob Faibussowitsch *dctx = dc; 20*030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 21*030f984aSJacob Faibussowitsch } 22*030f984aSJacob Faibussowitsch 23*030f984aSJacob Faibussowitsch PETSC_NODISCARD PetscErrorCode destroy(PetscDeviceContext &dctx) const noexcept 24*030f984aSJacob Faibussowitsch { 25*030f984aSJacob Faibussowitsch PetscErrorCode ierr; 26*030f984aSJacob Faibussowitsch 27*030f984aSJacob Faibussowitsch PetscFunctionBegin; 28*030f984aSJacob Faibussowitsch if (PetscUnlikelyDebug(dctx->numChildren)) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Device context still has %D un-restored children, must call PetscDeviceContextRestore() on all children before destroying",dctx->numChildren); 29*030f984aSJacob Faibussowitsch if (dctx->ops->destroy) {ierr = (*dctx->ops->destroy)(dctx);CHKERRQ(ierr);} 30*030f984aSJacob Faibussowitsch ierr = PetscDeviceDestroy(&dctx->device);CHKERRQ(ierr); 31*030f984aSJacob Faibussowitsch ierr = PetscFree(dctx->childIDs);CHKERRQ(ierr); 32*030f984aSJacob Faibussowitsch ierr = PetscFree(dctx);CHKERRQ(ierr); 33*030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 34*030f984aSJacob Faibussowitsch } 35*030f984aSJacob Faibussowitsch 36*030f984aSJacob Faibussowitsch PETSC_NODISCARD PetscErrorCode reset(PetscDeviceContext &dctx) const noexcept 37*030f984aSJacob Faibussowitsch { 38*030f984aSJacob Faibussowitsch PetscErrorCode ierr; 39*030f984aSJacob Faibussowitsch 40*030f984aSJacob Faibussowitsch PetscFunctionBegin; 41*030f984aSJacob Faibussowitsch /* don't deallocate the child array, rather just zero it out */ 42*030f984aSJacob Faibussowitsch ierr = PetscArrayzero(dctx->childIDs,dctx->maxNumChildren);CHKERRQ(ierr); 43*030f984aSJacob Faibussowitsch dctx->setup = PETSC_FALSE; 44*030f984aSJacob Faibussowitsch dctx->numChildren = 0; 45*030f984aSJacob Faibussowitsch dctx->idle = PETSC_TRUE; 46*030f984aSJacob Faibussowitsch dctx->streamType = PETSC_STREAM_DEFAULT_BLOCKING; 47*030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 48*030f984aSJacob Faibussowitsch } 49*030f984aSJacob Faibussowitsch 50*030f984aSJacob Faibussowitsch PETSC_NODISCARD PetscErrorCode finalize(void) noexcept 51*030f984aSJacob Faibussowitsch { 52*030f984aSJacob Faibussowitsch PetscFunctionBegin; 53*030f984aSJacob Faibussowitsch PetscDeviceContextID = 0; 54*030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 55*030f984aSJacob Faibussowitsch } 56*030f984aSJacob Faibussowitsch }; 57*030f984aSJacob Faibussowitsch PetscInt PetscDeviceContextAllocator::PetscDeviceContextID = 0; 58*030f984aSJacob Faibussowitsch 59*030f984aSJacob Faibussowitsch static Petsc::ObjectPool<PetscDeviceContext,PetscDeviceContextAllocator> contextPool; 60*030f984aSJacob Faibussowitsch 61*030f984aSJacob Faibussowitsch /*@C 62*030f984aSJacob Faibussowitsch PetscDeviceContextCreate - Creates a PetscDeviceContext 63*030f984aSJacob Faibussowitsch 64*030f984aSJacob Faibussowitsch Not Collective, Asynchronous 65*030f984aSJacob Faibussowitsch 66*030f984aSJacob Faibussowitsch Ouput Paramemters: 67*030f984aSJacob Faibussowitsch . dctx - The PetscDeviceContext 68*030f984aSJacob Faibussowitsch 69*030f984aSJacob Faibussowitsch Notes: 70*030f984aSJacob Faibussowitsch Unlike almost every other PETSc class it is advised that most users use 71*030f984aSJacob Faibussowitsch PetscDeviceContextDuplicate() rather than this routine to create new contexts. Contexts 72*030f984aSJacob Faibussowitsch of different types are incompatible with one another; using 73*030f984aSJacob Faibussowitsch PetscDeviceContextDuplicate() ensures compatible types. 74*030f984aSJacob Faibussowitsch 75*030f984aSJacob Faibussowitsch Level: beginner 76*030f984aSJacob Faibussowitsch 77*030f984aSJacob Faibussowitsch .seealso: PetscDeviceContextDuplicate(), PetscDeviceContextSetDevice(), 78*030f984aSJacob Faibussowitsch PetscDeviceContextSetStreamType(), PetscDeviceContextSetUp(), PetscDeviceContextDestroy(), 79*030f984aSJacob Faibussowitsch PetscDeviceContextSetFromOptions() 80*030f984aSJacob Faibussowitsch @*/ 81*030f984aSJacob Faibussowitsch PetscErrorCode PetscDeviceContextCreate(PetscDeviceContext *dctx) 82*030f984aSJacob Faibussowitsch { 83*030f984aSJacob Faibussowitsch PetscErrorCode ierr; 84*030f984aSJacob Faibussowitsch 85*030f984aSJacob Faibussowitsch PetscFunctionBegin; 86*030f984aSJacob Faibussowitsch PetscValidPointer(dctx,1); 87*030f984aSJacob Faibussowitsch ierr = PetscDeviceInitializePackage();CHKERRQ(ierr); 88*030f984aSJacob Faibussowitsch ierr = contextPool.get(*dctx);CHKERRQ(ierr); 89*030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 90*030f984aSJacob Faibussowitsch } 91*030f984aSJacob Faibussowitsch 92*030f984aSJacob Faibussowitsch /*@C 93*030f984aSJacob Faibussowitsch PetscDeviceContextDestroy - Frees a PetscDeviceContext 94*030f984aSJacob Faibussowitsch 95*030f984aSJacob Faibussowitsch Not Collective, Asynchronous 96*030f984aSJacob Faibussowitsch 97*030f984aSJacob Faibussowitsch Input Parameters: 98*030f984aSJacob Faibussowitsch . dctx - The PetscDeviceContext 99*030f984aSJacob Faibussowitsch 100*030f984aSJacob Faibussowitsch Notes: 101*030f984aSJacob Faibussowitsch No implicit synchronization occurs due to this routine, all resources are released completely asynchronously 102*030f984aSJacob Faibussowitsch w.r.t. the host. If one needs to guarantee access to the data produced on this contexts stream one should perform the 103*030f984aSJacob Faibussowitsch appropriate synchronization before calling this routine. 104*030f984aSJacob Faibussowitsch 105*030f984aSJacob Faibussowitsch Developer Notes: 106*030f984aSJacob Faibussowitsch The context is never actually "destroyed", only returned to an ever growing pool of 107*030f984aSJacob Faibussowitsch contexts. There are currently no safeguards on the size of the pool, this should perhaps 108*030f984aSJacob Faibussowitsch be implemented. 109*030f984aSJacob Faibussowitsch 110*030f984aSJacob Faibussowitsch Level: beginner 111*030f984aSJacob Faibussowitsch 112*030f984aSJacob Faibussowitsch .seealso: PetscDeviceContextCreate(), PetscDeviceContextSetDevice(), PetscDeviceContextSetUp(), PetscDeviceContextSynchronize() 113*030f984aSJacob Faibussowitsch @*/ 114*030f984aSJacob Faibussowitsch PetscErrorCode PetscDeviceContextDestroy(PetscDeviceContext *dctx) 115*030f984aSJacob Faibussowitsch { 116*030f984aSJacob Faibussowitsch PetscErrorCode ierr; 117*030f984aSJacob Faibussowitsch 118*030f984aSJacob Faibussowitsch PetscFunctionBegin; 119*030f984aSJacob Faibussowitsch if (!*dctx) PetscFunctionReturn(0); 120*030f984aSJacob Faibussowitsch /* use move assignment whenever possible */ 121*030f984aSJacob Faibussowitsch ierr = contextPool.reclaim(std::move(*dctx));CHKERRQ(ierr); 122*030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 123*030f984aSJacob Faibussowitsch } 124*030f984aSJacob Faibussowitsch 125*030f984aSJacob Faibussowitsch /*@C 126*030f984aSJacob Faibussowitsch PetscDeviceContextSetStreamType - Set the implementation type of the underlying stream for a PetscDeviceContext 127*030f984aSJacob Faibussowitsch 128*030f984aSJacob Faibussowitsch Not Collective, Asynchronous 129*030f984aSJacob Faibussowitsch 130*030f984aSJacob Faibussowitsch Input Paramaters: 131*030f984aSJacob Faibussowitsch + dctx - The PetscDeviceContext 132*030f984aSJacob Faibussowitsch - type - The PetscStreamType 133*030f984aSJacob Faibussowitsch 134*030f984aSJacob Faibussowitsch Notes: 135*030f984aSJacob Faibussowitsch See PetscStreamType in include/petscdevicetypes.h for more information on the available 136*030f984aSJacob Faibussowitsch types and their interactions. If the PetscDeviceContext was previously set up and stream 137*030f984aSJacob Faibussowitsch type was changed, you must call PetscDeviceContextSetUp() again after this routine. 138*030f984aSJacob Faibussowitsch 139*030f984aSJacob Faibussowitsch Level: intermediate 140*030f984aSJacob Faibussowitsch 141*030f984aSJacob Faibussowitsch .seealso: PetscDeviceContextCreate(), PetscDeviceContextSetDevice(), 142*030f984aSJacob Faibussowitsch PetscDeviceContextGetStreamType(), PetscDeviceContextSetUp(), PetscDeviceContextSetFromOptions() 143*030f984aSJacob Faibussowitsch @*/ 144*030f984aSJacob Faibussowitsch PetscErrorCode PetscDeviceContextSetStreamType(PetscDeviceContext dctx, PetscStreamType type) 145*030f984aSJacob Faibussowitsch { 146*030f984aSJacob Faibussowitsch PetscFunctionBegin; 147*030f984aSJacob Faibussowitsch PetscValidDeviceContext(dctx,1); 148*030f984aSJacob Faibussowitsch PetscValidStreamType(type,2); 149*030f984aSJacob Faibussowitsch /* only need to do complex swapping if the object has already been setup */ 150*030f984aSJacob Faibussowitsch if (dctx->setup && (dctx->streamType != type)) { 151*030f984aSJacob Faibussowitsch PetscErrorCode ierr; 152*030f984aSJacob Faibussowitsch 153*030f984aSJacob Faibussowitsch ierr = (*dctx->ops->changestreamtype)(dctx,type);CHKERRQ(ierr); 154*030f984aSJacob Faibussowitsch dctx->setup = PETSC_FALSE; 155*030f984aSJacob Faibussowitsch } 156*030f984aSJacob Faibussowitsch dctx->streamType = type; 157*030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 158*030f984aSJacob Faibussowitsch } 159*030f984aSJacob Faibussowitsch 160*030f984aSJacob Faibussowitsch /*@C 161*030f984aSJacob Faibussowitsch PetscDeviceContextGetStreamType - Get the implementation type of the underlying stream for a PetscDeviceContext 162*030f984aSJacob Faibussowitsch 163*030f984aSJacob Faibussowitsch Not Collective, Asynchronous 164*030f984aSJacob Faibussowitsch 165*030f984aSJacob Faibussowitsch Input Paramater: 166*030f984aSJacob Faibussowitsch . dctx - The PetscDeviceContext 167*030f984aSJacob Faibussowitsch 168*030f984aSJacob Faibussowitsch Output Parameter: 169*030f984aSJacob Faibussowitsch . type - The PetscStreamType 170*030f984aSJacob Faibussowitsch 171*030f984aSJacob Faibussowitsch Notes: 172*030f984aSJacob Faibussowitsch See PetscStreamType in include/petscdevicetypes.h for more information on the available types and their interactions 173*030f984aSJacob Faibussowitsch 174*030f984aSJacob Faibussowitsch Level: intermediate 175*030f984aSJacob Faibussowitsch 176*030f984aSJacob Faibussowitsch .seealso: PetscDeviceContextCreate(), PetscDeviceContextSetDevice(), 177*030f984aSJacob Faibussowitsch PetscDeviceContextSetStreamType(), PetscDeviceContextSetFromOptions() 178*030f984aSJacob Faibussowitsch @*/ 179*030f984aSJacob Faibussowitsch PetscErrorCode PetscDeviceContextGetStreamType(PetscDeviceContext dctx, PetscStreamType *type) 180*030f984aSJacob Faibussowitsch { 181*030f984aSJacob Faibussowitsch PetscFunctionBegin; 182*030f984aSJacob Faibussowitsch PetscValidDeviceContext(dctx,1); 183*030f984aSJacob Faibussowitsch PetscValidIntPointer(type,2); 184*030f984aSJacob Faibussowitsch *type = dctx->streamType; 185*030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 186*030f984aSJacob Faibussowitsch } 187*030f984aSJacob Faibussowitsch 188*030f984aSJacob Faibussowitsch /*@C 189*030f984aSJacob Faibussowitsch PetscDeviceContextSetDevice - Set the underlying device for the PetscDeviceContext 190*030f984aSJacob Faibussowitsch 191*030f984aSJacob Faibussowitsch Not Collective, Possibly Synchronous 192*030f984aSJacob Faibussowitsch 193*030f984aSJacob Faibussowitsch Input Paramaters: 194*030f984aSJacob Faibussowitsch + dctx - The PetscDeviceContext 195*030f984aSJacob Faibussowitsch - device - The PetscDevice 196*030f984aSJacob Faibussowitsch 197*030f984aSJacob Faibussowitsch Notes: 198*030f984aSJacob Faibussowitsch This routine is effectively PetscDeviceContext's "set-type" (so every PetscDeviceContext 199*030f984aSJacob Faibussowitsch must also have an attached PetscDevice). Unlike the usual set-type semantics, it is 200*030f984aSJacob Faibussowitsch not stricly necessary to set a contexts device to enable usage, any created device 201*030f984aSJacob Faibussowitsch contexts will always come equipped with the "default" device. 202*030f984aSJacob Faibussowitsch 203*030f984aSJacob Faibussowitsch Level: intermediate 204*030f984aSJacob Faibussowitsch 205*030f984aSJacob Faibussowitsch .seealso: PetscDeviceCreate(), PetscDeviceContextGetDevice() 206*030f984aSJacob Faibussowitsch @*/ 207*030f984aSJacob Faibussowitsch PetscErrorCode PetscDeviceContextSetDevice(PetscDeviceContext dctx, PetscDevice device) 208*030f984aSJacob Faibussowitsch { 209*030f984aSJacob Faibussowitsch PetscErrorCode ierr; 210*030f984aSJacob Faibussowitsch 211*030f984aSJacob Faibussowitsch PetscFunctionBegin; 212*030f984aSJacob Faibussowitsch PetscValidDeviceContext(dctx,1); 213*030f984aSJacob Faibussowitsch PetscValidDevice(device,2); 214*030f984aSJacob Faibussowitsch if (dctx->device == device) PetscFunctionReturn(0); 215*030f984aSJacob Faibussowitsch ierr = PetscDeviceDestroy(&dctx->device);CHKERRQ(ierr); 216*030f984aSJacob Faibussowitsch ierr = PetscMemzero(dctx->ops,sizeof(*dctx->ops));CHKERRQ(ierr); 217*030f984aSJacob Faibussowitsch ierr = (*device->ops->createcontext)(dctx);CHKERRQ(ierr); 218*030f984aSJacob Faibussowitsch dctx->device = PetscDeviceReference(device); 219*030f984aSJacob Faibussowitsch dctx->setup = PETSC_FALSE; 220*030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 221*030f984aSJacob Faibussowitsch } 222*030f984aSJacob Faibussowitsch 223*030f984aSJacob Faibussowitsch /*@C 224*030f984aSJacob Faibussowitsch PetscDeviceContextGetDevice - Get the underlying PetscDevice for a PetscDeviceContext 225*030f984aSJacob Faibussowitsch 226*030f984aSJacob Faibussowitsch Not Collective, Asynchronous 227*030f984aSJacob Faibussowitsch 228*030f984aSJacob Faibussowitsch Input Parameter: 229*030f984aSJacob Faibussowitsch . dctx - the PetscDeviceContext 230*030f984aSJacob Faibussowitsch 231*030f984aSJacob Faibussowitsch Output Parameter: 232*030f984aSJacob Faibussowitsch . device - The PetscDevice 233*030f984aSJacob Faibussowitsch 234*030f984aSJacob Faibussowitsch Notes: 235*030f984aSJacob Faibussowitsch This is a borrowed reference, the user should not destroy the device. 236*030f984aSJacob Faibussowitsch 237*030f984aSJacob Faibussowitsch .seealso: PetscDeviceContextSetDevice(), PetscDevice 238*030f984aSJacob Faibussowitsch @*/ 239*030f984aSJacob Faibussowitsch PetscErrorCode PetscDeviceContextGetDevice(PetscDeviceContext dctx, PetscDevice *device) 240*030f984aSJacob Faibussowitsch { 241*030f984aSJacob Faibussowitsch PetscFunctionBegin; 242*030f984aSJacob Faibussowitsch PetscValidDeviceContext(dctx,1); 243*030f984aSJacob Faibussowitsch PetscValidPointer(device,2); 244*030f984aSJacob Faibussowitsch *device = dctx->device; 245*030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 246*030f984aSJacob Faibussowitsch } 247*030f984aSJacob Faibussowitsch 248*030f984aSJacob Faibussowitsch /*@C 249*030f984aSJacob Faibussowitsch PetscDeviceContextSetUp - Prepares a PetscDeviceContext for use 250*030f984aSJacob Faibussowitsch 251*030f984aSJacob Faibussowitsch Not Collective, Asynchronous 252*030f984aSJacob Faibussowitsch 253*030f984aSJacob Faibussowitsch Intput Parameter: 254*030f984aSJacob Faibussowitsch . dctx - The PetscDeviceContext 255*030f984aSJacob Faibussowitsch 256*030f984aSJacob Faibussowitsch Developer Notes: 257*030f984aSJacob Faibussowitsch This routine is usually the stage where a PetscDeviceContext acquires device-side data structures such as streams, 258*030f984aSJacob Faibussowitsch events, and (possibly) handles. 259*030f984aSJacob Faibussowitsch 260*030f984aSJacob Faibussowitsch Level: beginner 261*030f984aSJacob Faibussowitsch 262*030f984aSJacob Faibussowitsch .seealso: PetscDeviceContextTypes, PetscDeviceContextCreate(), 263*030f984aSJacob Faibussowitsch PetscDeviceContextSetDevice(), PetscDeviceContextDestroy(), PetscDeviceContextSetFromOptions() 264*030f984aSJacob Faibussowitsch @*/ 265*030f984aSJacob Faibussowitsch PetscErrorCode PetscDeviceContextSetUp(PetscDeviceContext dctx) 266*030f984aSJacob Faibussowitsch { 267*030f984aSJacob Faibussowitsch PetscErrorCode ierr; 268*030f984aSJacob Faibussowitsch 269*030f984aSJacob Faibussowitsch PetscFunctionBegin; 270*030f984aSJacob Faibussowitsch PetscValidDeviceContext(dctx,1); 271*030f984aSJacob Faibussowitsch if (!dctx->device) { 272*030f984aSJacob Faibussowitsch ierr = PetscInfo2(NULL,"PetscDeviceContext %d did not have an explicitly attached PetscDevice, using default with type %s\n",dctx->id,PetscDeviceKinds[PETSC_DEVICE_DEFAULT]);CHKERRQ(ierr); 273*030f984aSJacob Faibussowitsch ierr = PetscDeviceContextSetDevice(dctx,PetscDeviceDefault_Internal());CHKERRQ(ierr); 274*030f984aSJacob Faibussowitsch } 275*030f984aSJacob Faibussowitsch if (dctx->setup) PetscFunctionReturn(0); 276*030f984aSJacob Faibussowitsch ierr = (*dctx->ops->setup)(dctx);CHKERRQ(ierr); 277*030f984aSJacob Faibussowitsch dctx->setup = PETSC_TRUE; 278*030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 279*030f984aSJacob Faibussowitsch } 280*030f984aSJacob Faibussowitsch 281*030f984aSJacob Faibussowitsch /*@C 282*030f984aSJacob Faibussowitsch PetscDeviceContextDuplicate - Duplicates a PetscDeviceContext object 283*030f984aSJacob Faibussowitsch 284*030f984aSJacob Faibussowitsch Not Collective, Asynchronous 285*030f984aSJacob Faibussowitsch 286*030f984aSJacob Faibussowitsch Input Parameter: 287*030f984aSJacob Faibussowitsch . dctx - The PetscDeviceContext to duplicate 288*030f984aSJacob Faibussowitsch 289*030f984aSJacob Faibussowitsch Output Paramter: 290*030f984aSJacob Faibussowitsch . strmdup - The duplicated PetscDeviceContext 291*030f984aSJacob Faibussowitsch 292*030f984aSJacob Faibussowitsch Notes: 293*030f984aSJacob Faibussowitsch This is a shorthand method for creating a PetscDeviceContext with the exact same 294*030f984aSJacob Faibussowitsch settings as another. Note however that the duplicated PetscDeviceContext does not "share" 295*030f984aSJacob Faibussowitsch any of the underlying data with the original, (including its current stream-state) they 296*030f984aSJacob Faibussowitsch are completely separate objects. 297*030f984aSJacob Faibussowitsch 298*030f984aSJacob Faibussowitsch Level: beginner 299*030f984aSJacob Faibussowitsch 300*030f984aSJacob Faibussowitsch .seealso: PetscDeviceContextCreate(), PetscDeviceContextSetDevice(), PetscDeviceContextSetStreamType() 301*030f984aSJacob Faibussowitsch @*/ 302*030f984aSJacob Faibussowitsch PetscErrorCode PetscDeviceContextDuplicate(PetscDeviceContext dctx, PetscDeviceContext *dctxdup) 303*030f984aSJacob Faibussowitsch { 304*030f984aSJacob Faibussowitsch PetscErrorCode ierr; 305*030f984aSJacob Faibussowitsch 306*030f984aSJacob Faibussowitsch PetscFunctionBegin; 307*030f984aSJacob Faibussowitsch PetscValidDeviceContext(dctx,1); 308*030f984aSJacob Faibussowitsch PetscValidPointer(dctxdup,2); 309*030f984aSJacob Faibussowitsch ierr = PetscDeviceContextCreate(dctxdup);CHKERRQ(ierr); 310*030f984aSJacob Faibussowitsch ierr = PetscDeviceContextSetDevice(*dctxdup,dctx->device);CHKERRQ(ierr); 311*030f984aSJacob Faibussowitsch ierr = PetscDeviceContextSetStreamType(*dctxdup,dctx->streamType);CHKERRQ(ierr); 312*030f984aSJacob Faibussowitsch ierr = PetscDeviceContextSetUp(*dctxdup);CHKERRQ(ierr); 313*030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 314*030f984aSJacob Faibussowitsch } 315*030f984aSJacob Faibussowitsch 316*030f984aSJacob Faibussowitsch /*@C 317*030f984aSJacob Faibussowitsch PetscDeviceContextQueryIdle - Returns whether or not a PetscDeviceContext is idle 318*030f984aSJacob Faibussowitsch 319*030f984aSJacob Faibussowitsch Not Collective, Asynchronous 320*030f984aSJacob Faibussowitsch 321*030f984aSJacob Faibussowitsch Input Parameter: 322*030f984aSJacob Faibussowitsch . dctx - The PetscDeviceContext object 323*030f984aSJacob Faibussowitsch 324*030f984aSJacob Faibussowitsch Output Parameter: 325*030f984aSJacob Faibussowitsch . idle - PETSC_TRUE if PetscDeviceContext has NO work, PETSC_FALSE if it has work 326*030f984aSJacob Faibussowitsch 327*030f984aSJacob Faibussowitsch Notes: 328*030f984aSJacob Faibussowitsch This routine only refers a singular context and does NOT take any of its children into account. That is, if dctx is 329*030f984aSJacob Faibussowitsch idle but has dependents who do have work, this routine still returns PETSC_TRUE. 330*030f984aSJacob Faibussowitsch 331*030f984aSJacob Faibussowitsch Results of PetscDeviceContextQueryIdle() are cached on return, allowing this function to be called repeatedly in an 332*030f984aSJacob Faibussowitsch efficient manner. When debug mode is enabled this cache is verified on every call to 333*030f984aSJacob Faibussowitsch this routine, but is blindly believed when debugging is disabled. 334*030f984aSJacob Faibussowitsch 335*030f984aSJacob Faibussowitsch Level: intermediate 336*030f984aSJacob Faibussowitsch 337*030f984aSJacob Faibussowitsch .seealso: PetscDeviceContextCreate(), PetscDeviceContextWaitForContext(), PetscDeviceContextFork() 338*030f984aSJacob Faibussowitsch @*/ 339*030f984aSJacob Faibussowitsch PetscErrorCode PetscDeviceContextQueryIdle(PetscDeviceContext dctx, PetscBool *idle) 340*030f984aSJacob Faibussowitsch { 341*030f984aSJacob Faibussowitsch PetscErrorCode ierr; 342*030f984aSJacob Faibussowitsch 343*030f984aSJacob Faibussowitsch PetscFunctionBegin; 344*030f984aSJacob Faibussowitsch PetscValidDeviceContext(dctx,1); 345*030f984aSJacob Faibussowitsch PetscValidBoolPointer(idle,2); 346*030f984aSJacob Faibussowitsch if (dctx->idle) { 347*030f984aSJacob Faibussowitsch *idle = PETSC_TRUE; 348*030f984aSJacob Faibussowitsch ierr = PetscDeviceContextValidateIdle_Internal(dctx);CHKERRQ(ierr); 349*030f984aSJacob Faibussowitsch } else { 350*030f984aSJacob Faibussowitsch ierr = (*dctx->ops->query)(dctx,idle);CHKERRQ(ierr); 351*030f984aSJacob Faibussowitsch dctx->idle = *idle; 352*030f984aSJacob Faibussowitsch } 353*030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 354*030f984aSJacob Faibussowitsch } 355*030f984aSJacob Faibussowitsch 356*030f984aSJacob Faibussowitsch /*@C 357*030f984aSJacob Faibussowitsch PetscDeviceContextWaitForContext - Make one context wait for another context to finish 358*030f984aSJacob Faibussowitsch 359*030f984aSJacob Faibussowitsch Not Collective, Asynchronous 360*030f984aSJacob Faibussowitsch 361*030f984aSJacob Faibussowitsch Input Parameters: 362*030f984aSJacob Faibussowitsch + dctxa - The PetscDeviceContext object that is waiting 363*030f984aSJacob Faibussowitsch - dctxb - The PetscDeviceContext object that is being waited on 364*030f984aSJacob Faibussowitsch 365*030f984aSJacob Faibussowitsch Notes: 366*030f984aSJacob Faibussowitsch Serializes two PetscDeviceContexts. This routine uses only the state of dctxb at the moment this routine was 367*030f984aSJacob Faibussowitsch called, so any future work queued will not affect dctxa. It is safe to pass the same context to both arguments. 368*030f984aSJacob Faibussowitsch 369*030f984aSJacob Faibussowitsch Level: beginner 370*030f984aSJacob Faibussowitsch 371*030f984aSJacob Faibussowitsch .seealso: PetscDeviceContextCreate(), PetscDeviceContextQueryIdle(), PetscDeviceContextJoin() 372*030f984aSJacob Faibussowitsch @*/ 373*030f984aSJacob Faibussowitsch PetscErrorCode PetscDeviceContextWaitForContext(PetscDeviceContext dctxa, PetscDeviceContext dctxb) 374*030f984aSJacob Faibussowitsch { 375*030f984aSJacob Faibussowitsch PetscErrorCode ierr; 376*030f984aSJacob Faibussowitsch 377*030f984aSJacob Faibussowitsch PetscFunctionBegin; 378*030f984aSJacob Faibussowitsch PetscCheckCompatibleDeviceContexts(dctxa,1,dctxb,2); 379*030f984aSJacob Faibussowitsch if (dctxa == dctxb) PetscFunctionReturn(0); 380*030f984aSJacob Faibussowitsch if (dctxb->idle) { 381*030f984aSJacob Faibussowitsch /* No need to do the extra function lookup and event record if the stream were waiting on isn't doing anything */ 382*030f984aSJacob Faibussowitsch ierr = PetscDeviceContextValidateIdle_Internal(dctxb);CHKERRQ(ierr); 383*030f984aSJacob Faibussowitsch } else { 384*030f984aSJacob Faibussowitsch ierr = (*dctxa->ops->waitforctx)(dctxa,dctxb);CHKERRQ(ierr); 385*030f984aSJacob Faibussowitsch } 386*030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 387*030f984aSJacob Faibussowitsch } 388*030f984aSJacob Faibussowitsch 389*030f984aSJacob Faibussowitsch /*@C 390*030f984aSJacob Faibussowitsch PetscDeviceContextFork - Create a set of dependent child contexts from a parent context 391*030f984aSJacob Faibussowitsch 392*030f984aSJacob Faibussowitsch Not Collective, Asynchronous 393*030f984aSJacob Faibussowitsch 394*030f984aSJacob Faibussowitsch Input Parameters: 395*030f984aSJacob Faibussowitsch + dctx - The parent PetscDeviceContext 396*030f984aSJacob Faibussowitsch - n - The number of children to create 397*030f984aSJacob Faibussowitsch 398*030f984aSJacob Faibussowitsch Output Parameter: 399*030f984aSJacob Faibussowitsch . dsub - The created child context(s) 400*030f984aSJacob Faibussowitsch 401*030f984aSJacob Faibussowitsch Notes: 402*030f984aSJacob Faibussowitsch This routine creates n edges of a DAG from a source node which are causally dependent on the source node, meaning 403*030f984aSJacob Faibussowitsch that work queued on child contexts will not start until the parent context finishes its work. This accounts for work 404*030f984aSJacob Faibussowitsch queued on the parent up until calling this function, any subsequent work enqueued on the parent has no effect on the children. 405*030f984aSJacob Faibussowitsch 406*030f984aSJacob Faibussowitsch Any children created with this routine have their lifetimes bounded by the parent. That is, the parent context expects 407*030f984aSJacob Faibussowitsch to free all of it's children (and ONLY its children) before itself is freed. 408*030f984aSJacob Faibussowitsch 409*030f984aSJacob Faibussowitsch DAG representation: 410*030f984aSJacob Faibussowitsch .vb 411*030f984aSJacob Faibussowitsch time -> 412*030f984aSJacob Faibussowitsch 413*030f984aSJacob Faibussowitsch -> dctx \----> dctx ------> 414*030f984aSJacob Faibussowitsch \---> dsub[0] ---> 415*030f984aSJacob Faibussowitsch \--> ... -------> 416*030f984aSJacob Faibussowitsch \-> dsub[n-1] -> 417*030f984aSJacob Faibussowitsch .ve 418*030f984aSJacob Faibussowitsch 419*030f984aSJacob Faibussowitsch Level: intermediate 420*030f984aSJacob Faibussowitsch 421*030f984aSJacob Faibussowitsch .seealso: PetscDeviceContextJoin(), PetscDeviceContextSynchronize(), PetscDeviceContextQueryIdle() 422*030f984aSJacob Faibussowitsch @*/ 423*030f984aSJacob Faibussowitsch PetscErrorCode PetscDeviceContextFork(PetscDeviceContext dctx, PetscInt n, PetscDeviceContext **dsub) 424*030f984aSJacob Faibussowitsch { 425*030f984aSJacob Faibussowitsch #if defined(PETSC_USE_DEBUG) && defined(PETSC_USE_INFO) 426*030f984aSJacob Faibussowitsch const PetscInt nBefore = n; 427*030f984aSJacob Faibussowitsch static std::string idList; 428*030f984aSJacob Faibussowitsch #endif 429*030f984aSJacob Faibussowitsch PetscDeviceContext *dsubTmp = nullptr; 430*030f984aSJacob Faibussowitsch PetscInt i = 0; 431*030f984aSJacob Faibussowitsch PetscErrorCode ierr; 432*030f984aSJacob Faibussowitsch 433*030f984aSJacob Faibussowitsch PetscFunctionBegin; 434*030f984aSJacob Faibussowitsch PetscValidDeviceContext(dctx,1); 435*030f984aSJacob Faibussowitsch PetscValidPointer(dsub,3); 436*030f984aSJacob Faibussowitsch if (PetscUnlikelyDebug(n < 0)) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Number of contexts requested %D < 0",n); 437*030f984aSJacob Faibussowitsch #if defined(PETSC_USE_DEBUG) && defined(PETSC_USE_INFO) 438*030f984aSJacob Faibussowitsch /* reserve 4 chars per id, 2 for number and 2 for ', ' separator */ 439*030f984aSJacob Faibussowitsch idList.reserve(4*n); 440*030f984aSJacob Faibussowitsch #endif 441*030f984aSJacob Faibussowitsch /* update child totals */ 442*030f984aSJacob Faibussowitsch dctx->numChildren += n; 443*030f984aSJacob Faibussowitsch /* now to find out if we have room */ 444*030f984aSJacob Faibussowitsch if (dctx->numChildren > dctx->maxNumChildren) { 445*030f984aSJacob Faibussowitsch /* no room, either from having too many kids or not having any */ 446*030f984aSJacob Faibussowitsch if (dctx->childIDs) { 447*030f984aSJacob Faibussowitsch /* have existing children, must reallocate them */ 448*030f984aSJacob Faibussowitsch ierr = PetscRealloc(dctx->numChildren*sizeof(*dctx->childIDs),&dctx->childIDs);CHKERRQ(ierr); 449*030f984aSJacob Faibussowitsch /* clear the extra memory since realloc doesn't do it for us */ 450*030f984aSJacob Faibussowitsch ierr = PetscArrayzero((dctx->childIDs)+(dctx->maxNumChildren),(dctx->numChildren)-(dctx->maxNumChildren));CHKERRQ(ierr); 451*030f984aSJacob Faibussowitsch } else { 452*030f984aSJacob Faibussowitsch /* have no children */ 453*030f984aSJacob Faibussowitsch ierr = PetscCalloc1(dctx->numChildren,&dctx->childIDs);CHKERRQ(ierr); 454*030f984aSJacob Faibussowitsch } 455*030f984aSJacob Faibussowitsch /* update total number of children */ 456*030f984aSJacob Faibussowitsch dctx->maxNumChildren = dctx->numChildren; 457*030f984aSJacob Faibussowitsch } 458*030f984aSJacob Faibussowitsch ierr = PetscMalloc1(n,&dsubTmp);CHKERRQ(ierr); 459*030f984aSJacob Faibussowitsch while (n) { 460*030f984aSJacob Faibussowitsch /* empty child slot */ 461*030f984aSJacob Faibussowitsch if (!(dctx->childIDs[i])) { 462*030f984aSJacob Faibussowitsch /* create the child context in the image of its parent */ 463*030f984aSJacob Faibussowitsch ierr = PetscDeviceContextDuplicate(dctx,dsubTmp+i);CHKERRQ(ierr); 464*030f984aSJacob Faibussowitsch ierr = PetscDeviceContextWaitForContext(dsubTmp[i],dctx);CHKERRQ(ierr); 465*030f984aSJacob Faibussowitsch /* register the child with its parent */ 466*030f984aSJacob Faibussowitsch dctx->childIDs[i] = dsubTmp[i]->id; 467*030f984aSJacob Faibussowitsch #if defined(PETSC_USE_DEBUG) && defined(PETSC_USE_INFO) 468*030f984aSJacob Faibussowitsch idList += std::to_string(dsubTmp[i]->id); 469*030f984aSJacob Faibussowitsch if (n != 1) idList += ", "; 470*030f984aSJacob Faibussowitsch #endif 471*030f984aSJacob Faibussowitsch --n; 472*030f984aSJacob Faibussowitsch } 473*030f984aSJacob Faibussowitsch ++i; 474*030f984aSJacob Faibussowitsch } 475*030f984aSJacob Faibussowitsch #if defined(PETSC_USE_DEBUG) && defined(PETSC_USE_INFO) 476*030f984aSJacob Faibussowitsch ierr = PetscInfo3(NULL,"Forked %D children from parent %D with IDs: %s\n",nBefore,dctx->id,idList.c_str());CHKERRQ(ierr); 477*030f984aSJacob Faibussowitsch /* resets the size but doesn't deallocate the memory */ 478*030f984aSJacob Faibussowitsch idList.clear(); 479*030f984aSJacob Faibussowitsch #endif 480*030f984aSJacob Faibussowitsch /* pass the children back to caller */ 481*030f984aSJacob Faibussowitsch *dsub = dsubTmp; 482*030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 483*030f984aSJacob Faibussowitsch } 484*030f984aSJacob Faibussowitsch 485*030f984aSJacob Faibussowitsch /*@C 486*030f984aSJacob Faibussowitsch PetscDeviceContextJoin() - Converge a set of child contexts 487*030f984aSJacob Faibussowitsch 488*030f984aSJacob Faibussowitsch Not Collective, Asynchronous 489*030f984aSJacob Faibussowitsch 490*030f984aSJacob Faibussowitsch Input Parameters: 491*030f984aSJacob Faibussowitsch + dctx - A PetscDeviceContext to converge on 492*030f984aSJacob Faibussowitsch . n - The number of sub contexts to converge 493*030f984aSJacob Faibussowitsch . joinMode - The type of join to perform 494*030f984aSJacob Faibussowitsch - dsub - The sub contexts to converge 495*030f984aSJacob Faibussowitsch 496*030f984aSJacob Faibussowitsch Notes: 497*030f984aSJacob Faibussowitsch If PetscDeviceContextFork() creates n edges from a source node which all depend on the 498*030f984aSJacob Faibussowitsch source node, then this routine is the exact mirror. That is, it creates a node 499*030f984aSJacob Faibussowitsch (represented in dctx) which recieves n edges (and optionally destroys them) which is 500*030f984aSJacob Faibussowitsch dependent on the completion of all incoming edges. 501*030f984aSJacob Faibussowitsch 502*030f984aSJacob Faibussowitsch If joinMode is PETSC_DEVICE_CONTEXT_JOIN_DESTROY all contexts in dsub will be destroyed 503*030f984aSJacob Faibussowitsch by this routine. Thus all sub contexts must have been created with the dctx passed to 504*030f984aSJacob Faibussowitsch this routine. 505*030f984aSJacob Faibussowitsch 506*030f984aSJacob Faibussowitsch if joinMode is PETSC_DEVICE_CONTEXT_JOIN_NO_SYNC dctx waits for all sub contexts but the 507*030f984aSJacob Faibussowitsch sub contexts do not wait for one another afterwards. 508*030f984aSJacob Faibussowitsch 509*030f984aSJacob Faibussowitsch If joinMode is PETSC_DEVICE_CONTEXT_JOIN_SYNC all sub contexts will additionally 510*030f984aSJacob Faibussowitsch wait on dctx after converging. This has the effect of "synchronizing" the outgoing 511*030f984aSJacob Faibussowitsch edges. 512*030f984aSJacob Faibussowitsch 513*030f984aSJacob Faibussowitsch DAG representations: 514*030f984aSJacob Faibussowitsch If joinMode is PETSC_DEVICE_CONTEXT_JOIN_DESTROY 515*030f984aSJacob Faibussowitsch .vb 516*030f984aSJacob Faibussowitsch time -> 517*030f984aSJacob Faibussowitsch 518*030f984aSJacob Faibussowitsch -> dctx ---------/- dctx -> 519*030f984aSJacob Faibussowitsch -> dsub[0] -----/ 520*030f984aSJacob Faibussowitsch -> ... -------/ 521*030f984aSJacob Faibussowitsch -> dsub[n-1] -/ 522*030f984aSJacob Faibussowitsch .ve 523*030f984aSJacob Faibussowitsch If joinMode is PETSC_DEVICE_CONTEXT_JOIN_NO_SYNC 524*030f984aSJacob Faibussowitsch .vb 525*030f984aSJacob Faibussowitsch time -> 526*030f984aSJacob Faibussowitsch 527*030f984aSJacob Faibussowitsch -> dctx ---------/- dctx -> 528*030f984aSJacob Faibussowitsch -> dsub[0] -----/---------> 529*030f984aSJacob Faibussowitsch -> ... -------/----------> 530*030f984aSJacob Faibussowitsch -> dsub[n-1] -/-----------> 531*030f984aSJacob Faibussowitsch .ve 532*030f984aSJacob Faibussowitsch If joinMode is PETSC_DEVICE_CONTEXT_JOIN_SYNC 533*030f984aSJacob Faibussowitsch .vb 534*030f984aSJacob Faibussowitsch time -> 535*030f984aSJacob Faibussowitsch 536*030f984aSJacob Faibussowitsch -> dctx ---------/- dctx -\----> dctx ------> 537*030f984aSJacob Faibussowitsch -> dsub[0] -----/ \---> dsub[0] ---> 538*030f984aSJacob Faibussowitsch -> ... -------/ \--> ... -------> 539*030f984aSJacob Faibussowitsch -> dsub[n-1] -/ \-> dsub[n-1] -> 540*030f984aSJacob Faibussowitsch .ve 541*030f984aSJacob Faibussowitsch 542*030f984aSJacob Faibussowitsch Level: intermediate 543*030f984aSJacob Faibussowitsch 544*030f984aSJacob Faibussowitsch .seealso: PetscDeviceContextFork(), PetscDeviceContextSynchronize(), PetscDeviceContextJoinMode 545*030f984aSJacob Faibussowitsch @*/ 546*030f984aSJacob Faibussowitsch PetscErrorCode PetscDeviceContextJoin(PetscDeviceContext dctx, PetscInt n, PetscDeviceContextJoinMode joinMode, PetscDeviceContext **dsub) 547*030f984aSJacob Faibussowitsch { 548*030f984aSJacob Faibussowitsch #if defined(PETSC_USE_DEBUG) && defined(PETSC_USE_INFO) 549*030f984aSJacob Faibussowitsch static std::string idList; 550*030f984aSJacob Faibussowitsch #endif 551*030f984aSJacob Faibussowitsch PetscErrorCode ierr; 552*030f984aSJacob Faibussowitsch 553*030f984aSJacob Faibussowitsch PetscFunctionBegin; 554*030f984aSJacob Faibussowitsch /* validity of dctx is checked in the wait-for loop */ 555*030f984aSJacob Faibussowitsch PetscValidPointer(dsub,4); 556*030f984aSJacob Faibussowitsch if (PetscUnlikelyDebug(n < 0)) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Number of contexts merged %D < 0",n); 557*030f984aSJacob Faibussowitsch #if defined(PETSC_USE_DEBUG) && defined(PETSC_USE_INFO) 558*030f984aSJacob Faibussowitsch /* reserve 4 chars per id, 2 for number and 2 for ', ' separator */ 559*030f984aSJacob Faibussowitsch idList.reserve(4*n); 560*030f984aSJacob Faibussowitsch #endif 561*030f984aSJacob Faibussowitsch /* first dctx waits on all the incoming edges */ 562*030f984aSJacob Faibussowitsch for (PetscInt i = 0; i < n; ++i) { 563*030f984aSJacob Faibussowitsch PetscCheckCompatibleDeviceContexts(dctx,1,(*dsub)[i],4); 564*030f984aSJacob Faibussowitsch ierr = PetscDeviceContextWaitForContext(dctx,(*dsub)[i]);CHKERRQ(ierr); 565*030f984aSJacob Faibussowitsch #if defined(PETSC_USE_DEBUG) && defined(PETSC_USE_INFO) 566*030f984aSJacob Faibussowitsch idList += std::to_string((*dsub)[i]->id); 567*030f984aSJacob Faibussowitsch if (i+1 < n) idList += ", "; 568*030f984aSJacob Faibussowitsch #endif 569*030f984aSJacob Faibussowitsch } 570*030f984aSJacob Faibussowitsch 571*030f984aSJacob Faibussowitsch /* now we handle the aftermath */ 572*030f984aSJacob Faibussowitsch switch (joinMode) { 573*030f984aSJacob Faibussowitsch case PETSC_DEVICE_CONTEXT_JOIN_DESTROY: 574*030f984aSJacob Faibussowitsch { 575*030f984aSJacob Faibussowitsch PetscInt j = 0; 576*030f984aSJacob Faibussowitsch 577*030f984aSJacob Faibussowitsch if (PetscUnlikelyDebug(n > dctx->numChildren)) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Trying to destroy %D children of a parent context that only has %D children, likely trying to restore to wrong parent",n,dctx->numChildren); 578*030f984aSJacob Faibussowitsch /* update child count while it's still fresh in memory */ 579*030f984aSJacob Faibussowitsch dctx->numChildren -= n; 580*030f984aSJacob Faibussowitsch for (PetscInt i = 0; i < dctx->maxNumChildren; ++i) { 581*030f984aSJacob Faibussowitsch if (dctx->childIDs[i] && (dctx->childIDs[i] == (*dsub)[j]->id)) { 582*030f984aSJacob Faibussowitsch /* child is one of ours, can destroy it */ 583*030f984aSJacob Faibussowitsch ierr = PetscDeviceContextDestroy((*dsub)+j);CHKERRQ(ierr); 584*030f984aSJacob Faibussowitsch /* reset the child slot */ 585*030f984aSJacob Faibussowitsch dctx->childIDs[i] = 0; 586*030f984aSJacob Faibussowitsch if (++j == n) break; 587*030f984aSJacob Faibussowitsch } 588*030f984aSJacob Faibussowitsch } 589*030f984aSJacob 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 */ 590*030f984aSJacob Faibussowitsch if (PetscUnlikelyDebug(j != n)) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"%D 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); 591*030f984aSJacob Faibussowitsch ierr = PetscFree(*dsub);CHKERRQ(ierr); 592*030f984aSJacob Faibussowitsch } 593*030f984aSJacob Faibussowitsch break; 594*030f984aSJacob Faibussowitsch case PETSC_DEVICE_CONTEXT_JOIN_SYNC: 595*030f984aSJacob Faibussowitsch for (PetscInt i = 0; i < n; ++i) { 596*030f984aSJacob Faibussowitsch ierr = PetscDeviceContextWaitForContext((*dsub)[i],dctx);CHKERRQ(ierr); 597*030f984aSJacob Faibussowitsch } 598*030f984aSJacob Faibussowitsch case PETSC_DEVICE_CONTEXT_JOIN_NO_SYNC: 599*030f984aSJacob Faibussowitsch break; 600*030f984aSJacob Faibussowitsch default: 601*030f984aSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Unknown PetscDeviceContextJoinMode given"); 602*030f984aSJacob Faibussowitsch break; 603*030f984aSJacob Faibussowitsch } 604*030f984aSJacob Faibussowitsch 605*030f984aSJacob Faibussowitsch #if defined(PETSC_USE_DEBUG) && defined(PETSC_USE_INFO) 606*030f984aSJacob Faibussowitsch ierr = PetscInfo4(NULL,"Joined %D ctxs to ctx %D, mode %s with IDs: %s\n",n,dctx->id,PetscDeviceContextJoinModes[joinMode],idList.c_str());CHKERRQ(ierr); 607*030f984aSJacob Faibussowitsch idList.clear(); 608*030f984aSJacob Faibussowitsch #endif 609*030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 610*030f984aSJacob Faibussowitsch } 611*030f984aSJacob Faibussowitsch 612*030f984aSJacob Faibussowitsch /*@C 613*030f984aSJacob Faibussowitsch PetscDeviceContextSynchronize() - Block the host until all work queued on or associated with a PetscDeviceContext has finished 614*030f984aSJacob Faibussowitsch 615*030f984aSJacob Faibussowitsch Not Collective, Synchronous 616*030f984aSJacob Faibussowitsch 617*030f984aSJacob Faibussowitsch Input Parameters: 618*030f984aSJacob Faibussowitsch . dctx - The PetscDeviceContext to synchronize 619*030f984aSJacob Faibussowitsch 620*030f984aSJacob Faibussowitsch Level: beginner 621*030f984aSJacob Faibussowitsch 622*030f984aSJacob Faibussowitsch .seealso: PetscDeviceContextFork(), PetscDeviceContextJoin(), PetscDeviceContextQueryIdle() 623*030f984aSJacob Faibussowitsch @*/ 624*030f984aSJacob Faibussowitsch PetscErrorCode PetscDeviceContextSynchronize(PetscDeviceContext dctx) 625*030f984aSJacob Faibussowitsch { 626*030f984aSJacob Faibussowitsch PetscErrorCode ierr; 627*030f984aSJacob Faibussowitsch 628*030f984aSJacob Faibussowitsch PetscFunctionBegin; 629*030f984aSJacob Faibussowitsch PetscValidDeviceContext(dctx,1); 630*030f984aSJacob Faibussowitsch /* if it isn't setup there is nothing to sync on */ 631*030f984aSJacob Faibussowitsch if (dctx->setup) {ierr = (*dctx->ops->synchronize)(dctx);CHKERRQ(ierr);} 632*030f984aSJacob Faibussowitsch dctx->idle = PETSC_TRUE; 633*030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 634*030f984aSJacob Faibussowitsch } 635*030f984aSJacob Faibussowitsch 636*030f984aSJacob Faibussowitsch static PetscDeviceContext globalContext = nullptr; 637*030f984aSJacob Faibussowitsch static PetscBool globalContextSetup = PETSC_FALSE; 638*030f984aSJacob Faibussowitsch static PetscStreamType defaultStreamType = PETSC_STREAM_DEFAULT_BLOCKING; 639*030f984aSJacob Faibussowitsch 640*030f984aSJacob Faibussowitsch /* automatically registered to PetscFinalize() when first context is instantiated, do not 641*030f984aSJacob Faibussowitsch call */ 642*030f984aSJacob Faibussowitsch static PetscErrorCode PetscDeviceContextDestroyGlobalContext_Private(void) 643*030f984aSJacob Faibussowitsch { 644*030f984aSJacob Faibussowitsch PetscErrorCode ierr; 645*030f984aSJacob Faibussowitsch 646*030f984aSJacob Faibussowitsch PetscFunctionBegin; 647*030f984aSJacob Faibussowitsch ierr = PetscDeviceContextSynchronize(globalContext);CHKERRQ(ierr); 648*030f984aSJacob Faibussowitsch ierr = PetscDeviceContextDestroy(&globalContext);CHKERRQ(ierr); 649*030f984aSJacob Faibussowitsch /* reset everything to defaults */ 650*030f984aSJacob Faibussowitsch defaultStreamType = PETSC_STREAM_DEFAULT_BLOCKING; 651*030f984aSJacob Faibussowitsch globalContextSetup = PETSC_FALSE; 652*030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 653*030f984aSJacob Faibussowitsch } 654*030f984aSJacob Faibussowitsch 655*030f984aSJacob Faibussowitsch /* creates and initializes the root context in PetscInitialize() but does not call 656*030f984aSJacob Faibussowitsch SetUp() as the user may wish to change types after PetscInitialize() */ 657*030f984aSJacob Faibussowitsch PetscErrorCode PetscDeviceContextInitializeRootContext_Internal(MPI_Comm comm, const char prefix[]) 658*030f984aSJacob Faibussowitsch { 659*030f984aSJacob Faibussowitsch PetscErrorCode ierr; 660*030f984aSJacob Faibussowitsch 661*030f984aSJacob Faibussowitsch PetscFunctionBegin; 662*030f984aSJacob Faibussowitsch ierr = PetscInfo1(NULL,"Initializing root PetscDeviceContext with PetscDeviceKind %s\n",PetscDeviceKinds[PETSC_DEVICE_DEFAULT]);CHKERRQ(ierr); 663*030f984aSJacob Faibussowitsch ierr = PetscDeviceContextCreate(&globalContext);CHKERRQ(ierr); 664*030f984aSJacob Faibussowitsch if (PetscUnlikelyDebug(globalContext->id != 0)) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"The root current PetscDeviceContext should have id = 0, however it has id = %D",globalContext->id); 665*030f984aSJacob Faibussowitsch ierr = PetscDeviceContextSetDevice(globalContext,PetscDeviceDefault_Internal());CHKERRQ(ierr); 666*030f984aSJacob Faibussowitsch ierr = PetscDeviceContextSetStreamType(globalContext,defaultStreamType);CHKERRQ(ierr); 667*030f984aSJacob Faibussowitsch ierr = PetscDeviceContextSetFromOptions(comm,prefix,globalContext);CHKERRQ(ierr); 668*030f984aSJacob Faibussowitsch ierr = PetscRegisterFinalize(PetscDeviceContextDestroyGlobalContext_Private);CHKERRQ(ierr); 669*030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 670*030f984aSJacob Faibussowitsch } 671*030f984aSJacob Faibussowitsch 672*030f984aSJacob Faibussowitsch /*@C 673*030f984aSJacob Faibussowitsch PetscDeviceContextGetCurrentContext() - Get the current active PetscDeviceContext 674*030f984aSJacob Faibussowitsch 675*030f984aSJacob Faibussowitsch Not Collective, Asynchronous 676*030f984aSJacob Faibussowitsch 677*030f984aSJacob Faibussowitsch Output Parameter: 678*030f984aSJacob Faibussowitsch . dctx - The PetscDeviceContext 679*030f984aSJacob Faibussowitsch 680*030f984aSJacob Faibussowitsch Notes: 681*030f984aSJacob Faibussowitsch The user generally should not destroy contexts retrieved with this routine unless they themselves have created 682*030f984aSJacob Faibussowitsch them. There exists no protection against destroying the root context. 683*030f984aSJacob Faibussowitsch 684*030f984aSJacob Faibussowitsch Developer Notes: 685*030f984aSJacob Faibussowitsch This routine creates the "root" context the first time it is called, registering its 686*030f984aSJacob Faibussowitsch destructor to PetscFinalize(). The root context is synchronized before being destroyed. 687*030f984aSJacob Faibussowitsch 688*030f984aSJacob Faibussowitsch Level: beginner 689*030f984aSJacob Faibussowitsch 690*030f984aSJacob Faibussowitsch .seealso: PetscDeviceContextSetCurrentContext(), PetscDeviceContextFork(), 691*030f984aSJacob Faibussowitsch PetscDeviceContextJoin(), PetscDeviceContextCreate() 692*030f984aSJacob Faibussowitsch @*/ 693*030f984aSJacob Faibussowitsch PetscErrorCode PetscDeviceContextGetCurrentContext(PetscDeviceContext *dctx) 694*030f984aSJacob Faibussowitsch { 695*030f984aSJacob Faibussowitsch PetscFunctionBegin; 696*030f984aSJacob Faibussowitsch PetscValidPointer(dctx,1); 697*030f984aSJacob Faibussowitsch if (PetscUnlikely(!globalContextSetup)) { 698*030f984aSJacob Faibussowitsch PetscErrorCode ierr; 699*030f984aSJacob Faibussowitsch 700*030f984aSJacob Faibussowitsch /* if there is no available device backend, PetscDeviceInitializePackage() will fire a 701*030f984aSJacob Faibussowitsch PETSC_ERR_SUP_SYS error. */ 702*030f984aSJacob Faibussowitsch ierr = PetscDeviceInitializePackage();CHKERRQ(ierr); 703*030f984aSJacob Faibussowitsch ierr = PetscDeviceContextSetUp(globalContext);CHKERRQ(ierr); 704*030f984aSJacob Faibussowitsch globalContextSetup = PETSC_TRUE; 705*030f984aSJacob Faibussowitsch } 706*030f984aSJacob Faibussowitsch *dctx = globalContext; 707*030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 708*030f984aSJacob Faibussowitsch } 709*030f984aSJacob Faibussowitsch 710*030f984aSJacob Faibussowitsch /*@C 711*030f984aSJacob Faibussowitsch PetscDeviceContextSetCurrentContext() - Set the current active PetscDeviceContext 712*030f984aSJacob Faibussowitsch 713*030f984aSJacob Faibussowitsch Not Collective, Asynchronous 714*030f984aSJacob Faibussowitsch 715*030f984aSJacob Faibussowitsch Input Parameter: 716*030f984aSJacob Faibussowitsch . dctx - The PetscDeviceContext 717*030f984aSJacob Faibussowitsch 718*030f984aSJacob Faibussowitsch Notes: 719*030f984aSJacob Faibussowitsch The old context is not stored in any way by this routine; if one is overriding a context that they themselves do not 720*030f984aSJacob Faibussowitsch control, one should take care to temporarily store it by calling PetscDeviceContextGetCurrentContext() before calling 721*030f984aSJacob Faibussowitsch this routine. 722*030f984aSJacob Faibussowitsch 723*030f984aSJacob Faibussowitsch Level: beginner 724*030f984aSJacob Faibussowitsch 725*030f984aSJacob Faibussowitsch .seealso: PetscDeviceContextGetCurrentContext(), PetscDeviceContextFork(), 726*030f984aSJacob Faibussowitsch PetscDeviceContextJoin(), PetscDeviceContextCreate() 727*030f984aSJacob Faibussowitsch @*/ 728*030f984aSJacob Faibussowitsch PetscErrorCode PetscDeviceContextSetCurrentContext(PetscDeviceContext dctx) 729*030f984aSJacob Faibussowitsch { 730*030f984aSJacob Faibussowitsch PetscErrorCode ierr; 731*030f984aSJacob Faibussowitsch 732*030f984aSJacob Faibussowitsch PetscFunctionBegin; 733*030f984aSJacob Faibussowitsch PetscValidDeviceContext(dctx,1); 734*030f984aSJacob Faibussowitsch globalContext = dctx; 735*030f984aSJacob Faibussowitsch ierr = PetscInfo1(NULL,"Set global device context id %D\n",dctx->id);CHKERRQ(ierr); 736*030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 737*030f984aSJacob Faibussowitsch } 738*030f984aSJacob Faibussowitsch 739*030f984aSJacob Faibussowitsch /*@C 740*030f984aSJacob Faibussowitsch PetscDeviceContextSetFromOptions - Configure a PetscDeviceContext from the options database 741*030f984aSJacob Faibussowitsch 742*030f984aSJacob Faibussowitsch Collective on comm, Asynchronous 743*030f984aSJacob Faibussowitsch 744*030f984aSJacob Faibussowitsch Input Parameters: 745*030f984aSJacob Faibussowitsch + comm - MPI communicator on which to query the options database 746*030f984aSJacob Faibussowitsch . prefix - prefix to prepend to all options database queries, NULL if not needed 747*030f984aSJacob Faibussowitsch - dctx - The PetscDeviceContext to configure 748*030f984aSJacob Faibussowitsch 749*030f984aSJacob Faibussowitsch Output Parameter: 750*030f984aSJacob Faibussowitsch . dctx - The PetscDeviceContext 751*030f984aSJacob Faibussowitsch 752*030f984aSJacob Faibussowitsch Options Database: 753*030f984aSJacob Faibussowitsch . -device_context_device_kind - the kind of PetscDevice to attach by default 754*030f984aSJacob Faibussowitsch . -device_context_stream_type - type of stream to create inside the PetscDeviceContext - 755*030f984aSJacob Faibussowitsch PetscDeviceContextSetStreamType() 756*030f984aSJacob Faibussowitsch 757*030f984aSJacob Faibussowitsch Level: beginner 758*030f984aSJacob Faibussowitsch 759*030f984aSJacob Faibussowitsch .seealso: PetscDeviceContextSetStreamType() 760*030f984aSJacob Faibussowitsch @*/ 761*030f984aSJacob Faibussowitsch PetscErrorCode PetscDeviceContextSetFromOptions(MPI_Comm comm, const char prefix[], PetscDeviceContext dctx) 762*030f984aSJacob Faibussowitsch { 763*030f984aSJacob Faibussowitsch PetscBool flag; 764*030f984aSJacob Faibussowitsch PetscInt stype,dkind; 765*030f984aSJacob Faibussowitsch PetscErrorCode ierr; 766*030f984aSJacob Faibussowitsch 767*030f984aSJacob Faibussowitsch PetscFunctionBegin; 768*030f984aSJacob Faibussowitsch if (prefix) {PetscValidCharPointer(prefix,2);} 769*030f984aSJacob Faibussowitsch PetscValidDeviceContext(dctx,3); 770*030f984aSJacob Faibussowitsch ierr = PetscOptionsBegin(comm,prefix,"PetscDeviceContext Options","Sys");CHKERRQ(ierr); 771*030f984aSJacob Faibussowitsch ierr = PetscOptionsEList("-device_context_device_kind","Underlying PetscDevice","PetscDeviceContextSetDevice",PetscDeviceKinds+1,PETSC_DEVICE_MAX-1,dctx->device ? PetscDeviceKinds[dctx->device->kind] : PetscDeviceKinds[PETSC_DEVICE_DEFAULT],&dkind,&flag);CHKERRQ(ierr); 772*030f984aSJacob Faibussowitsch if (flag) { 773*030f984aSJacob Faibussowitsch ierr = PetscDeviceContextSetDevice(dctx,PetscDeviceDefaultKind_Internal(static_cast<PetscDeviceKind>(dkind+1)));CHKERRQ(ierr); 774*030f984aSJacob Faibussowitsch } 775*030f984aSJacob Faibussowitsch ierr = PetscOptionsEList("-device_context_stream_type","PetscDeviceContext PetscStreamType","PetscDeviceContextSetStreamType",PetscStreamTypes,3,PetscStreamTypes[dctx->streamType],&stype,&flag);CHKERRQ(ierr); 776*030f984aSJacob Faibussowitsch if (flag) { 777*030f984aSJacob Faibussowitsch ierr = PetscDeviceContextSetStreamType(dctx,static_cast<PetscStreamType>(stype));CHKERRQ(ierr); 778*030f984aSJacob Faibussowitsch } 779*030f984aSJacob Faibussowitsch ierr = PetscOptionsEnd();CHKERRQ(ierr); 780*030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 781*030f984aSJacob Faibussowitsch } 782