10e6b6b59SJacob Faibussowitsch #include "petscdevice_interface_internal.hpp" /*I <petscdevice.h> I*/ 20e6b6b59SJacob Faibussowitsch #include <petsc/private/viewerimpl.h> // _p_PetscViewer for PetscObjectCast() 3030f984aSJacob Faibussowitsch 40e6b6b59SJacob Faibussowitsch #include <petsc/private/cpp/object_pool.hpp> 50e6b6b59SJacob Faibussowitsch #include <petsc/private/cpp/utility.hpp> 60e6b6b59SJacob Faibussowitsch #include <petsc/private/cpp/array.hpp> 7a4af0ceeSJacob Faibussowitsch 80e6b6b59SJacob Faibussowitsch #include <vector> 90e6b6b59SJacob Faibussowitsch #include <string> // std::to_string among other things 10a4af0ceeSJacob Faibussowitsch 11030f984aSJacob Faibussowitsch /* Define the allocator */ 120e6b6b59SJacob Faibussowitsch class PetscDeviceContextAllocator : public Petsc::AllocatorBase<PetscDeviceContext> { 130e6b6b59SJacob Faibussowitsch public: 140e6b6b59SJacob Faibussowitsch PETSC_CXX_COMPAT_DECL(PetscErrorCode create(PetscDeviceContext *dctx)) { 15030f984aSJacob Faibussowitsch PetscFunctionBegin; 160e6b6b59SJacob Faibussowitsch PetscCall(PetscHeaderCreate(*dctx, PETSC_DEVICE_CONTEXT_CLASSID, "PetscDeviceContext", "PetscDeviceContext", "Sys", PETSC_COMM_SELF, PetscDeviceContextDestroy, PetscDeviceContextView)); 170e6b6b59SJacob Faibussowitsch PetscCallCXX(PetscObjectCast(*dctx)->cpp = new CxxData()); 180e6b6b59SJacob Faibussowitsch PetscCall(reset(*dctx, false)); 19030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 20030f984aSJacob Faibussowitsch } 21030f984aSJacob Faibussowitsch 220e6b6b59SJacob Faibussowitsch PETSC_CXX_COMPAT_DECL(PetscErrorCode destroy(PetscDeviceContext dctx)) { 23030f984aSJacob Faibussowitsch PetscFunctionBegin; 24bf025ffbSJacob Faibussowitsch PetscAssert(!dctx->numChildren, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Device context still has %" PetscInt_FMT " un-joined children, must call PetscDeviceContextJoin() with all children before destroying", dctx->numChildren); 25dbbe0bcdSBarry Smith PetscTryTypeMethod(dctx, destroy); 269566063dSJacob Faibussowitsch PetscCall(PetscDeviceDestroy(&dctx->device)); 279566063dSJacob Faibussowitsch PetscCall(PetscFree(dctx->childIDs)); 280e6b6b59SJacob Faibussowitsch delete CxxDataCast(dctx); 290e6b6b59SJacob Faibussowitsch PetscCall(PetscHeaderDestroy(&dctx)); 30030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 31030f984aSJacob Faibussowitsch } 32030f984aSJacob Faibussowitsch 330e6b6b59SJacob Faibussowitsch PETSC_CXX_COMPAT_DECL(PetscErrorCode reset(PetscDeviceContext dctx, bool zero = true)) { 34030f984aSJacob Faibussowitsch PetscFunctionBegin; 350e6b6b59SJacob Faibussowitsch if (zero) { 360e6b6b59SJacob Faibussowitsch // reset the device if the user set it 370e6b6b59SJacob Faibussowitsch if (auto &userset = dctx->usersetdevice) { 380e6b6b59SJacob Faibussowitsch userset = PETSC_FALSE; 390e6b6b59SJacob Faibussowitsch PetscTryTypeMethod(dctx, destroy); 400e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceDestroy(&dctx->device)); 410e6b6b59SJacob Faibussowitsch PetscCall(PetscArrayzero(dctx->ops, 1)); 420e6b6b59SJacob Faibussowitsch dctx->data = nullptr; 430e6b6b59SJacob Faibussowitsch } 440e6b6b59SJacob Faibussowitsch PetscCall(PetscHeaderReset_Internal(PetscObjectCast(dctx))); 45030f984aSJacob Faibussowitsch dctx->numChildren = 0; 460e6b6b59SJacob Faibussowitsch dctx->setup = PETSC_FALSE; 470e6b6b59SJacob Faibussowitsch // don't deallocate the child array, rather just zero it out 480e6b6b59SJacob Faibussowitsch PetscCall(PetscArrayzero(dctx->childIDs, dctx->maxNumChildren)); 490e6b6b59SJacob Faibussowitsch PetscCall(CxxDataCast(dctx)->clear()); 500e6b6b59SJacob Faibussowitsch } 51030f984aSJacob Faibussowitsch dctx->streamType = PETSC_STREAM_DEFAULT_BLOCKING; 52030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 53030f984aSJacob Faibussowitsch } 54030f984aSJacob Faibussowitsch }; 55030f984aSJacob Faibussowitsch 56030f984aSJacob Faibussowitsch static Petsc::ObjectPool<PetscDeviceContext, PetscDeviceContextAllocator> contextPool; 57030f984aSJacob Faibussowitsch 58030f984aSJacob Faibussowitsch /*@C 59811af0c4SBarry Smith PetscDeviceContextCreate - Creates a `PetscDeviceContext` 60030f984aSJacob Faibussowitsch 610e6b6b59SJacob Faibussowitsch Not Collective 62030f984aSJacob Faibussowitsch 6301d2d390SJose E. Roman Output Paramemter: 64811af0c4SBarry Smith . dctx - The `PetscDeviceContext` 65030f984aSJacob Faibussowitsch 66811af0c4SBarry Smith Note: 67030f984aSJacob Faibussowitsch Unlike almost every other PETSc class it is advised that most users use 680e6b6b59SJacob Faibussowitsch `PetscDeviceContextDuplicate()` rather than this routine to create new contexts. Contexts of 690e6b6b59SJacob Faibussowitsch different types are incompatible with one another; using `PetscDeviceContextDuplicate()` 700e6b6b59SJacob Faibussowitsch ensures compatible types. 710e6b6b59SJacob Faibussowitsch 720e6b6b59SJacob Faibussowitsch DAG representation: 730e6b6b59SJacob Faibussowitsch .vb 740e6b6b59SJacob Faibussowitsch time -> 750e6b6b59SJacob Faibussowitsch 760e6b6b59SJacob Faibussowitsch |= CALL =| - dctx -> 770e6b6b59SJacob Faibussowitsch .ve 78030f984aSJacob Faibussowitsch 79030f984aSJacob Faibussowitsch Level: beginner 80030f984aSJacob Faibussowitsch 810e6b6b59SJacob Faibussowitsch .N ASYNC_API 820e6b6b59SJacob Faibussowitsch 83db781477SPatrick Sanan .seealso: `PetscDeviceContextDuplicate()`, `PetscDeviceContextSetDevice()`, 84db781477SPatrick Sanan `PetscDeviceContextSetStreamType()`, `PetscDeviceContextSetUp()`, 850e6b6b59SJacob Faibussowitsch `PetscDeviceContextSetFromOptions()`, `PetscDeviceContextView()`, `PetscDeviceContextDestroy()` 86030f984aSJacob Faibussowitsch @*/ 879371c9d4SSatish Balay PetscErrorCode PetscDeviceContextCreate(PetscDeviceContext *dctx) { 88030f984aSJacob Faibussowitsch PetscFunctionBegin; 89030f984aSJacob Faibussowitsch PetscValidPointer(dctx, 1); 909566063dSJacob Faibussowitsch PetscCall(PetscDeviceInitializePackage()); 91*6a4a1270SPierre Jolivet PetscCall(PetscLogEventBegin(DCONTEXT_Create, nullptr, nullptr, nullptr, nullptr)); 920e6b6b59SJacob Faibussowitsch PetscCall(contextPool.allocate(dctx)); 93*6a4a1270SPierre Jolivet PetscCall(PetscLogEventEnd(DCONTEXT_Create, nullptr, nullptr, nullptr, nullptr)); 94030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 95030f984aSJacob Faibussowitsch } 96030f984aSJacob Faibussowitsch 97030f984aSJacob Faibussowitsch /*@C 98811af0c4SBarry Smith PetscDeviceContextDestroy - Frees a `PetscDeviceContext` 99030f984aSJacob Faibussowitsch 1000e6b6b59SJacob Faibussowitsch Not Collective 101030f984aSJacob Faibussowitsch 102030f984aSJacob Faibussowitsch Input Parameters: 103811af0c4SBarry Smith . dctx - The `PetscDeviceContext` 104030f984aSJacob Faibussowitsch 1050e6b6b59SJacob Faibussowitsch Notes: 1060e6b6b59SJacob Faibussowitsch No implicit synchronization occurs due to this routine, all resources are released completely 1070e6b6b59SJacob Faibussowitsch asynchronously w.r.t. the host. If one needs to guarantee access to the data produced on 1080e6b6b59SJacob Faibussowitsch `dctx`'s stream the user is responsible for calling `PetscDeviceContextSynchronize()` before 1090e6b6b59SJacob Faibussowitsch calling this routine. 110030f984aSJacob Faibussowitsch 1110e6b6b59SJacob Faibussowitsch DAG represetation: 1120e6b6b59SJacob Faibussowitsch .vb 1130e6b6b59SJacob Faibussowitsch time -> 1140e6b6b59SJacob Faibussowitsch 1150e6b6b59SJacob Faibussowitsch -> dctx - |= CALL =| 1160e6b6b59SJacob Faibussowitsch .ve 1170e6b6b59SJacob Faibussowitsch 1180e6b6b59SJacob Faibussowitsch Developer Notes: 1190e6b6b59SJacob Faibussowitsch `dctx` is never actually "destroyed" in the classical sense. It is returned to an ever 1200e6b6b59SJacob Faibussowitsch growing pool of `PetscDeviceContext`s. There are currently no limits on the size of the pool, 1210e6b6b59SJacob Faibussowitsch this should perhaps be implemented. 122030f984aSJacob Faibussowitsch 123030f984aSJacob Faibussowitsch Level: beginner 124030f984aSJacob Faibussowitsch 1250e6b6b59SJacob Faibussowitsch .N ASYNC_API 1260e6b6b59SJacob Faibussowitsch 1270e6b6b59SJacob Faibussowitsch .seealso: `PetscDeviceContextCreate()`, `PetscDeviceContextSetDevice()`, 1280e6b6b59SJacob Faibussowitsch `PetscDeviceContextSetUp()`, `PetscDeviceContextSynchronize()` 129030f984aSJacob Faibussowitsch @*/ 1309371c9d4SSatish Balay PetscErrorCode PetscDeviceContextDestroy(PetscDeviceContext *dctx) { 131030f984aSJacob Faibussowitsch PetscFunctionBegin; 1320e6b6b59SJacob Faibussowitsch PetscValidPointer(dctx, 1); 133030f984aSJacob Faibussowitsch if (!*dctx) PetscFunctionReturn(0); 134*6a4a1270SPierre Jolivet PetscCall(PetscLogEventBegin(DCONTEXT_Destroy, nullptr, nullptr, nullptr, nullptr)); 1350e6b6b59SJacob Faibussowitsch if (--(PetscObjectCast(*dctx)->refct) <= 0) { 1360e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextCheckNotOrphaned_Internal(*dctx)); 1370e6b6b59SJacob Faibussowitsch // std::move of the expression of the trivially-copyable type 'PetscDeviceContext' (aka 1380e6b6b59SJacob Faibussowitsch // '_n_PetscDeviceContext *') has no effect; remove std::move() [performance-move-const-arg] 1390e6b6b59SJacob Faibussowitsch // can't remove std::move, since reclaim only takes r-value reference 1400e6b6b59SJacob Faibussowitsch PetscCall(contextPool.deallocate(std::move(*dctx))); // NOLINT (performance-move-const-arg) 1410e6b6b59SJacob Faibussowitsch } 142*6a4a1270SPierre Jolivet PetscCall(PetscLogEventEnd(DCONTEXT_Destroy, nullptr, nullptr, nullptr, nullptr)); 143bf025ffbSJacob Faibussowitsch *dctx = nullptr; 144030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 145030f984aSJacob Faibussowitsch } 146030f984aSJacob Faibussowitsch 147030f984aSJacob Faibussowitsch /*@C 1480e6b6b59SJacob Faibussowitsch PetscDeviceContextSetStreamType - Set the implementation type of the underlying stream for a 1490e6b6b59SJacob Faibussowitsch `PetscDeviceContext` 150030f984aSJacob Faibussowitsch 1510e6b6b59SJacob Faibussowitsch Not Collective 152030f984aSJacob Faibussowitsch 15301d2d390SJose E. Roman Input Parameters: 154811af0c4SBarry Smith + dctx - The `PetscDeviceContext` 155811af0c4SBarry Smith - type - The `PetscStreamType` 156030f984aSJacob Faibussowitsch 157030f984aSJacob Faibussowitsch Notes: 158811af0c4SBarry Smith See `PetscStreamType` in `include/petscdevicetypes.h` for more information on the available 1590e6b6b59SJacob Faibussowitsch types and their interactions. If the `PetscDeviceContext` was previously set up and stream 160811af0c4SBarry Smith type was changed, you must call `PetscDeviceContextSetUp()` again after this routine. 161030f984aSJacob Faibussowitsch 1620e6b6b59SJacob Faibussowitsch Level: beginner 163030f984aSJacob Faibussowitsch 1640e6b6b59SJacob Faibussowitsch .seealso: `PetscStreamType`, `PetscDeviceContextGetStreamType()`, `PetscDeviceContextCreate()`, 1650e6b6b59SJacob Faibussowitsch `PetscDeviceContextSetUp()`, `PetscDeviceContextSetFromOptions()` 166030f984aSJacob Faibussowitsch @*/ 1679371c9d4SSatish Balay PetscErrorCode PetscDeviceContextSetStreamType(PetscDeviceContext dctx, PetscStreamType type) { 168030f984aSJacob Faibussowitsch PetscFunctionBegin; 1690e6b6b59SJacob Faibussowitsch // do not use getoptionalnullcontext here since we do not want the user to change the stream 1700e6b6b59SJacob Faibussowitsch // type 171030f984aSJacob Faibussowitsch PetscValidDeviceContext(dctx, 1); 172030f984aSJacob Faibussowitsch PetscValidStreamType(type, 2); 1730e6b6b59SJacob Faibussowitsch // only need to do complex swapping if the object has already been setup 174030f984aSJacob Faibussowitsch if (dctx->setup && (dctx->streamType != type)) { 175030f984aSJacob Faibussowitsch dctx->setup = PETSC_FALSE; 176*6a4a1270SPierre Jolivet PetscCall(PetscLogEventBegin(DCONTEXT_ChangeStream, dctx, nullptr, nullptr, nullptr)); 1770e6b6b59SJacob Faibussowitsch PetscUseTypeMethod(dctx, changestreamtype, type); 178*6a4a1270SPierre Jolivet PetscCall(PetscLogEventEnd(DCONTEXT_ChangeStream, dctx, nullptr, nullptr, nullptr)); 179030f984aSJacob Faibussowitsch } 180030f984aSJacob Faibussowitsch dctx->streamType = type; 181030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 182030f984aSJacob Faibussowitsch } 183030f984aSJacob Faibussowitsch 184030f984aSJacob Faibussowitsch /*@C 1850e6b6b59SJacob Faibussowitsch PetscDeviceContextGetStreamType - Get the implementation type of the underlying stream for a 1860e6b6b59SJacob Faibussowitsch `PetscDeviceContext` 187030f984aSJacob Faibussowitsch 1880e6b6b59SJacob Faibussowitsch Not Collective 189030f984aSJacob Faibussowitsch 19001d2d390SJose E. Roman Input Parameter: 191811af0c4SBarry Smith . dctx - The `PetscDeviceContext` 192030f984aSJacob Faibussowitsch 193030f984aSJacob Faibussowitsch Output Parameter: 194811af0c4SBarry Smith . type - The `PetscStreamType` 195030f984aSJacob Faibussowitsch 1960e6b6b59SJacob Faibussowitsch Notes: 1970e6b6b59SJacob Faibussowitsch See `PetscStreamType` in `include/petscdevicetypes.h` for more information on the available 1980e6b6b59SJacob Faibussowitsch types and their interactions 199030f984aSJacob Faibussowitsch 2000e6b6b59SJacob Faibussowitsch Level: beginner 201030f984aSJacob Faibussowitsch 2020e6b6b59SJacob Faibussowitsch .seealso: `PetscDeviceContextSetStreamType()`, `PetscDeviceContextCreate()`, 2030e6b6b59SJacob Faibussowitsch `PetscDeviceContextSetFromOptions()` 204030f984aSJacob Faibussowitsch @*/ 2059371c9d4SSatish Balay PetscErrorCode PetscDeviceContextGetStreamType(PetscDeviceContext dctx, PetscStreamType *type) { 206030f984aSJacob Faibussowitsch PetscFunctionBegin; 2070e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextGetOptionalNullContext_Internal(&dctx)); 208030f984aSJacob Faibussowitsch PetscValidIntPointer(type, 2); 209030f984aSJacob Faibussowitsch *type = dctx->streamType; 210030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 211030f984aSJacob Faibussowitsch } 212030f984aSJacob Faibussowitsch 2130e6b6b59SJacob Faibussowitsch /* 2140e6b6b59SJacob Faibussowitsch Actual function to set the device. 215030f984aSJacob Faibussowitsch 2160e6b6b59SJacob Faibussowitsch 1. Repeatedly destroying and recreating internal data structures (like streams and events) 2170e6b6b59SJacob Faibussowitsch for recycled PetscDeviceContexts is not free. If done often, it does add up. 2180e6b6b59SJacob Faibussowitsch 2. The vast majority of PetscDeviceContexts are created by PETSc either as children or 2190e6b6b59SJacob Faibussowitsch default contexts. The default contexts *never* change type, and the chilren are extremely 2200e6b6b59SJacob Faibussowitsch unlikely to (chances are if you fork once, you will fork again very soon). 2210e6b6b59SJacob Faibussowitsch 3. The only time this calculus changes is if the user themselves sets the device type. In 2220e6b6b59SJacob Faibussowitsch this case we do not know what the user has changed, so must always wipe the slate clean. 2230e6b6b59SJacob Faibussowitsch 2240e6b6b59SJacob Faibussowitsch Thus we need to keep track whether the user explicitly sets the device contexts device. 2250e6b6b59SJacob Faibussowitsch */ 2260e6b6b59SJacob Faibussowitsch static PetscErrorCode PetscDeviceContextSetDevice_Private(PetscDeviceContext dctx, PetscDevice device, PetscBool user_set) { 2270e6b6b59SJacob Faibussowitsch PetscFunctionBegin; 2280e6b6b59SJacob Faibussowitsch // do not use getoptionalnullcontext here since we do not want the user to change its device 2290e6b6b59SJacob Faibussowitsch PetscValidDeviceContext(dctx, 1); 2300e6b6b59SJacob Faibussowitsch PetscValidDevice(device, 2); 2310e6b6b59SJacob Faibussowitsch if (dctx->device && (dctx->device->id == device->id)) PetscFunctionReturn(0); 232*6a4a1270SPierre Jolivet PetscCall(PetscLogEventBegin(DCONTEXT_SetDevice, dctx, nullptr, nullptr, nullptr)); 2330e6b6b59SJacob Faibussowitsch if (const auto destroy = dctx->ops->destroy) PetscCall((*destroy)(dctx)); 2340e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceDestroy(&dctx->device)); 2350e6b6b59SJacob Faibussowitsch PetscCall(PetscMemzero(dctx->ops, sizeof(*dctx->ops))); 2360e6b6b59SJacob Faibussowitsch PetscCall((*device->ops->createcontext)(dctx)); 237*6a4a1270SPierre Jolivet PetscCall(PetscLogEventEnd(DCONTEXT_SetDevice, dctx, nullptr, nullptr, nullptr)); 2380e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceReference_Internal(device)); 2390e6b6b59SJacob Faibussowitsch dctx->device = device; 2400e6b6b59SJacob Faibussowitsch dctx->setup = PETSC_FALSE; 2410e6b6b59SJacob Faibussowitsch dctx->usersetdevice = user_set; 2420e6b6b59SJacob Faibussowitsch PetscFunctionReturn(0); 2430e6b6b59SJacob Faibussowitsch } 2440e6b6b59SJacob Faibussowitsch 2450e6b6b59SJacob Faibussowitsch PetscErrorCode PetscDeviceContextSetDefaultDeviceForType_Internal(PetscDeviceContext dctx, PetscDeviceType type) { 2460e6b6b59SJacob Faibussowitsch PetscDevice device; 2470e6b6b59SJacob Faibussowitsch 2480e6b6b59SJacob Faibussowitsch PetscFunctionBegin; 2490e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceGetDefaultForType_Internal(type, &device)); 2500e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextSetDevice_Private(dctx, device, PETSC_FALSE)); 2510e6b6b59SJacob Faibussowitsch PetscFunctionReturn(0); 2520e6b6b59SJacob Faibussowitsch } 2530e6b6b59SJacob Faibussowitsch 2540e6b6b59SJacob Faibussowitsch /*@C 2550e6b6b59SJacob Faibussowitsch PetscDeviceContextSetDevice - Set the underlying `PetscDevice` for a `PetscDeviceContext` 2560e6b6b59SJacob Faibussowitsch 2570e6b6b59SJacob Faibussowitsch Not Collective 258030f984aSJacob Faibussowitsch 25901d2d390SJose E. Roman Input Parameters: 260811af0c4SBarry Smith + dctx - The `PetscDeviceContext` 261811af0c4SBarry Smith - device - The `PetscDevice` 262030f984aSJacob Faibussowitsch 263030f984aSJacob Faibussowitsch Notes: 2640e6b6b59SJacob Faibussowitsch This routine is effectively `PetscDeviceContext`'s "set-type" (so every `PetscDeviceContext` must 2650e6b6b59SJacob Faibussowitsch also have an attached `PetscDevice`). Unlike the usual set-type semantics, it is not stricly 2660e6b6b59SJacob Faibussowitsch necessary to set a contexts device to enable usage, any created `PetscDeviceContext`s will 2670e6b6b59SJacob Faibussowitsch always come equipped with the "default" device. 268030f984aSJacob Faibussowitsch 2690e6b6b59SJacob Faibussowitsch This routine is a no-op if `device` is already attached to `dctx`. 270a4af0ceeSJacob Faibussowitsch 2710e6b6b59SJacob Faibussowitsch This routine may (but is very unlikely to) initialize the backend device and may incur 2720e6b6b59SJacob Faibussowitsch synchronization. 2735181c4f9SJacob Faibussowitsch 274030f984aSJacob Faibussowitsch Level: intermediate 275030f984aSJacob Faibussowitsch 2760e6b6b59SJacob Faibussowitsch .seealso: `PetscDeviceCreate()`, `PetscDeviceConfigure()`, `PetscDeviceContextGetDevice()`, 2770e6b6b59SJacob Faibussowitsch `PetscDeviceContextGetDeviceType()` 278030f984aSJacob Faibussowitsch @*/ 2799371c9d4SSatish Balay PetscErrorCode PetscDeviceContextSetDevice(PetscDeviceContext dctx, PetscDevice device) { 280030f984aSJacob Faibussowitsch PetscFunctionBegin; 2810e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextSetDevice_Private(dctx, device, PETSC_TRUE)); 282030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 283030f984aSJacob Faibussowitsch } 284030f984aSJacob Faibussowitsch 285030f984aSJacob Faibussowitsch /*@C 286811af0c4SBarry Smith PetscDeviceContextGetDevice - Get the underlying `PetscDevice` for a `PetscDeviceContext` 287030f984aSJacob Faibussowitsch 2880e6b6b59SJacob Faibussowitsch Not Collective 289030f984aSJacob Faibussowitsch 290030f984aSJacob Faibussowitsch Input Parameter: 291811af0c4SBarry Smith . dctx - the `PetscDeviceContext` 292030f984aSJacob Faibussowitsch 293030f984aSJacob Faibussowitsch Output Parameter: 294811af0c4SBarry Smith . device - The `PetscDevice` 295030f984aSJacob Faibussowitsch 2960e6b6b59SJacob Faibussowitsch Notes: 297811af0c4SBarry Smith This is a borrowed reference, the user should not destroy `device`. 298030f984aSJacob Faibussowitsch 299a375dbeeSPatrick Sanan Level: intermediate 300a375dbeeSPatrick Sanan 3010e6b6b59SJacob Faibussowitsch .seealso: `PetscDeviceContextSetDevice()`, `PetscDevice`, `PetscDeviceContextGetDeviceType()` 302030f984aSJacob Faibussowitsch @*/ 3039371c9d4SSatish Balay PetscErrorCode PetscDeviceContextGetDevice(PetscDeviceContext dctx, PetscDevice *device) { 304030f984aSJacob Faibussowitsch PetscFunctionBegin; 3050e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextGetOptionalNullContext_Internal(&dctx)); 306030f984aSJacob Faibussowitsch PetscValidPointer(device, 2); 3070e6b6b59SJacob Faibussowitsch PetscAssert(dctx->device, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "PetscDeviceContext %" PetscInt64_FMT " has no attached PetscDevice to get", PetscObjectCast(dctx)->id); 308030f984aSJacob Faibussowitsch *device = dctx->device; 309030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 310030f984aSJacob Faibussowitsch } 311030f984aSJacob Faibussowitsch 312030f984aSJacob Faibussowitsch /*@C 3130e6b6b59SJacob Faibussowitsch PetscDeviceContextGetDeviceType - Get the `PetscDeviceType` for a `PetscDeviceContext` 3140e6b6b59SJacob Faibussowitsch 3150e6b6b59SJacob Faibussowitsch Not Collective 3160e6b6b59SJacob Faibussowitsch 3170e6b6b59SJacob Faibussowitsch Input Parameter: 3180e6b6b59SJacob Faibussowitsch . dctx - The `PetscDeviceContext` 3190e6b6b59SJacob Faibussowitsch 3200e6b6b59SJacob Faibussowitsch Output Parameter: 3210e6b6b59SJacob Faibussowitsch . type - The `PetscDeviceType` 3220e6b6b59SJacob Faibussowitsch 3230e6b6b59SJacob Faibussowitsch Notes: 3240e6b6b59SJacob Faibussowitsch This routine is a convenience shorthand for `PetscDeviceContextGetDevice()` -> 3250e6b6b59SJacob Faibussowitsch `PetscDeviceGetType()`. 3260e6b6b59SJacob Faibussowitsch 3270e6b6b59SJacob Faibussowitsch Level: beginner 3280e6b6b59SJacob Faibussowitsch 3290e6b6b59SJacob Faibussowitsch .seealso: `PetscDeviceType`, `PetscDeviceContextGetDevice()`, `PetscDeviceGetType()`, `PetscDevice` 3300e6b6b59SJacob Faibussowitsch @*/ 3310e6b6b59SJacob Faibussowitsch PetscErrorCode PetscDeviceContextGetDeviceType(PetscDeviceContext dctx, PetscDeviceType *type) { 3320e6b6b59SJacob Faibussowitsch PetscDevice device = nullptr; 3330e6b6b59SJacob Faibussowitsch 3340e6b6b59SJacob Faibussowitsch PetscFunctionBegin; 3350e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextGetOptionalNullContext_Internal(&dctx)); 3360e6b6b59SJacob Faibussowitsch PetscValidPointer(type, 2); 3370e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextGetDevice(dctx, &device)); 3380e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceGetType(device, type)); 3390e6b6b59SJacob Faibussowitsch PetscFunctionReturn(0); 3400e6b6b59SJacob Faibussowitsch } 3410e6b6b59SJacob Faibussowitsch 3420e6b6b59SJacob Faibussowitsch /*@C 343811af0c4SBarry Smith PetscDeviceContextSetUp - Prepares a `PetscDeviceContext` for use 344030f984aSJacob Faibussowitsch 3450e6b6b59SJacob Faibussowitsch Not Collective 346030f984aSJacob Faibussowitsch 34701d2d390SJose E. Roman Input Parameter: 348811af0c4SBarry Smith . dctx - The `PetscDeviceContext` 349030f984aSJacob Faibussowitsch 3500e6b6b59SJacob Faibussowitsch Developer Notes: 3510e6b6b59SJacob Faibussowitsch This routine is usually the stage where a `PetscDeviceContext` acquires device-side data 3520e6b6b59SJacob Faibussowitsch structures such as streams, events, and (possibly) handles. 353030f984aSJacob Faibussowitsch 354030f984aSJacob Faibussowitsch Level: beginner 355030f984aSJacob Faibussowitsch 3560e6b6b59SJacob Faibussowitsch .seealso: `PetscDeviceContextCreate()`, `PetscDeviceContextSetDevice()`, 3570e6b6b59SJacob Faibussowitsch `PetscDeviceContextDestroy()`, `PetscDeviceContextSetFromOptions()` 358030f984aSJacob Faibussowitsch @*/ 3599371c9d4SSatish Balay PetscErrorCode PetscDeviceContextSetUp(PetscDeviceContext dctx) { 360030f984aSJacob Faibussowitsch PetscFunctionBegin; 3610e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextGetOptionalNullContext_Internal(&dctx)); 362030f984aSJacob Faibussowitsch if (dctx->setup) PetscFunctionReturn(0); 3630e6b6b59SJacob Faibussowitsch if (!dctx->device) { 3640e6b6b59SJacob Faibussowitsch const auto default_dtype = PETSC_DEVICE_DEFAULT(); 3650e6b6b59SJacob Faibussowitsch 3660e6b6b59SJacob Faibussowitsch PetscCall(PetscInfo(dctx, "PetscDeviceContext %" PetscInt64_FMT " did not have an explicitly attached PetscDevice, using default with type %s\n", PetscObjectCast(dctx)->id, PetscDeviceTypes[default_dtype])); 3670e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextSetDefaultDeviceForType_Internal(dctx, default_dtype)); 3680e6b6b59SJacob Faibussowitsch } 369*6a4a1270SPierre Jolivet PetscCall(PetscLogEventBegin(DCONTEXT_SetUp, dctx, nullptr, nullptr, nullptr)); 370dbbe0bcdSBarry Smith PetscUseTypeMethod(dctx, setup); 371*6a4a1270SPierre Jolivet PetscCall(PetscLogEventEnd(DCONTEXT_SetUp, dctx, nullptr, nullptr, nullptr)); 372030f984aSJacob Faibussowitsch dctx->setup = PETSC_TRUE; 373030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 374030f984aSJacob Faibussowitsch } 375030f984aSJacob Faibussowitsch 3760e6b6b59SJacob Faibussowitsch static PetscErrorCode PetscDeviceContextDuplicate_Private(PetscDeviceContext dctx, PetscStreamType stype, PetscDeviceContext *dctxdup) { 3770e6b6b59SJacob Faibussowitsch PetscFunctionBegin; 378*6a4a1270SPierre Jolivet PetscCall(PetscLogEventBegin(DCONTEXT_Duplicate, dctx, nullptr, nullptr, nullptr)); 3790e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextCreate(dctxdup)); 3800e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextSetStreamType(*dctxdup, stype)); 3810e6b6b59SJacob Faibussowitsch if (const auto device = dctx->device) PetscCall(PetscDeviceContextSetDevice_Private(*dctxdup, device, dctx->usersetdevice)); 3820e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextSetUp(*dctxdup)); 383*6a4a1270SPierre Jolivet PetscCall(PetscLogEventEnd(DCONTEXT_Duplicate, dctx, nullptr, nullptr, nullptr)); 3840e6b6b59SJacob Faibussowitsch PetscFunctionReturn(0); 3850e6b6b59SJacob Faibussowitsch } 3860e6b6b59SJacob Faibussowitsch 387030f984aSJacob Faibussowitsch /*@C 388811af0c4SBarry Smith PetscDeviceContextDuplicate - Duplicates a `PetscDeviceContext` object 389030f984aSJacob Faibussowitsch 3900e6b6b59SJacob Faibussowitsch Not Collective 391030f984aSJacob Faibussowitsch 392030f984aSJacob Faibussowitsch Input Parameter: 393811af0c4SBarry Smith . dctx - The `PetscDeviceContext` to duplicate 394030f984aSJacob Faibussowitsch 3956aad120cSJose E. Roman Output Parameter: 396811af0c4SBarry Smith . dctxdup - The duplicated `PetscDeviceContext` 397030f984aSJacob Faibussowitsch 3980e6b6b59SJacob Faibussowitsch Notes: 3990e6b6b59SJacob Faibussowitsch This is a shorthand method for creating a `PetscDeviceContext` with the exact same settings as 4000e6b6b59SJacob Faibussowitsch another. Note however that `dctxdup` does not share any of the underlying data with `dctx`, 4010e6b6b59SJacob Faibussowitsch (including its current stream-state) they are completely separate objects. 4020e6b6b59SJacob Faibussowitsch 4030e6b6b59SJacob Faibussowitsch There is no implied ordering between `dctx` or `dctxdup`. 4040e6b6b59SJacob Faibussowitsch 4050e6b6b59SJacob Faibussowitsch DAG representation: 4060e6b6b59SJacob Faibussowitsch .vb 4070e6b6b59SJacob Faibussowitsch time -> 4080e6b6b59SJacob Faibussowitsch 4090e6b6b59SJacob Faibussowitsch -> dctx - |= CALL =| - dctx ----> 4100e6b6b59SJacob Faibussowitsch - dctxdup -> 4110e6b6b59SJacob Faibussowitsch .ve 412030f984aSJacob Faibussowitsch 413030f984aSJacob Faibussowitsch Level: beginner 414030f984aSJacob Faibussowitsch 4150e6b6b59SJacob Faibussowitsch .seealso: `PetscDeviceContextCreate()`, `PetscDeviceContextSetDevice()`, 4160e6b6b59SJacob Faibussowitsch `PetscDeviceContextSetStreamType()` 417030f984aSJacob Faibussowitsch @*/ 4189371c9d4SSatish Balay PetscErrorCode PetscDeviceContextDuplicate(PetscDeviceContext dctx, PetscDeviceContext *dctxdup) { 4190e6b6b59SJacob Faibussowitsch auto stype = PETSC_STREAM_DEFAULT_BLOCKING; 420030f984aSJacob Faibussowitsch 421030f984aSJacob Faibussowitsch PetscFunctionBegin; 4220e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextGetOptionalNullContext_Internal(&dctx)); 423030f984aSJacob Faibussowitsch PetscValidPointer(dctxdup, 2); 4240e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextGetStreamType(dctx, &stype)); 4250e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextDuplicate_Private(dctx, stype, dctxdup)); 426030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 427030f984aSJacob Faibussowitsch } 428030f984aSJacob Faibussowitsch 429030f984aSJacob Faibussowitsch /*@C 430811af0c4SBarry Smith PetscDeviceContextQueryIdle - Returns whether or not a `PetscDeviceContext` is idle 431030f984aSJacob Faibussowitsch 4320e6b6b59SJacob Faibussowitsch Not Collective 433030f984aSJacob Faibussowitsch 434030f984aSJacob Faibussowitsch Input Parameter: 4350e6b6b59SJacob Faibussowitsch . dctx - The `PetscDeviceContext` 436030f984aSJacob Faibussowitsch 437030f984aSJacob Faibussowitsch Output Parameter: 4380e6b6b59SJacob Faibussowitsch . idle - `PETSC_TRUE` if `dctx` has NO work, `PETSC_FALSE` if it has work 439030f984aSJacob Faibussowitsch 440811af0c4SBarry Smith Note: 441ef657721SJacob Faibussowitsch This routine only refers a singular context and does NOT take any of its children into 4420e6b6b59SJacob Faibussowitsch account. That is, if `dctx` is idle but has dependents who do have work this routine still 443811af0c4SBarry Smith returns `PETSC_TRUE`. 444030f984aSJacob Faibussowitsch 445030f984aSJacob Faibussowitsch Level: intermediate 446030f984aSJacob Faibussowitsch 447db781477SPatrick Sanan .seealso: `PetscDeviceContextCreate()`, `PetscDeviceContextWaitForContext()`, `PetscDeviceContextFork()` 448030f984aSJacob Faibussowitsch @*/ 4499371c9d4SSatish Balay PetscErrorCode PetscDeviceContextQueryIdle(PetscDeviceContext dctx, PetscBool *idle) { 450030f984aSJacob Faibussowitsch PetscFunctionBegin; 4510e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextGetOptionalNullContext_Internal(&dctx)); 452030f984aSJacob Faibussowitsch PetscValidBoolPointer(idle, 2); 453*6a4a1270SPierre Jolivet PetscCall(PetscLogEventBegin(DCONTEXT_QueryIdle, dctx, nullptr, nullptr, nullptr)); 454dbbe0bcdSBarry Smith PetscUseTypeMethod(dctx, query, idle); 455*6a4a1270SPierre Jolivet PetscCall(PetscLogEventEnd(DCONTEXT_QueryIdle, dctx, nullptr, nullptr, nullptr)); 4560e6b6b59SJacob Faibussowitsch PetscCall(PetscInfo(dctx, "PetscDeviceContext ('%s', id %" PetscInt64_FMT ") %s idle\n", PetscObjectCast(dctx)->name ? PetscObjectCast(dctx)->name : "unnamed", PetscObjectCast(dctx)->id, *idle ? "was" : "was not")); 457030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 458030f984aSJacob Faibussowitsch } 459030f984aSJacob Faibussowitsch 460030f984aSJacob Faibussowitsch /*@C 461030f984aSJacob Faibussowitsch PetscDeviceContextWaitForContext - Make one context wait for another context to finish 462030f984aSJacob Faibussowitsch 4630e6b6b59SJacob Faibussowitsch Not Collective 464030f984aSJacob Faibussowitsch 465030f984aSJacob Faibussowitsch Input Parameters: 466811af0c4SBarry Smith + dctxa - The `PetscDeviceContext` object that is waiting 467811af0c4SBarry Smith - dctxb - The `PetscDeviceContext` object that is being waited on 468030f984aSJacob Faibussowitsch 469030f984aSJacob Faibussowitsch Notes: 4700e6b6b59SJacob Faibussowitsch Serializes two `PetscDeviceContext`s. Serialization is performed asynchronously; the host 4710e6b6b59SJacob Faibussowitsch does not wait for the serialization to actually occur. 472811af0c4SBarry Smith 4730e6b6b59SJacob Faibussowitsch This routine uses only the state of `dctxb` at the moment this routine was called, so any 4740e6b6b59SJacob Faibussowitsch future work queued will not affect `dctxa`. It is safe to pass the same context to both 4750e6b6b59SJacob Faibussowitsch arguments (in which case this routine does nothing). 4760e6b6b59SJacob Faibussowitsch 4770e6b6b59SJacob Faibussowitsch DAG representation: 4780e6b6b59SJacob Faibussowitsch .vb 4790e6b6b59SJacob Faibussowitsch time -> 4800e6b6b59SJacob Faibussowitsch 4810e6b6b59SJacob Faibussowitsch -> dctxa ---/- |= CALL =| - dctxa -> 4820e6b6b59SJacob Faibussowitsch / 4830e6b6b59SJacob Faibussowitsch -> dctxb -/------------------------> 4840e6b6b59SJacob Faibussowitsch .ve 485030f984aSJacob Faibussowitsch 486030f984aSJacob Faibussowitsch Level: beginner 487030f984aSJacob Faibussowitsch 4880e6b6b59SJacob Faibussowitsch .N ASYNC_API 4890e6b6b59SJacob Faibussowitsch 490db781477SPatrick Sanan .seealso: `PetscDeviceContextCreate()`, `PetscDeviceContextQueryIdle()`, `PetscDeviceContextJoin()` 491030f984aSJacob Faibussowitsch @*/ 4929371c9d4SSatish Balay PetscErrorCode PetscDeviceContextWaitForContext(PetscDeviceContext dctxa, PetscDeviceContext dctxb) { 4930e6b6b59SJacob Faibussowitsch PetscObject aobj; 4940e6b6b59SJacob Faibussowitsch 495030f984aSJacob Faibussowitsch PetscFunctionBegin; 4960e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextGetOptionalNullContext_Internal(&dctxa)); 4970e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextGetOptionalNullContext_Internal(&dctxb)); 498030f984aSJacob Faibussowitsch PetscCheckCompatibleDeviceContexts(dctxa, 1, dctxb, 2); 499030f984aSJacob Faibussowitsch if (dctxa == dctxb) PetscFunctionReturn(0); 5000e6b6b59SJacob Faibussowitsch aobj = PetscObjectCast(dctxa); 501*6a4a1270SPierre Jolivet PetscCall(PetscLogEventBegin(DCONTEXT_WaitForCtx, dctxa, dctxb, nullptr, nullptr)); 502dbbe0bcdSBarry Smith PetscUseTypeMethod(dctxa, waitforcontext, dctxb); 5030e6b6b59SJacob Faibussowitsch PetscCallCXX(CxxDataCast(dctxa)->upstream[dctxb] = CxxData::parent_type(dctxb)); 504*6a4a1270SPierre Jolivet PetscCall(PetscLogEventEnd(DCONTEXT_WaitForCtx, dctxa, dctxb, nullptr, nullptr)); 5050e6b6b59SJacob Faibussowitsch PetscCall(PetscInfo(dctxa, "dctx %" PetscInt64_FMT " waiting on dctx %" PetscInt64_FMT "\n", aobj->id, PetscObjectCast(dctxb)->id)); 5060e6b6b59SJacob Faibussowitsch PetscCall(PetscObjectStateIncrease(aobj)); 507030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 508030f984aSJacob Faibussowitsch } 509030f984aSJacob Faibussowitsch 5100e6b6b59SJacob Faibussowitsch /*@C 5110e6b6b59SJacob Faibussowitsch PetscDeviceContextForkWithStreamType - Create a set of dependent child contexts from a parent 5120e6b6b59SJacob Faibussowitsch context with a prescribed `PetscStreamType` 5130e6b6b59SJacob Faibussowitsch 5140e6b6b59SJacob Faibussowitsch Not Collective, Asynchronous 5150e6b6b59SJacob Faibussowitsch 5160e6b6b59SJacob Faibussowitsch Input Parameters: 5170e6b6b59SJacob Faibussowitsch + dctx - The parent `PetscDeviceContext` 5180e6b6b59SJacob Faibussowitsch . stype - The prescribed `PetscStreamType` 5190e6b6b59SJacob Faibussowitsch - n - The number of children to create 5200e6b6b59SJacob Faibussowitsch 5210e6b6b59SJacob Faibussowitsch Output Parameter: 5220e6b6b59SJacob Faibussowitsch . dsub - The created child context(s) 5230e6b6b59SJacob Faibussowitsch 5240e6b6b59SJacob Faibussowitsch Notes: 5250e6b6b59SJacob Faibussowitsch This routine creates `n` edges of a DAG from a source node which are causally dependent on the 5260e6b6b59SJacob Faibussowitsch source node. This causal dependency is established as-if by calling 5270e6b6b59SJacob Faibussowitsch `PetscDeviceContextWaitForContext()` on every child. 5280e6b6b59SJacob Faibussowitsch 5290e6b6b59SJacob Faibussowitsch `dsub` is allocated by this routine and has its lifetime bounded by `dctx`. That is, `dctx` 5300e6b6b59SJacob Faibussowitsch expects to free `dsub` (via `PetscDeviceContextJoin()`) before it itself is destroyed. 5310e6b6b59SJacob Faibussowitsch 5320e6b6b59SJacob Faibussowitsch This routine only accounts for work queued on `dctx` up until calling this routine, any 5330e6b6b59SJacob Faibussowitsch subsequent work enqueued on `dctx` has no effect on `dsub`. 5340e6b6b59SJacob Faibussowitsch 5350e6b6b59SJacob Faibussowitsch The `PetscStreamType` of `dctx` does not have to equal `stype`. In fact, it is often the case 5360e6b6b59SJacob Faibussowitsch that they are different. This is useful in cases where a routine can locally exploit stream 5370e6b6b59SJacob Faibussowitsch parallelism without needing to worry about what stream type the incoming `PetscDeviceContext` 5380e6b6b59SJacob Faibussowitsch carries. 5390e6b6b59SJacob Faibussowitsch 5400e6b6b59SJacob Faibussowitsch DAG representation: 5410e6b6b59SJacob Faibussowitsch .vb 5420e6b6b59SJacob Faibussowitsch time -> 5430e6b6b59SJacob Faibussowitsch 5440e6b6b59SJacob Faibussowitsch -> dctx - |= CALL =| -\----> dctx ------> 5450e6b6b59SJacob Faibussowitsch \---> dsub[0] ---> 5460e6b6b59SJacob Faibussowitsch \--> ... -------> 5470e6b6b59SJacob Faibussowitsch \-> dsub[n-1] -> 5480e6b6b59SJacob Faibussowitsch .ve 5490e6b6b59SJacob Faibussowitsch 5500e6b6b59SJacob Faibussowitsch Level: intermediate 5510e6b6b59SJacob Faibussowitsch 5520e6b6b59SJacob Faibussowitsch .N ASYNC_API 5530e6b6b59SJacob Faibussowitsch 5540e6b6b59SJacob Faibussowitsch .seealso: `PetscDeviceContextJoin()`, `PetscDeviceContextSynchronize()`, 5550e6b6b59SJacob Faibussowitsch `PetscDeviceContextQueryIdle()`, `PetscDeviceContextWaitForContext()` 5560e6b6b59SJacob Faibussowitsch @*/ 5570e6b6b59SJacob Faibussowitsch PetscErrorCode PetscDeviceContextForkWithStreamType(PetscDeviceContext dctx, PetscStreamType stype, PetscInt n, PetscDeviceContext **dsub) { 5580e6b6b59SJacob Faibussowitsch // debugging only 5590e6b6b59SJacob Faibussowitsch std::string idList; 5600e6b6b59SJacob Faibussowitsch auto ninput = n; 5610e6b6b59SJacob Faibussowitsch 5620e6b6b59SJacob Faibussowitsch PetscFunctionBegin; 5630e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextGetOptionalNullContext_Internal(&dctx)); 5640e6b6b59SJacob Faibussowitsch PetscAssert(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of contexts requested %" PetscInt_FMT " < 0", n); 5650e6b6b59SJacob Faibussowitsch PetscValidPointer(dsub, 4); 5660e6b6b59SJacob Faibussowitsch *dsub = nullptr; 5670e6b6b59SJacob Faibussowitsch /* reserve 4 chars per id, 2 for number and 2 for ', ' separator */ 5680e6b6b59SJacob Faibussowitsch if (PetscDefined(USE_DEBUG_AND_INFO)) PetscCallCXX(idList.reserve(4 * n)); 569*6a4a1270SPierre Jolivet PetscCall(PetscLogEventBegin(DCONTEXT_Fork, dctx, nullptr, nullptr, nullptr)); 5700e6b6b59SJacob Faibussowitsch /* update child totals */ 5710e6b6b59SJacob Faibussowitsch dctx->numChildren += n; 5720e6b6b59SJacob Faibussowitsch /* now to find out if we have room */ 5730e6b6b59SJacob Faibussowitsch if (dctx->numChildren > dctx->maxNumChildren) { 5740e6b6b59SJacob Faibussowitsch const auto numChildren = dctx->numChildren; 5750e6b6b59SJacob Faibussowitsch auto &maxNumChildren = dctx->maxNumChildren; 5760e6b6b59SJacob Faibussowitsch auto numAllocated = numChildren; 5770e6b6b59SJacob Faibussowitsch 5780e6b6b59SJacob Faibussowitsch /* no room, either from having too many kids or not having any */ 5790e6b6b59SJacob Faibussowitsch if (auto &childIDs = dctx->childIDs) { 5800e6b6b59SJacob Faibussowitsch // the difference is backwards because we have not updated maxNumChildren yet 5810e6b6b59SJacob Faibussowitsch numAllocated -= maxNumChildren; 5820e6b6b59SJacob Faibussowitsch /* have existing children, must reallocate them */ 5830e6b6b59SJacob Faibussowitsch PetscCall(PetscRealloc(numChildren * sizeof(*childIDs), &childIDs)); 5840e6b6b59SJacob Faibussowitsch /* clear the extra memory since realloc doesn't do it for us */ 5850e6b6b59SJacob Faibussowitsch PetscCall(PetscArrayzero(std::next(childIDs, maxNumChildren), numAllocated)); 5860e6b6b59SJacob Faibussowitsch } else { 5870e6b6b59SJacob Faibussowitsch /* have no children */ 5880e6b6b59SJacob Faibussowitsch PetscCall(PetscCalloc1(numChildren, &childIDs)); 5890e6b6b59SJacob Faibussowitsch } 5900e6b6b59SJacob Faibussowitsch /* update total number of children */ 5910e6b6b59SJacob Faibussowitsch maxNumChildren = numChildren; 5920e6b6b59SJacob Faibussowitsch PetscCall(PetscLogObjectMemory(PetscObjectCast(dctx), numAllocated * sizeof(*(dctx->childIDs)))); 5930e6b6b59SJacob Faibussowitsch } 5940e6b6b59SJacob Faibussowitsch PetscCall(PetscMalloc1(n, dsub)); 5950e6b6b59SJacob Faibussowitsch PetscCall(PetscLogObjectMemory(PetscObjectCast(dctx), n * sizeof(*dsub))); 5960e6b6b59SJacob Faibussowitsch for (PetscInt i = 0; ninput && (i < dctx->numChildren); ++i) { 5970e6b6b59SJacob Faibussowitsch auto &childID = dctx->childIDs[i]; 5980e6b6b59SJacob Faibussowitsch /* empty child slot */ 5990e6b6b59SJacob Faibussowitsch if (!childID) { 6000e6b6b59SJacob Faibussowitsch auto &childctx = (*dsub)[i]; 6010e6b6b59SJacob Faibussowitsch 6020e6b6b59SJacob Faibussowitsch /* create the child context in the image of its parent */ 6030e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextDuplicate_Private(dctx, stype, &childctx)); 6040e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextWaitForContext(childctx, dctx)); 6050e6b6b59SJacob Faibussowitsch /* register the child with its parent */ 6060e6b6b59SJacob Faibussowitsch PetscCall(PetscObjectGetId(PetscObjectCast(childctx), &childID)); 6070e6b6b59SJacob Faibussowitsch if (PetscDefined(USE_DEBUG_AND_INFO)) { 6080e6b6b59SJacob Faibussowitsch PetscCallCXX(idList += std::to_string(childID)); 6090e6b6b59SJacob Faibussowitsch if (ninput != 1) PetscCallCXX(idList += ", "); 6100e6b6b59SJacob Faibussowitsch } 6110e6b6b59SJacob Faibussowitsch --ninput; 6120e6b6b59SJacob Faibussowitsch } 6130e6b6b59SJacob Faibussowitsch } 614*6a4a1270SPierre Jolivet PetscCall(PetscLogEventEnd(DCONTEXT_Fork, dctx, nullptr, nullptr, nullptr)); 6150e6b6b59SJacob Faibussowitsch PetscCall(PetscDebugInfo(dctx, "Forked %" PetscInt_FMT " children from parent %" PetscInt64_FMT " with IDs: %s\n", n, PetscObjectCast(dctx)->id, idList.c_str())); 6160e6b6b59SJacob Faibussowitsch PetscFunctionReturn(0); 6170e6b6b59SJacob Faibussowitsch } 6180e6b6b59SJacob Faibussowitsch 619030f984aSJacob Faibussowitsch /*@C 620030f984aSJacob Faibussowitsch PetscDeviceContextFork - Create a set of dependent child contexts from a parent context 621030f984aSJacob Faibussowitsch 622030f984aSJacob Faibussowitsch Not Collective, Asynchronous 623030f984aSJacob Faibussowitsch 624030f984aSJacob Faibussowitsch Input Parameters: 625811af0c4SBarry Smith + dctx - The parent `PetscDeviceContext` 626030f984aSJacob Faibussowitsch - n - The number of children to create 627030f984aSJacob Faibussowitsch 628030f984aSJacob Faibussowitsch Output Parameter: 629030f984aSJacob Faibussowitsch . dsub - The created child context(s) 630030f984aSJacob Faibussowitsch 631030f984aSJacob Faibussowitsch Notes: 6320e6b6b59SJacob Faibussowitsch Behaves identically to `PetscDeviceContextForkWithStreamType()` except that the prescribed 6330e6b6b59SJacob Faibussowitsch `PetscStreamType` is taken from `dctx`. In effect this routine is shorthand for\: 634030f984aSJacob Faibussowitsch 635030f984aSJacob Faibussowitsch .vb 6360e6b6b59SJacob Faibussowitsch PetscStreamType stype; 637030f984aSJacob Faibussowitsch 6380e6b6b59SJacob Faibussowitsch PetscDeviceContextGetStreamType(dctx, &stype); 6390e6b6b59SJacob Faibussowitsch PetscDeviceContextForkWithStreamType(dctx, stype, ...); 640030f984aSJacob Faibussowitsch .ve 641030f984aSJacob Faibussowitsch 6420e6b6b59SJacob Faibussowitsch Level: beginner 643030f984aSJacob Faibussowitsch 6440e6b6b59SJacob Faibussowitsch .N ASYNC_API 6450e6b6b59SJacob Faibussowitsch 6460e6b6b59SJacob Faibussowitsch .seealso: `PetscDeviceContextForkWithStreamType()`, `PetscDeviceContextJoin()`, 6470e6b6b59SJacob Faibussowitsch `PetscDeviceContextSynchronize()`, `PetscDeviceContextQueryIdle()` 648030f984aSJacob Faibussowitsch @*/ 6499371c9d4SSatish Balay PetscErrorCode PetscDeviceContextFork(PetscDeviceContext dctx, PetscInt n, PetscDeviceContext **dsub) { 6500e6b6b59SJacob Faibussowitsch auto stype = PETSC_STREAM_DEFAULT_BLOCKING; 651030f984aSJacob Faibussowitsch 652030f984aSJacob Faibussowitsch PetscFunctionBegin; 6530e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextGetOptionalNullContext_Internal(&dctx)); 6540e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextGetStreamType(dctx, &stype)); 6550e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextForkWithStreamType(dctx, stype, n, dsub)); 656030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 657030f984aSJacob Faibussowitsch } 658030f984aSJacob Faibussowitsch 659030f984aSJacob Faibussowitsch /*@C 6605181c4f9SJacob Faibussowitsch PetscDeviceContextJoin - Converge a set of child contexts 661030f984aSJacob Faibussowitsch 662030f984aSJacob Faibussowitsch Not Collective, Asynchronous 663030f984aSJacob Faibussowitsch 664030f984aSJacob Faibussowitsch Input Parameters: 665811af0c4SBarry Smith + dctx - A `PetscDeviceContext` to converge on 666030f984aSJacob Faibussowitsch . n - The number of sub contexts to converge 667030f984aSJacob Faibussowitsch . joinMode - The type of join to perform 668030f984aSJacob Faibussowitsch - dsub - The sub contexts to converge 669030f984aSJacob Faibussowitsch 670030f984aSJacob Faibussowitsch Notes: 6710e6b6b59SJacob Faibussowitsch If `PetscDeviceContextFork()` creates `n` edges from a source node which all depend on the source 6720e6b6b59SJacob Faibussowitsch node, then this routine is the exact mirror. That is, it creates a node (represented in `dctx`) 6730e6b6b59SJacob Faibussowitsch which recieves `n` edges (and optionally destroys them) which is dependent on the completion 6740e6b6b59SJacob Faibussowitsch of all incoming edges. 675030f984aSJacob Faibussowitsch 6760e6b6b59SJacob Faibussowitsch If `joinMode` is `PETSC_DEVICE_CONTEXT_JOIN_DESTROY`. All contexts in `dsub` will be 6770e6b6b59SJacob Faibussowitsch destroyed by this routine. Thus all sub contexts must have been created with the `dctx` 6780e6b6b59SJacob Faibussowitsch passed to this routine. 679030f984aSJacob Faibussowitsch 6800e6b6b59SJacob Faibussowitsch If `joinMode` is `PETSC_DEVICE_CONTEXT_JOIN_SYNC`. All sub contexts will additionally wait on 6810e6b6b59SJacob Faibussowitsch `dctx` after converging. This has the effect of "synchronizing" the outgoing edges. Note the 6820e6b6b59SJacob Faibussowitsch sync suffix does NOT refer to the host, i.e. this routine does NOT call 6830e6b6b59SJacob Faibussowitsch `PetscDeviceSynchronize()`. 684030f984aSJacob Faibussowitsch 6850e6b6b59SJacob Faibussowitsch If `joinMode` is `PETSC_DEVICE_CONTEXT_JOIN_NO_SYNC`. `dctx` waits for all sub contexts but 6860e6b6b59SJacob Faibussowitsch the sub contexts do not wait for one another or `dctx` afterwards. 687030f984aSJacob Faibussowitsch 688030f984aSJacob Faibussowitsch DAG representations: 689811af0c4SBarry Smith If `joinMode` is `PETSC_DEVICE_CONTEXT_JOIN_DESTROY` 690030f984aSJacob Faibussowitsch .vb 691030f984aSJacob Faibussowitsch time -> 692030f984aSJacob Faibussowitsch 6930e6b6b59SJacob Faibussowitsch -> dctx ---------/- |= CALL =| - dctx -> 694030f984aSJacob Faibussowitsch -> dsub[0] -----/ 695030f984aSJacob Faibussowitsch -> ... -------/ 696030f984aSJacob Faibussowitsch -> dsub[n-1] -/ 697030f984aSJacob Faibussowitsch .ve 698811af0c4SBarry Smith If `joinMode` is `PETSC_DEVICE_CONTEXT_JOIN_SYNC` 699030f984aSJacob Faibussowitsch .vb 700030f984aSJacob Faibussowitsch time -> 701030f984aSJacob Faibussowitsch 7020e6b6b59SJacob Faibussowitsch -> dctx ---------/- |= CALL =| -\----> dctx ------> 703030f984aSJacob Faibussowitsch -> dsub[0] -----/ \---> dsub[0] ---> 704030f984aSJacob Faibussowitsch -> ... -------/ \--> ... -------> 705030f984aSJacob Faibussowitsch -> dsub[n-1] -/ \-> dsub[n-1] -> 706030f984aSJacob Faibussowitsch .ve 7070e6b6b59SJacob Faibussowitsch If `joinMode` is `PETSC_DEVICE_CONTEXT_JOIN_NO_SYNC` 7080e6b6b59SJacob Faibussowitsch .vb 7090e6b6b59SJacob Faibussowitsch time -> 710030f984aSJacob Faibussowitsch 7110e6b6b59SJacob Faibussowitsch -> dctx ----------/- |= CALL =| - dctx -> 7120e6b6b59SJacob Faibussowitsch -> dsub[0] ------/-----------------------> 7130e6b6b59SJacob Faibussowitsch -> ... --------/------------------------> 7140e6b6b59SJacob Faibussowitsch -> dsub[n-1] --/-------------------------> 7150e6b6b59SJacob Faibussowitsch .ve 716030f984aSJacob Faibussowitsch 7170e6b6b59SJacob Faibussowitsch Level: beginner 7180e6b6b59SJacob Faibussowitsch 7190e6b6b59SJacob Faibussowitsch .N ASYNC_API 7200e6b6b59SJacob Faibussowitsch 7210e6b6b59SJacob Faibussowitsch .seealso: `PetscDeviceContextFork()`, `PetscDeviceContextForkWithStreamType()`, 7220e6b6b59SJacob Faibussowitsch `PetscDeviceContextSynchronize()`, `PetscDeviceContextJoinMode` 723030f984aSJacob Faibussowitsch @*/ 7249371c9d4SSatish Balay PetscErrorCode PetscDeviceContextJoin(PetscDeviceContext dctx, PetscInt n, PetscDeviceContextJoinMode joinMode, PetscDeviceContext **dsub) { 7250e6b6b59SJacob Faibussowitsch // debugging only 7260e6b6b59SJacob Faibussowitsch std::string idList; 727030f984aSJacob Faibussowitsch 728030f984aSJacob Faibussowitsch PetscFunctionBegin; 7290e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextGetOptionalNullContext_Internal(&dctx)); 730030f984aSJacob Faibussowitsch /* validity of dctx is checked in the wait-for loop */ 731030f984aSJacob Faibussowitsch PetscValidPointer(dsub, 4); 732bf025ffbSJacob Faibussowitsch PetscAssert(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of contexts merged %" PetscInt_FMT " < 0", n); 733030f984aSJacob Faibussowitsch /* reserve 4 chars per id, 2 for number and 2 for ', ' separator */ 7340e6b6b59SJacob Faibussowitsch if (PetscDefined(USE_DEBUG_AND_INFO)) PetscCallCXX(idList.reserve(4 * n)); 735030f984aSJacob Faibussowitsch /* first dctx waits on all the incoming edges */ 736*6a4a1270SPierre Jolivet PetscCall(PetscLogEventBegin(DCONTEXT_Join, dctx, nullptr, nullptr, nullptr)); 737030f984aSJacob Faibussowitsch for (PetscInt i = 0; i < n; ++i) { 738030f984aSJacob Faibussowitsch PetscCheckCompatibleDeviceContexts(dctx, 1, (*dsub)[i], 4); 7399566063dSJacob Faibussowitsch PetscCall(PetscDeviceContextWaitForContext(dctx, (*dsub)[i])); 7400e6b6b59SJacob Faibussowitsch if (PetscDefined(USE_DEBUG_AND_INFO)) { 7410e6b6b59SJacob Faibussowitsch PetscCallCXX(idList += std::to_string(PetscObjectCast((*dsub)[i])->id)); 7420e6b6b59SJacob Faibussowitsch if (i + 1 < n) PetscCallCXX(idList += ", "); 7430e6b6b59SJacob Faibussowitsch } 744030f984aSJacob Faibussowitsch } 745030f984aSJacob Faibussowitsch 746030f984aSJacob Faibussowitsch /* now we handle the aftermath */ 747030f984aSJacob Faibussowitsch switch (joinMode) { 7489371c9d4SSatish Balay case PETSC_DEVICE_CONTEXT_JOIN_DESTROY: { 7490e6b6b59SJacob Faibussowitsch const auto children = dctx->childIDs; 7500e6b6b59SJacob Faibussowitsch const auto maxchild = dctx->maxNumChildren; 7510e6b6b59SJacob Faibussowitsch auto &nchild = dctx->numChildren; 752030f984aSJacob Faibussowitsch PetscInt j = 0; 753030f984aSJacob Faibussowitsch 7540e6b6b59SJacob Faibussowitsch PetscCheck(n <= nchild, 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, nchild); 755030f984aSJacob Faibussowitsch /* update child count while it's still fresh in memory */ 7560e6b6b59SJacob Faibussowitsch nchild -= n; 7570e6b6b59SJacob Faibussowitsch for (PetscInt i = 0; i < maxchild; ++i) { 7580e6b6b59SJacob Faibussowitsch if (children[i] && (children[i] == PetscObjectCast((*dsub)[j])->id)) { 759030f984aSJacob Faibussowitsch /* child is one of ours, can destroy it */ 7609566063dSJacob Faibussowitsch PetscCall(PetscDeviceContextDestroy((*dsub) + j)); 761030f984aSJacob Faibussowitsch /* reset the child slot */ 7620e6b6b59SJacob Faibussowitsch children[i] = 0; 763030f984aSJacob Faibussowitsch if (++j == n) break; 764030f984aSJacob Faibussowitsch } 765030f984aSJacob Faibussowitsch } 7660e6b6b59SJacob Faibussowitsch /* gone through the loop but did not find every child */ 7670e6b6b59SJacob Faibussowitsch PetscCheck(j == n, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "%" PetscInt_FMT " contexts still remain after destroy, this may be because you are trying to restore to the wrong parent context, or the device contexts are not in the same order as they were checked out out in", n - j); 7689566063dSJacob Faibussowitsch PetscCall(PetscFree(*dsub)); 7690e6b6b59SJacob Faibussowitsch PetscCall(PetscLogObjectMemory(PetscObjectCast(dctx), -n * sizeof(*dsub))); 7709371c9d4SSatish Balay } break; 771030f984aSJacob Faibussowitsch case PETSC_DEVICE_CONTEXT_JOIN_SYNC: 7729566063dSJacob Faibussowitsch for (PetscInt i = 0; i < n; ++i) PetscCall(PetscDeviceContextWaitForContext((*dsub)[i], dctx)); 7739371c9d4SSatish Balay case PETSC_DEVICE_CONTEXT_JOIN_NO_SYNC: break; 7749371c9d4SSatish Balay default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown PetscDeviceContextJoinMode given"); 775030f984aSJacob Faibussowitsch } 776*6a4a1270SPierre Jolivet PetscCall(PetscLogEventEnd(DCONTEXT_Join, dctx, nullptr, nullptr, nullptr)); 777030f984aSJacob Faibussowitsch 7780e6b6b59SJacob Faibussowitsch PetscCall(PetscDebugInfo(dctx, "Joined %" PetscInt_FMT " ctxs to ctx %" PetscInt64_FMT ", mode %s with IDs: %s\n", n, PetscObjectCast(dctx)->id, PetscDeviceContextJoinModes[joinMode], idList.c_str())); 779030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 780030f984aSJacob Faibussowitsch } 781030f984aSJacob Faibussowitsch 782030f984aSJacob Faibussowitsch /*@C 7830e6b6b59SJacob Faibussowitsch PetscDeviceContextSynchronize - Block the host until all work queued on a 7840e6b6b59SJacob Faibussowitsch `PetscDeviceContext` has finished 785030f984aSJacob Faibussowitsch 7860e6b6b59SJacob Faibussowitsch Not Collective 787030f984aSJacob Faibussowitsch 788030f984aSJacob Faibussowitsch Input Parameters: 789811af0c4SBarry Smith . dctx - The `PetscDeviceContext` to synchronize 790030f984aSJacob Faibussowitsch 7910e6b6b59SJacob Faibussowitsch Notes: 7920e6b6b59SJacob Faibussowitsch The host will not return from this routine until `dctx` is idle. Any and all memory 7930e6b6b59SJacob Faibussowitsch operations queued on or otherwise associated with (either explicitly or implicitly via 7940e6b6b59SJacob Faibussowitsch dependencies) are guaranteed to have finished and be globally visible on return. 7950e6b6b59SJacob Faibussowitsch 7960e6b6b59SJacob Faibussowitsch In effect, this routine serves as memory and execution barrier. 7970e6b6b59SJacob Faibussowitsch 7980e6b6b59SJacob Faibussowitsch DAG representation: 7990e6b6b59SJacob Faibussowitsch .vb 8000e6b6b59SJacob Faibussowitsch time -> 8010e6b6b59SJacob Faibussowitsch 8020e6b6b59SJacob Faibussowitsch -> dctx - |= CALL =| - dctx -> 8030e6b6b59SJacob Faibussowitsch .ve 8040e6b6b59SJacob Faibussowitsch 805030f984aSJacob Faibussowitsch Level: beginner 806030f984aSJacob Faibussowitsch 807db781477SPatrick Sanan .seealso: `PetscDeviceContextFork()`, `PetscDeviceContextJoin()`, `PetscDeviceContextQueryIdle()` 808030f984aSJacob Faibussowitsch @*/ 8099371c9d4SSatish Balay PetscErrorCode PetscDeviceContextSynchronize(PetscDeviceContext dctx) { 810030f984aSJacob Faibussowitsch PetscFunctionBegin; 8110e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextGetOptionalNullContext_Internal(&dctx)); 812*6a4a1270SPierre Jolivet PetscCall(PetscLogEventBegin(DCONTEXT_Sync, dctx, nullptr, nullptr, nullptr)); 813030f984aSJacob Faibussowitsch /* if it isn't setup there is nothing to sync on */ 8140e6b6b59SJacob Faibussowitsch if (dctx->setup) { 8150e6b6b59SJacob Faibussowitsch PetscCall((*dctx->ops->synchronize)(dctx)); 8160e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextSyncClearMap_Internal(dctx)); 8170e6b6b59SJacob Faibussowitsch } 818*6a4a1270SPierre Jolivet PetscCall(PetscLogEventEnd(DCONTEXT_Sync, dctx, nullptr, nullptr, nullptr)); 819030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 820030f984aSJacob Faibussowitsch } 821030f984aSJacob Faibussowitsch 8220e6b6b59SJacob Faibussowitsch /* every device type has a vector of null PetscDeviceContexts -- one for each device */ 8230e6b6b59SJacob Faibussowitsch static auto nullContexts = std::array<std::vector<PetscDeviceContext>, PETSC_DEVICE_MAX>{}; 8240e6b6b59SJacob Faibussowitsch static auto nullContextsFinalizer = false; 825030f984aSJacob Faibussowitsch 8260e6b6b59SJacob Faibussowitsch static PetscErrorCode PetscDeviceContextGetNullContextForDevice_Private(PetscBool user_set_device, PetscDevice device, PetscDeviceContext *dctx) { 8270e6b6b59SJacob Faibussowitsch PetscInt devid; 8280e6b6b59SJacob Faibussowitsch PetscDeviceType dtype; 829a4af0ceeSJacob Faibussowitsch 830030f984aSJacob Faibussowitsch PetscFunctionBegin; 8310e6b6b59SJacob Faibussowitsch PetscValidDevice(device, 2); 8320e6b6b59SJacob Faibussowitsch PetscValidPointer(dctx, 3); 8330e6b6b59SJacob Faibussowitsch if (PetscUnlikely(!nullContextsFinalizer)) { 8340e6b6b59SJacob Faibussowitsch const auto finalizer = [] { 8350e6b6b59SJacob Faibussowitsch PetscFunctionBegin; 8360e6b6b59SJacob Faibussowitsch for (auto &&dvec : nullContexts) { 8370e6b6b59SJacob Faibussowitsch for (auto &&dctx : dvec) PetscCall(PetscDeviceContextDestroy(&dctx)); 8380e6b6b59SJacob Faibussowitsch PetscCallCXX(dvec.clear()); 839030f984aSJacob Faibussowitsch } 8400e6b6b59SJacob Faibussowitsch nullContextsFinalizer = false; 841a4af0ceeSJacob Faibussowitsch PetscFunctionReturn(0); 842a4af0ceeSJacob Faibussowitsch }; 843a4af0ceeSJacob Faibussowitsch 8440e6b6b59SJacob Faibussowitsch nullContextsFinalizer = true; 8450e6b6b59SJacob Faibussowitsch PetscCall(PetscRegisterFinalize(std::move(finalizer))); 8460e6b6b59SJacob Faibussowitsch } 8470e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceGetDeviceId(device, &devid)); 8480e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceGetType(device, &dtype)); 8490e6b6b59SJacob Faibussowitsch { 8500e6b6b59SJacob Faibussowitsch auto &ctxlist = nullContexts[dtype]; 8510e6b6b59SJacob Faibussowitsch 8520e6b6b59SJacob Faibussowitsch PetscCheck(devid >= 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Device ID (%" PetscInt_FMT ") must be positive", devid); 8530e6b6b59SJacob Faibussowitsch // need to resize the container if not big enough because incrementing the iterator in 8540e6b6b59SJacob Faibussowitsch // std::next() (if we haven't initialized that ctx yet) may cause it to fall outside the 8550e6b6b59SJacob Faibussowitsch // current size of the container. 8560e6b6b59SJacob Faibussowitsch if (static_cast<std::size_t>(devid) >= ctxlist.size()) PetscCallCXX(ctxlist.resize(devid + 1)); 8570e6b6b59SJacob Faibussowitsch if (PetscUnlikely(!ctxlist[devid])) { 8580e6b6b59SJacob Faibussowitsch // we have not seen this device before 8590e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextCreate(dctx)); 8600e6b6b59SJacob Faibussowitsch PetscCall(PetscInfo(dctx, "Initializing null PetscDeviceContext (of type %s) for device %" PetscInt_FMT "\n", PetscDeviceTypes[dtype], devid)); 8610e6b6b59SJacob Faibussowitsch { 8620e6b6b59SJacob Faibussowitsch const auto pobj = PetscObjectCast(*dctx); 8630e6b6b59SJacob Faibussowitsch const auto name = "null context " + std::to_string(devid); 8640e6b6b59SJacob Faibussowitsch const auto prefix = "null_context_" + std::to_string(devid) + '_'; 8650e6b6b59SJacob Faibussowitsch 8660e6b6b59SJacob Faibussowitsch PetscCall(PetscObjectSetName(pobj, name.c_str())); 8670e6b6b59SJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix(pobj, prefix.c_str())); 8680e6b6b59SJacob Faibussowitsch } 8690e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextSetStreamType(*dctx, PETSC_STREAM_GLOBAL_BLOCKING)); 8700e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextSetDevice_Private(*dctx, device, user_set_device)); 8710e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextSetUp(*dctx)); 8720e6b6b59SJacob Faibussowitsch // would use ctxlist.cbegin() but GCC 4.8 can't handle const iterator insert! 8730e6b6b59SJacob Faibussowitsch PetscCallCXX(ctxlist.insert(std::next(ctxlist.begin(), devid), *dctx)); 8740e6b6b59SJacob Faibussowitsch } else *dctx = ctxlist[devid]; 8750e6b6b59SJacob Faibussowitsch } 876030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 877030f984aSJacob Faibussowitsch } 878030f984aSJacob Faibussowitsch 8790e6b6b59SJacob Faibussowitsch /* 8800e6b6b59SJacob Faibussowitsch Gets the "NULL" context for the current PetscDeviceType and PetscDevice. NULL contexts are 8810e6b6b59SJacob Faibussowitsch guaranteed to always be globally blocking. 8820e6b6b59SJacob Faibussowitsch */ 8830e6b6b59SJacob Faibussowitsch PetscErrorCode PetscDeviceContextGetNullContext_Internal(PetscDeviceContext *dctx) { 8840e6b6b59SJacob Faibussowitsch PetscDeviceContext gctx; 8850e6b6b59SJacob Faibussowitsch PetscDevice gdev = nullptr; 886030f984aSJacob Faibussowitsch 887a4af0ceeSJacob Faibussowitsch PetscFunctionBegin; 888a4af0ceeSJacob Faibussowitsch PetscValidPointer(dctx, 1); 8890e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextGetCurrentContext(&gctx)); 8900e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextGetDevice(gctx, &gdev)); 8910e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextGetNullContextForDevice_Private(gctx->usersetdevice, gdev, dctx)); 892030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 893030f984aSJacob Faibussowitsch } 894030f984aSJacob Faibussowitsch 895030f984aSJacob Faibussowitsch /*@C 896811af0c4SBarry Smith PetscDeviceContextSetFromOptions - Configure a `PetscDeviceContext` from the options database 897030f984aSJacob Faibussowitsch 8980e6b6b59SJacob Faibussowitsch Collective on `comm` or `dctx` 899030f984aSJacob Faibussowitsch 900030f984aSJacob Faibussowitsch Input Parameters: 9010e6b6b59SJacob Faibussowitsch + comm - MPI communicator on which to query the options database (optional) 902811af0c4SBarry Smith - dctx - The `PetscDeviceContext` to configure 903030f984aSJacob Faibussowitsch 904030f984aSJacob Faibussowitsch Output Parameter: 905811af0c4SBarry Smith . dctx - The `PetscDeviceContext` 906030f984aSJacob Faibussowitsch 9070e6b6b59SJacob Faibussowitsch Options Database: 9080e6b6b59SJacob Faibussowitsch + -device_context_stream_type - type of stream to create inside the `PetscDeviceContext` - 9090e6b6b59SJacob Faibussowitsch `PetscDeviceContextSetStreamType()` 910811af0c4SBarry Smith - -device_context_device_type - the type of `PetscDevice` to attach by default - `PetscDeviceType` 911030f984aSJacob Faibussowitsch 9120e6b6b59SJacob Faibussowitsch Notes: 9130e6b6b59SJacob Faibussowitsch The user may pass `MPI_COMM_NULL` for `comm` in which case the communicator of `dctx` is 9140e6b6b59SJacob Faibussowitsch used (which is always `PETSC_COMM_SELF`). 9150e6b6b59SJacob Faibussowitsch 916030f984aSJacob Faibussowitsch Level: beginner 917030f984aSJacob Faibussowitsch 9180e6b6b59SJacob Faibussowitsch .seealso: `PetscDeviceContextSetStreamType()`, `PetscDeviceContextSetDevice()`, 9190e6b6b59SJacob Faibussowitsch `PetscDeviceContextView()` 920030f984aSJacob Faibussowitsch @*/ 9210e6b6b59SJacob Faibussowitsch PetscErrorCode PetscDeviceContextSetFromOptions(MPI_Comm comm, PetscDeviceContext dctx) { 9220e6b6b59SJacob Faibussowitsch const auto pobj = PetscObjectCast(dctx); 9230e6b6b59SJacob Faibussowitsch auto dtype = std::make_pair(PETSC_DEVICE_DEFAULT(), PETSC_FALSE); 9240e6b6b59SJacob Faibussowitsch auto stype = std::make_pair(PETSC_DEVICE_CONTEXT_DEFAULT_STREAM_TYPE, PETSC_FALSE); 9250e6b6b59SJacob Faibussowitsch auto old_comm = PETSC_COMM_SELF; 926030f984aSJacob Faibussowitsch 927030f984aSJacob Faibussowitsch PetscFunctionBegin; 9280e6b6b59SJacob Faibussowitsch // do not user getoptionalnullcontext here, the user is not allowed to set it from options! 9290e6b6b59SJacob Faibussowitsch PetscValidDeviceContext(dctx, 2); 9300e6b6b59SJacob Faibussowitsch /* set the device type first */ 9310e6b6b59SJacob Faibussowitsch if (const auto device = dctx->device) PetscCall(PetscDeviceGetType(device, &dtype.first)); 9320e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextGetStreamType(dctx, &stype.first)); 9330e6b6b59SJacob Faibussowitsch 9340e6b6b59SJacob Faibussowitsch if (comm == MPI_COMM_NULL) { 9350e6b6b59SJacob Faibussowitsch PetscCall(PetscObjectGetComm(pobj, &comm)); 9360e6b6b59SJacob Faibussowitsch } else { 9370e6b6b59SJacob Faibussowitsch // briefly set the communicator for dctx (it is always PETSC_COMM_SELF) so 9380e6b6b59SJacob Faibussowitsch // PetscObjectOptionsBegin() behaves as if dctx had comm 9390e6b6b59SJacob Faibussowitsch old_comm = Petsc::util::exchange(pobj->comm, comm); 9400e6b6b59SJacob Faibussowitsch } 9410e6b6b59SJacob Faibussowitsch 9420e6b6b59SJacob Faibussowitsch PetscObjectOptionsBegin(pobj); 9430e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextQueryOptions_Internal(PetscOptionsObject, dtype, stype)); 944d0609cedSBarry Smith PetscOptionsEnd(); 9450e6b6b59SJacob Faibussowitsch // reset the comm (should be PETSC_COMM_SELF) 9460e6b6b59SJacob Faibussowitsch if (comm != MPI_COMM_NULL) pobj->comm = old_comm; 9470e6b6b59SJacob Faibussowitsch if (dtype.second) PetscCall(PetscDeviceContextSetDefaultDeviceForType_Internal(dctx, dtype.first)); 9480e6b6b59SJacob Faibussowitsch if (stype.second) PetscCall(PetscDeviceContextSetStreamType(dctx, stype.first)); 9490e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextSetUp(dctx)); 9500e6b6b59SJacob Faibussowitsch PetscFunctionReturn(0); 9510e6b6b59SJacob Faibussowitsch } 9520e6b6b59SJacob Faibussowitsch 9530e6b6b59SJacob Faibussowitsch /*@C 9540e6b6b59SJacob Faibussowitsch PetscDeviceContextView - View a `PetscDeviceContext` 9550e6b6b59SJacob Faibussowitsch 9560e6b6b59SJacob Faibussowitsch Collective on `viewer` 9570e6b6b59SJacob Faibussowitsch 9580e6b6b59SJacob Faibussowitsch Input Parameters: 9590e6b6b59SJacob Faibussowitsch + dctx - The `PetscDeviceContext` 9600e6b6b59SJacob Faibussowitsch - viewer - The `PetscViewer` to view `dctx` with (may be `NULL`) 9610e6b6b59SJacob Faibussowitsch 9620e6b6b59SJacob Faibussowitsch Notes: 9630e6b6b59SJacob Faibussowitsch If `viewer` is `NULL`, `PETSC_VIEWER_STDOUT_WORLD` is used instead, in which case this 9640e6b6b59SJacob Faibussowitsch routine is collective on `PETSC_COMM_WORLD`. 9650e6b6b59SJacob Faibussowitsch 9660e6b6b59SJacob Faibussowitsch Level: beginner 9670e6b6b59SJacob Faibussowitsch 9680e6b6b59SJacob Faibussowitsch .seealso: `PetscDeviceContextViewFromOptions()`, `PetscDeviceView()`, `PETSC_VIEWER_STDOUT_WORLD`, `PetscDeviceContextCreate()` 9690e6b6b59SJacob Faibussowitsch @*/ 9700e6b6b59SJacob Faibussowitsch PetscErrorCode PetscDeviceContextView(PetscDeviceContext dctx, PetscViewer viewer) { 9710e6b6b59SJacob Faibussowitsch PetscBool iascii; 9720e6b6b59SJacob Faibussowitsch 9730e6b6b59SJacob Faibussowitsch PetscFunctionBegin; 9740e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextGetOptionalNullContext_Internal(&dctx)); 9750e6b6b59SJacob Faibussowitsch if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PETSC_COMM_WORLD, &viewer)); 9760e6b6b59SJacob Faibussowitsch PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 9770e6b6b59SJacob Faibussowitsch PetscCall(PetscObjectTypeCompare(PetscObjectCast(viewer), PETSCVIEWERASCII, &iascii)); 9780e6b6b59SJacob Faibussowitsch if (iascii) { 9790e6b6b59SJacob Faibussowitsch auto stype = PETSC_STREAM_DEFAULT_BLOCKING; 9800e6b6b59SJacob Faibussowitsch PetscViewer sub; 9810e6b6b59SJacob Faibussowitsch 9820e6b6b59SJacob Faibussowitsch PetscCall(PetscViewerGetSubViewer(viewer, PETSC_COMM_SELF, &sub)); 9830e6b6b59SJacob Faibussowitsch PetscCall(PetscObjectPrintClassNamePrefixType(PetscObjectCast(dctx), sub)); 9840e6b6b59SJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(sub)); 9850e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextGetStreamType(dctx, &stype)); 9860e6b6b59SJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(sub, "stream type: %s\n", PetscStreamTypes[stype])); 9870e6b6b59SJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(sub, "children: %" PetscInt_FMT "\n", dctx->numChildren)); 9880e6b6b59SJacob Faibussowitsch if (const auto nchild = dctx->numChildren) { 9890e6b6b59SJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(sub)); 9900e6b6b59SJacob Faibussowitsch for (PetscInt i = 0; i < nchild; ++i) { 9910e6b6b59SJacob Faibussowitsch if (i == nchild - 1) { 9920e6b6b59SJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(sub, "%" PetscInt64_FMT, dctx->childIDs[i])); 9930e6b6b59SJacob Faibussowitsch } else { 9940e6b6b59SJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(sub, "%" PetscInt64_FMT ", ", dctx->childIDs[i])); 9950e6b6b59SJacob Faibussowitsch } 9960e6b6b59SJacob Faibussowitsch } 9970e6b6b59SJacob Faibussowitsch } 9980e6b6b59SJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(sub)); 9990e6b6b59SJacob Faibussowitsch PetscCall(PetscViewerRestoreSubViewer(viewer, PETSC_COMM_SELF, &sub)); 10000e6b6b59SJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 10010e6b6b59SJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 10020e6b6b59SJacob Faibussowitsch } 10030e6b6b59SJacob Faibussowitsch if (const auto device = dctx->device) PetscCall(PetscDeviceView(device, viewer)); 10040e6b6b59SJacob Faibussowitsch if (iascii) PetscCall(PetscViewerASCIIPopTab(viewer)); 10050e6b6b59SJacob Faibussowitsch PetscFunctionReturn(0); 10060e6b6b59SJacob Faibussowitsch } 10070e6b6b59SJacob Faibussowitsch 10080e6b6b59SJacob Faibussowitsch /*@C 10090e6b6b59SJacob Faibussowitsch PetscDeviceContextViewFromOptions - View a `PetscDeviceContext` from options 10100e6b6b59SJacob Faibussowitsch 10110e6b6b59SJacob Faibussowitsch Input Parameters: 10120e6b6b59SJacob Faibussowitsch + dctx - The `PetscDeviceContext` to view 10130e6b6b59SJacob Faibussowitsch . obj - Optional `PetscObject` to associate (may be `NULL`) 10140e6b6b59SJacob Faibussowitsch - name - The command line option 10150e6b6b59SJacob Faibussowitsch 10160e6b6b59SJacob Faibussowitsch Level: beginner 10170e6b6b59SJacob Faibussowitsch 10180e6b6b59SJacob Faibussowitsch .seealso: `PetscDeviceContextView()`, `PetscObjectViewFromOptions()`, `PetscDeviceContextCreate()` 10190e6b6b59SJacob Faibussowitsch @*/ 10200e6b6b59SJacob Faibussowitsch PetscErrorCode PetscDeviceContextViewFromOptions(PetscDeviceContext dctx, PetscObject obj, const char name[]) { 10210e6b6b59SJacob Faibussowitsch PetscFunctionBegin; 10220e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextGetOptionalNullContext_Internal(&dctx)); 10230e6b6b59SJacob Faibussowitsch if (obj) PetscValidHeader(obj, 2); 10240e6b6b59SJacob Faibussowitsch PetscValidCharPointer(name, 3); 10250e6b6b59SJacob Faibussowitsch PetscCall(PetscObjectViewFromOptions(PetscObjectCast(dctx), obj, name)); 1026030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 1027030f984aSJacob Faibussowitsch } 1028