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 */
12146a86ebSJacob Faibussowitsch class PetscDeviceContextConstructor : public Petsc::ConstructorInterface<_p_PetscDeviceContext, PetscDeviceContextConstructor> {
130e6b6b59SJacob Faibussowitsch public:
construct_(PetscDeviceContext dctx) const14089fb57cSJacob Faibussowitsch PetscErrorCode construct_(PetscDeviceContext dctx) const noexcept
15d71ae5a4SJacob Faibussowitsch {
16030f984aSJacob Faibussowitsch PetscFunctionBegin;
17146a86ebSJacob Faibussowitsch PetscCall(PetscArrayzero(dctx, 1));
188434afd1SBarry Smith PetscCall(PetscHeaderCreate_Private((PetscObject)dctx, PETSC_DEVICE_CONTEXT_CLASSID, "PetscDeviceContext", "PetscDeviceContext", "Sys", PETSC_COMM_SELF, (PetscObjectDestroyFn *)PetscDeviceContextDestroy, (PetscObjectViewFn *)PetscDeviceContextView));
1947496788SBarry Smith PetscCall(PetscLogObjectCreate((PetscObject)dctx));
2047496788SBarry Smith
21dcf958e2SJacob Faibussowitsch PetscCallCXX(PetscObjectCast(dctx)->cpp = new CxxData{dctx});
22146a86ebSJacob Faibussowitsch PetscCall(underlying().reset(dctx, false));
233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
24030f984aSJacob Faibussowitsch }
25030f984aSJacob Faibussowitsch
destroy_(PetscDeviceContext dctx)26089fb57cSJacob Faibussowitsch static PetscErrorCode destroy_(PetscDeviceContext dctx) noexcept
27d71ae5a4SJacob Faibussowitsch {
28030f984aSJacob Faibussowitsch PetscFunctionBegin;
29bf025ffbSJacob 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);
30dbbe0bcdSBarry Smith PetscTryTypeMethod(dctx, destroy);
319566063dSJacob Faibussowitsch PetscCall(PetscDeviceDestroy(&dctx->device));
329566063dSJacob Faibussowitsch PetscCall(PetscFree(dctx->childIDs));
330e6b6b59SJacob Faibussowitsch delete CxxDataCast(dctx);
34146a86ebSJacob Faibussowitsch PetscCall(PetscHeaderDestroy_Private(PetscObjectCast(dctx), PETSC_FALSE));
353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
36030f984aSJacob Faibussowitsch }
37030f984aSJacob Faibussowitsch
reset_(PetscDeviceContext dctx,bool zero=true)38089fb57cSJacob Faibussowitsch static PetscErrorCode reset_(PetscDeviceContext dctx, bool zero = true) noexcept
39d71ae5a4SJacob Faibussowitsch {
40030f984aSJacob Faibussowitsch PetscFunctionBegin;
410e6b6b59SJacob Faibussowitsch if (zero) {
420e6b6b59SJacob Faibussowitsch // reset the device if the user set it
43146a86ebSJacob Faibussowitsch if (Petsc::util::exchange(dctx->usersetdevice, PETSC_FALSE)) {
440e6b6b59SJacob Faibussowitsch PetscTryTypeMethod(dctx, destroy);
450e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceDestroy(&dctx->device));
460e6b6b59SJacob Faibussowitsch PetscCall(PetscArrayzero(dctx->ops, 1));
470e6b6b59SJacob Faibussowitsch dctx->data = nullptr;
480e6b6b59SJacob Faibussowitsch }
490e6b6b59SJacob Faibussowitsch PetscCall(PetscHeaderReset_Internal(PetscObjectCast(dctx)));
50030f984aSJacob Faibussowitsch dctx->numChildren = 0;
510e6b6b59SJacob Faibussowitsch dctx->setup = PETSC_FALSE;
520e6b6b59SJacob Faibussowitsch // don't deallocate the child array, rather just zero it out
530e6b6b59SJacob Faibussowitsch PetscCall(PetscArrayzero(dctx->childIDs, dctx->maxNumChildren));
540e6b6b59SJacob Faibussowitsch PetscCall(CxxDataCast(dctx)->clear());
55dcf958e2SJacob Faibussowitsch PetscCall(CxxDataCast(dctx)->reset_self(dctx));
560e6b6b59SJacob Faibussowitsch }
57d9acb416SHong Zhang dctx->streamType = PETSC_STREAM_DEFAULT;
583ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
59030f984aSJacob Faibussowitsch }
60146a86ebSJacob Faibussowitsch
invalidate_(PetscDeviceContext dctx)61dcf958e2SJacob Faibussowitsch static PetscErrorCode invalidate_(PetscDeviceContext dctx) noexcept
62dcf958e2SJacob Faibussowitsch {
63dcf958e2SJacob Faibussowitsch PetscFunctionBegin;
64dcf958e2SJacob Faibussowitsch PetscCall(CxxDataCast(dctx)->reset_self(dctx));
65dcf958e2SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
66dcf958e2SJacob Faibussowitsch }
67030f984aSJacob Faibussowitsch };
68030f984aSJacob Faibussowitsch
69146a86ebSJacob Faibussowitsch static Petsc::ObjectPool<_p_PetscDeviceContext, PetscDeviceContextConstructor> contextPool;
70030f984aSJacob Faibussowitsch
7110450e9eSJacob Faibussowitsch // PetscClangLinter pragma disable: -fdoc-section-header-unknown
72030f984aSJacob Faibussowitsch /*@C
73811af0c4SBarry Smith PetscDeviceContextCreate - Creates a `PetscDeviceContext`
74030f984aSJacob Faibussowitsch
750e6b6b59SJacob Faibussowitsch Not Collective
76030f984aSJacob Faibussowitsch
77d5b43468SJose E. Roman Output Parameter:
78811af0c4SBarry Smith . dctx - The `PetscDeviceContext`
79030f984aSJacob Faibussowitsch
802fe279fdSBarry Smith Level: beginner
812fe279fdSBarry Smith
82811af0c4SBarry Smith Note:
83030f984aSJacob Faibussowitsch Unlike almost every other PETSc class it is advised that most users use
840e6b6b59SJacob Faibussowitsch `PetscDeviceContextDuplicate()` rather than this routine to create new contexts. Contexts of
850e6b6b59SJacob Faibussowitsch different types are incompatible with one another; using `PetscDeviceContextDuplicate()`
860e6b6b59SJacob Faibussowitsch ensures compatible types.
870e6b6b59SJacob Faibussowitsch
880e6b6b59SJacob Faibussowitsch DAG representation:
890e6b6b59SJacob Faibussowitsch .vb
900e6b6b59SJacob Faibussowitsch time ->
910e6b6b59SJacob Faibussowitsch
920e6b6b59SJacob Faibussowitsch |= CALL =| - dctx ->
930e6b6b59SJacob Faibussowitsch .ve
94030f984aSJacob Faibussowitsch
950e6b6b59SJacob Faibussowitsch .N ASYNC_API
960e6b6b59SJacob Faibussowitsch
97db781477SPatrick Sanan .seealso: `PetscDeviceContextDuplicate()`, `PetscDeviceContextSetDevice()`,
98db781477SPatrick Sanan `PetscDeviceContextSetStreamType()`, `PetscDeviceContextSetUp()`,
990e6b6b59SJacob Faibussowitsch `PetscDeviceContextSetFromOptions()`, `PetscDeviceContextView()`, `PetscDeviceContextDestroy()`
100030f984aSJacob Faibussowitsch @*/
PetscDeviceContextCreate(PetscDeviceContext * dctx)101d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDeviceContextCreate(PetscDeviceContext *dctx)
102d71ae5a4SJacob Faibussowitsch {
103030f984aSJacob Faibussowitsch PetscFunctionBegin;
1044f572ea9SToby Isaac PetscAssertPointer(dctx, 1);
1059566063dSJacob Faibussowitsch PetscCall(PetscDeviceInitializePackage());
1066a4a1270SPierre Jolivet PetscCall(PetscLogEventBegin(DCONTEXT_Create, nullptr, nullptr, nullptr, nullptr));
1070e6b6b59SJacob Faibussowitsch PetscCall(contextPool.allocate(dctx));
1086a4a1270SPierre Jolivet PetscCall(PetscLogEventEnd(DCONTEXT_Create, nullptr, nullptr, nullptr, nullptr));
1093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
110030f984aSJacob Faibussowitsch }
111030f984aSJacob Faibussowitsch
11210450e9eSJacob Faibussowitsch // PetscClangLinter pragma disable: -fdoc-section-header-unknown
113030f984aSJacob Faibussowitsch /*@C
114811af0c4SBarry Smith PetscDeviceContextDestroy - Frees a `PetscDeviceContext`
115030f984aSJacob Faibussowitsch
1160e6b6b59SJacob Faibussowitsch Not Collective
117030f984aSJacob Faibussowitsch
1182fe279fdSBarry Smith Input Parameter:
119811af0c4SBarry Smith . dctx - The `PetscDeviceContext`
120030f984aSJacob Faibussowitsch
1212fe279fdSBarry Smith Level: beginner
1222fe279fdSBarry Smith
1230e6b6b59SJacob Faibussowitsch Notes:
1240e6b6b59SJacob Faibussowitsch No implicit synchronization occurs due to this routine, all resources are released completely
1250e6b6b59SJacob Faibussowitsch asynchronously w.r.t. the host. If one needs to guarantee access to the data produced on
1260e6b6b59SJacob Faibussowitsch `dctx`'s stream the user is responsible for calling `PetscDeviceContextSynchronize()` before
1270e6b6b59SJacob Faibussowitsch calling this routine.
128030f984aSJacob Faibussowitsch
129da81f932SPierre Jolivet DAG representation:
1300e6b6b59SJacob Faibussowitsch .vb
1310e6b6b59SJacob Faibussowitsch time ->
1320e6b6b59SJacob Faibussowitsch
1330e6b6b59SJacob Faibussowitsch -> dctx - |= CALL =|
1340e6b6b59SJacob Faibussowitsch .ve
1350e6b6b59SJacob Faibussowitsch
1360e6b6b59SJacob Faibussowitsch Developer Notes:
1370e6b6b59SJacob Faibussowitsch `dctx` is never actually "destroyed" in the classical sense. It is returned to an ever
1380e6b6b59SJacob Faibussowitsch growing pool of `PetscDeviceContext`s. There are currently no limits on the size of the pool,
1390e6b6b59SJacob Faibussowitsch this should perhaps be implemented.
140030f984aSJacob Faibussowitsch
1410e6b6b59SJacob Faibussowitsch .N ASYNC_API
1420e6b6b59SJacob Faibussowitsch
1430e6b6b59SJacob Faibussowitsch .seealso: `PetscDeviceContextCreate()`, `PetscDeviceContextSetDevice()`,
1440e6b6b59SJacob Faibussowitsch `PetscDeviceContextSetUp()`, `PetscDeviceContextSynchronize()`
145030f984aSJacob Faibussowitsch @*/
PetscDeviceContextDestroy(PetscDeviceContext * dctx)146d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDeviceContextDestroy(PetscDeviceContext *dctx)
147d71ae5a4SJacob Faibussowitsch {
148030f984aSJacob Faibussowitsch PetscFunctionBegin;
1494f572ea9SToby Isaac PetscAssertPointer(dctx, 1);
1503ba16761SJacob Faibussowitsch if (!*dctx) PetscFunctionReturn(PETSC_SUCCESS);
1516a4a1270SPierre Jolivet PetscCall(PetscLogEventBegin(DCONTEXT_Destroy, nullptr, nullptr, nullptr, nullptr));
1520e6b6b59SJacob Faibussowitsch if (--(PetscObjectCast(*dctx)->refct) <= 0) {
1530e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextCheckNotOrphaned_Internal(*dctx));
154146a86ebSJacob Faibussowitsch PetscCall(contextPool.deallocate(dctx));
1550e6b6b59SJacob Faibussowitsch }
1566a4a1270SPierre Jolivet PetscCall(PetscLogEventEnd(DCONTEXT_Destroy, nullptr, nullptr, nullptr, nullptr));
157bf025ffbSJacob Faibussowitsch *dctx = nullptr;
1583ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
159030f984aSJacob Faibussowitsch }
160030f984aSJacob Faibussowitsch
161030f984aSJacob Faibussowitsch /*@C
1620e6b6b59SJacob Faibussowitsch PetscDeviceContextSetStreamType - Set the implementation type of the underlying stream for a
1630e6b6b59SJacob Faibussowitsch `PetscDeviceContext`
164030f984aSJacob Faibussowitsch
1650e6b6b59SJacob Faibussowitsch Not Collective
166030f984aSJacob Faibussowitsch
16701d2d390SJose E. Roman Input Parameters:
168811af0c4SBarry Smith + dctx - The `PetscDeviceContext`
169811af0c4SBarry Smith - type - The `PetscStreamType`
170030f984aSJacob Faibussowitsch
1712fe279fdSBarry Smith Level: beginner
1722fe279fdSBarry Smith
1732fe279fdSBarry Smith Note:
174811af0c4SBarry Smith See `PetscStreamType` in `include/petscdevicetypes.h` for more information on the available
1750e6b6b59SJacob Faibussowitsch types and their interactions. If the `PetscDeviceContext` was previously set up and stream
176811af0c4SBarry Smith type was changed, you must call `PetscDeviceContextSetUp()` again after this routine.
177030f984aSJacob Faibussowitsch
1780e6b6b59SJacob Faibussowitsch .seealso: `PetscStreamType`, `PetscDeviceContextGetStreamType()`, `PetscDeviceContextCreate()`,
1790e6b6b59SJacob Faibussowitsch `PetscDeviceContextSetUp()`, `PetscDeviceContextSetFromOptions()`
180030f984aSJacob Faibussowitsch @*/
PetscDeviceContextSetStreamType(PetscDeviceContext dctx,PetscStreamType type)181d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDeviceContextSetStreamType(PetscDeviceContext dctx, PetscStreamType type)
182d71ae5a4SJacob Faibussowitsch {
183030f984aSJacob Faibussowitsch PetscFunctionBegin;
1840e6b6b59SJacob Faibussowitsch // do not use getoptionalnullcontext here since we do not want the user to change the stream
1850e6b6b59SJacob Faibussowitsch // type
186030f984aSJacob Faibussowitsch PetscValidDeviceContext(dctx, 1);
187030f984aSJacob Faibussowitsch PetscValidStreamType(type, 2);
1880e6b6b59SJacob Faibussowitsch // only need to do complex swapping if the object has already been setup
189030f984aSJacob Faibussowitsch if (dctx->setup && (dctx->streamType != type)) {
190030f984aSJacob Faibussowitsch dctx->setup = PETSC_FALSE;
1916a4a1270SPierre Jolivet PetscCall(PetscLogEventBegin(DCONTEXT_ChangeStream, dctx, nullptr, nullptr, nullptr));
1920e6b6b59SJacob Faibussowitsch PetscUseTypeMethod(dctx, changestreamtype, type);
1936a4a1270SPierre Jolivet PetscCall(PetscLogEventEnd(DCONTEXT_ChangeStream, dctx, nullptr, nullptr, nullptr));
194030f984aSJacob Faibussowitsch }
195030f984aSJacob Faibussowitsch dctx->streamType = type;
1963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
197030f984aSJacob Faibussowitsch }
198030f984aSJacob Faibussowitsch
199030f984aSJacob Faibussowitsch /*@C
2000e6b6b59SJacob Faibussowitsch PetscDeviceContextGetStreamType - Get the implementation type of the underlying stream for a
2010e6b6b59SJacob Faibussowitsch `PetscDeviceContext`
202030f984aSJacob Faibussowitsch
2030e6b6b59SJacob Faibussowitsch Not Collective
204030f984aSJacob Faibussowitsch
20501d2d390SJose E. Roman Input Parameter:
206811af0c4SBarry Smith . dctx - The `PetscDeviceContext`
207030f984aSJacob Faibussowitsch
208030f984aSJacob Faibussowitsch Output Parameter:
209811af0c4SBarry Smith . type - The `PetscStreamType`
210030f984aSJacob Faibussowitsch
2112fe279fdSBarry Smith Level: beginner
2122fe279fdSBarry Smith
2132fe279fdSBarry Smith Note:
2140e6b6b59SJacob Faibussowitsch See `PetscStreamType` in `include/petscdevicetypes.h` for more information on the available
2150e6b6b59SJacob Faibussowitsch types and their interactions
216030f984aSJacob Faibussowitsch
2170e6b6b59SJacob Faibussowitsch .seealso: `PetscDeviceContextSetStreamType()`, `PetscDeviceContextCreate()`,
2180e6b6b59SJacob Faibussowitsch `PetscDeviceContextSetFromOptions()`
219030f984aSJacob Faibussowitsch @*/
PetscDeviceContextGetStreamType(PetscDeviceContext dctx,PetscStreamType * type)220d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDeviceContextGetStreamType(PetscDeviceContext dctx, PetscStreamType *type)
221d71ae5a4SJacob Faibussowitsch {
222030f984aSJacob Faibussowitsch PetscFunctionBegin;
2230e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextGetOptionalNullContext_Internal(&dctx));
2244f572ea9SToby Isaac PetscAssertPointer(type, 2);
225030f984aSJacob Faibussowitsch *type = dctx->streamType;
2263ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
227030f984aSJacob Faibussowitsch }
228030f984aSJacob Faibussowitsch
2290e6b6b59SJacob Faibussowitsch /*
2300e6b6b59SJacob Faibussowitsch Actual function to set the device.
231030f984aSJacob Faibussowitsch
2320e6b6b59SJacob Faibussowitsch 1. Repeatedly destroying and recreating internal data structures (like streams and events)
2330e6b6b59SJacob Faibussowitsch for recycled PetscDeviceContexts is not free. If done often, it does add up.
2340e6b6b59SJacob Faibussowitsch 2. The vast majority of PetscDeviceContexts are created by PETSc either as children or
23535cb6cd3SPierre Jolivet default contexts. The default contexts *never* change type, and the children are extremely
2360e6b6b59SJacob Faibussowitsch unlikely to (chances are if you fork once, you will fork again very soon).
2370e6b6b59SJacob Faibussowitsch 3. The only time this calculus changes is if the user themselves sets the device type. In
2380e6b6b59SJacob Faibussowitsch this case we do not know what the user has changed, so must always wipe the slate clean.
2390e6b6b59SJacob Faibussowitsch
2400e6b6b59SJacob Faibussowitsch Thus we need to keep track whether the user explicitly sets the device contexts device.
2410e6b6b59SJacob Faibussowitsch */
PetscDeviceContextSetDevice_Private(PetscDeviceContext dctx,PetscDevice device,PetscBool user_set)242d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscDeviceContextSetDevice_Private(PetscDeviceContext dctx, PetscDevice device, PetscBool user_set)
243d71ae5a4SJacob Faibussowitsch {
2440e6b6b59SJacob Faibussowitsch PetscFunctionBegin;
2450e6b6b59SJacob Faibussowitsch // do not use getoptionalnullcontext here since we do not want the user to change its device
2460e6b6b59SJacob Faibussowitsch PetscValidDeviceContext(dctx, 1);
2470e6b6b59SJacob Faibussowitsch PetscValidDevice(device, 2);
2483ba16761SJacob Faibussowitsch if (dctx->device && (dctx->device->id == device->id)) PetscFunctionReturn(PETSC_SUCCESS);
2496a4a1270SPierre Jolivet PetscCall(PetscLogEventBegin(DCONTEXT_SetDevice, dctx, nullptr, nullptr, nullptr));
2502126a61dSJacob Faibussowitsch PetscTryTypeMethod(dctx, destroy);
2510e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceDestroy(&dctx->device));
2520e6b6b59SJacob Faibussowitsch PetscCall(PetscMemzero(dctx->ops, sizeof(*dctx->ops)));
2532126a61dSJacob Faibussowitsch PetscCall(PetscDeviceReference_Internal(device));
2542126a61dSJacob Faibussowitsch // set it before calling the method
2552126a61dSJacob Faibussowitsch dctx->device = device;
2560e6b6b59SJacob Faibussowitsch PetscCall((*device->ops->createcontext)(dctx));
2576a4a1270SPierre Jolivet PetscCall(PetscLogEventEnd(DCONTEXT_SetDevice, dctx, nullptr, nullptr, nullptr));
2580e6b6b59SJacob Faibussowitsch dctx->setup = PETSC_FALSE;
2590e6b6b59SJacob Faibussowitsch dctx->usersetdevice = user_set;
2603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
2610e6b6b59SJacob Faibussowitsch }
2620e6b6b59SJacob Faibussowitsch
PetscDeviceContextSetDefaultDeviceForType_Internal(PetscDeviceContext dctx,PetscDeviceType type)263d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDeviceContextSetDefaultDeviceForType_Internal(PetscDeviceContext dctx, PetscDeviceType type)
264d71ae5a4SJacob Faibussowitsch {
2650e6b6b59SJacob Faibussowitsch PetscDevice device;
2660e6b6b59SJacob Faibussowitsch
2670e6b6b59SJacob Faibussowitsch PetscFunctionBegin;
2680e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceGetDefaultForType_Internal(type, &device));
2690e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextSetDevice_Private(dctx, device, PETSC_FALSE));
2703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
2710e6b6b59SJacob Faibussowitsch }
2720e6b6b59SJacob Faibussowitsch
2730e6b6b59SJacob Faibussowitsch /*@C
2740e6b6b59SJacob Faibussowitsch PetscDeviceContextSetDevice - Set the underlying `PetscDevice` for a `PetscDeviceContext`
2750e6b6b59SJacob Faibussowitsch
2760e6b6b59SJacob Faibussowitsch Not Collective
277030f984aSJacob Faibussowitsch
27801d2d390SJose E. Roman Input Parameters:
279811af0c4SBarry Smith + dctx - The `PetscDeviceContext`
280811af0c4SBarry Smith - device - The `PetscDevice`
281030f984aSJacob Faibussowitsch
2822fe279fdSBarry Smith Level: intermediate
2832fe279fdSBarry Smith
284030f984aSJacob Faibussowitsch Notes:
2850e6b6b59SJacob Faibussowitsch This routine is effectively `PetscDeviceContext`'s "set-type" (so every `PetscDeviceContext` must
286da81f932SPierre Jolivet also have an attached `PetscDevice`). Unlike the usual set-type semantics, it is not strictly
2870e6b6b59SJacob Faibussowitsch necessary to set a contexts device to enable usage, any created `PetscDeviceContext`s will
2880e6b6b59SJacob Faibussowitsch always come equipped with the "default" device.
289030f984aSJacob Faibussowitsch
2900e6b6b59SJacob Faibussowitsch This routine is a no-op if `device` is already attached to `dctx`.
291a4af0ceeSJacob Faibussowitsch
2920e6b6b59SJacob Faibussowitsch This routine may (but is very unlikely to) initialize the backend device and may incur
2930e6b6b59SJacob Faibussowitsch synchronization.
2945181c4f9SJacob Faibussowitsch
2950e6b6b59SJacob Faibussowitsch .seealso: `PetscDeviceCreate()`, `PetscDeviceConfigure()`, `PetscDeviceContextGetDevice()`,
2960e6b6b59SJacob Faibussowitsch `PetscDeviceContextGetDeviceType()`
297030f984aSJacob Faibussowitsch @*/
PetscDeviceContextSetDevice(PetscDeviceContext dctx,PetscDevice device)298d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDeviceContextSetDevice(PetscDeviceContext dctx, PetscDevice device)
299d71ae5a4SJacob Faibussowitsch {
300030f984aSJacob Faibussowitsch PetscFunctionBegin;
3010e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextSetDevice_Private(dctx, device, PETSC_TRUE));
3023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
303030f984aSJacob Faibussowitsch }
304030f984aSJacob Faibussowitsch
305030f984aSJacob Faibussowitsch /*@C
306811af0c4SBarry Smith PetscDeviceContextGetDevice - Get the underlying `PetscDevice` for a `PetscDeviceContext`
307030f984aSJacob Faibussowitsch
3080e6b6b59SJacob Faibussowitsch Not Collective
309030f984aSJacob Faibussowitsch
310030f984aSJacob Faibussowitsch Input Parameter:
311811af0c4SBarry Smith . dctx - the `PetscDeviceContext`
312030f984aSJacob Faibussowitsch
313030f984aSJacob Faibussowitsch Output Parameter:
314811af0c4SBarry Smith . device - The `PetscDevice`
315030f984aSJacob Faibussowitsch
316a375dbeeSPatrick Sanan Level: intermediate
317a375dbeeSPatrick Sanan
3182fe279fdSBarry Smith Note:
3192fe279fdSBarry Smith This is a borrowed reference, the user should not destroy `device`.
3202fe279fdSBarry Smith
3210e6b6b59SJacob Faibussowitsch .seealso: `PetscDeviceContextSetDevice()`, `PetscDevice`, `PetscDeviceContextGetDeviceType()`
322030f984aSJacob Faibussowitsch @*/
PetscDeviceContextGetDevice(PetscDeviceContext dctx,PetscDevice * device)323d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDeviceContextGetDevice(PetscDeviceContext dctx, PetscDevice *device)
324d71ae5a4SJacob Faibussowitsch {
325030f984aSJacob Faibussowitsch PetscFunctionBegin;
3260e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextGetOptionalNullContext_Internal(&dctx));
3274f572ea9SToby Isaac PetscAssertPointer(device, 2);
3280e6b6b59SJacob Faibussowitsch PetscAssert(dctx->device, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "PetscDeviceContext %" PetscInt64_FMT " has no attached PetscDevice to get", PetscObjectCast(dctx)->id);
329030f984aSJacob Faibussowitsch *device = dctx->device;
3303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
331030f984aSJacob Faibussowitsch }
332030f984aSJacob Faibussowitsch
333030f984aSJacob Faibussowitsch /*@C
3340e6b6b59SJacob Faibussowitsch PetscDeviceContextGetDeviceType - Get the `PetscDeviceType` for a `PetscDeviceContext`
3350e6b6b59SJacob Faibussowitsch
3360e6b6b59SJacob Faibussowitsch Not Collective
3370e6b6b59SJacob Faibussowitsch
3380e6b6b59SJacob Faibussowitsch Input Parameter:
3390e6b6b59SJacob Faibussowitsch . dctx - The `PetscDeviceContext`
3400e6b6b59SJacob Faibussowitsch
3410e6b6b59SJacob Faibussowitsch Output Parameter:
3420e6b6b59SJacob Faibussowitsch . type - The `PetscDeviceType`
3430e6b6b59SJacob Faibussowitsch
3442fe279fdSBarry Smith Level: beginner
3452fe279fdSBarry Smith
3462fe279fdSBarry Smith Note:
3470e6b6b59SJacob Faibussowitsch This routine is a convenience shorthand for `PetscDeviceContextGetDevice()` ->
3480e6b6b59SJacob Faibussowitsch `PetscDeviceGetType()`.
3490e6b6b59SJacob Faibussowitsch
3500e6b6b59SJacob Faibussowitsch .seealso: `PetscDeviceType`, `PetscDeviceContextGetDevice()`, `PetscDeviceGetType()`, `PetscDevice`
3510e6b6b59SJacob Faibussowitsch @*/
PetscDeviceContextGetDeviceType(PetscDeviceContext dctx,PetscDeviceType * type)352d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDeviceContextGetDeviceType(PetscDeviceContext dctx, PetscDeviceType *type)
353d71ae5a4SJacob Faibussowitsch {
3540e6b6b59SJacob Faibussowitsch PetscDevice device = nullptr;
3550e6b6b59SJacob Faibussowitsch
3560e6b6b59SJacob Faibussowitsch PetscFunctionBegin;
3570e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextGetOptionalNullContext_Internal(&dctx));
3584f572ea9SToby Isaac PetscAssertPointer(type, 2);
3590e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextGetDevice(dctx, &device));
3600e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceGetType(device, type));
3613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
3620e6b6b59SJacob Faibussowitsch }
3630e6b6b59SJacob Faibussowitsch
3640e6b6b59SJacob Faibussowitsch /*@C
365811af0c4SBarry Smith PetscDeviceContextSetUp - Prepares a `PetscDeviceContext` for use
366030f984aSJacob Faibussowitsch
3670e6b6b59SJacob Faibussowitsch Not Collective
368030f984aSJacob Faibussowitsch
36901d2d390SJose E. Roman Input Parameter:
370811af0c4SBarry Smith . dctx - The `PetscDeviceContext`
371030f984aSJacob Faibussowitsch
3722fe279fdSBarry Smith Level: beginner
3732fe279fdSBarry Smith
374aec76313SJacob Faibussowitsch Developer Notes:
3750e6b6b59SJacob Faibussowitsch This routine is usually the stage where a `PetscDeviceContext` acquires device-side data
3760e6b6b59SJacob Faibussowitsch structures such as streams, events, and (possibly) handles.
377030f984aSJacob Faibussowitsch
3780e6b6b59SJacob Faibussowitsch .seealso: `PetscDeviceContextCreate()`, `PetscDeviceContextSetDevice()`,
3790e6b6b59SJacob Faibussowitsch `PetscDeviceContextDestroy()`, `PetscDeviceContextSetFromOptions()`
380030f984aSJacob Faibussowitsch @*/
PetscDeviceContextSetUp(PetscDeviceContext dctx)381d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDeviceContextSetUp(PetscDeviceContext dctx)
382d71ae5a4SJacob Faibussowitsch {
383030f984aSJacob Faibussowitsch PetscFunctionBegin;
3840e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextGetOptionalNullContext_Internal(&dctx));
3853ba16761SJacob Faibussowitsch if (dctx->setup) PetscFunctionReturn(PETSC_SUCCESS);
3860e6b6b59SJacob Faibussowitsch if (!dctx->device) {
3870e6b6b59SJacob Faibussowitsch const auto default_dtype = PETSC_DEVICE_DEFAULT();
3880e6b6b59SJacob Faibussowitsch
3890e6b6b59SJacob 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]));
3900e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextSetDefaultDeviceForType_Internal(dctx, default_dtype));
3910e6b6b59SJacob Faibussowitsch }
3926a4a1270SPierre Jolivet PetscCall(PetscLogEventBegin(DCONTEXT_SetUp, dctx, nullptr, nullptr, nullptr));
393dbbe0bcdSBarry Smith PetscUseTypeMethod(dctx, setup);
3946a4a1270SPierre Jolivet PetscCall(PetscLogEventEnd(DCONTEXT_SetUp, dctx, nullptr, nullptr, nullptr));
395030f984aSJacob Faibussowitsch dctx->setup = PETSC_TRUE;
3963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
397030f984aSJacob Faibussowitsch }
398030f984aSJacob Faibussowitsch
PetscDeviceContextDuplicate_Private(PetscDeviceContext dctx,PetscStreamType stype,PetscDeviceContext * dctxdup)399d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscDeviceContextDuplicate_Private(PetscDeviceContext dctx, PetscStreamType stype, PetscDeviceContext *dctxdup)
400d71ae5a4SJacob Faibussowitsch {
4010e6b6b59SJacob Faibussowitsch PetscFunctionBegin;
4026a4a1270SPierre Jolivet PetscCall(PetscLogEventBegin(DCONTEXT_Duplicate, dctx, nullptr, nullptr, nullptr));
4030e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextCreate(dctxdup));
4040e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextSetStreamType(*dctxdup, stype));
4050e6b6b59SJacob Faibussowitsch if (const auto device = dctx->device) PetscCall(PetscDeviceContextSetDevice_Private(*dctxdup, device, dctx->usersetdevice));
4060e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextSetUp(*dctxdup));
4076a4a1270SPierre Jolivet PetscCall(PetscLogEventEnd(DCONTEXT_Duplicate, dctx, nullptr, nullptr, nullptr));
4083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
4090e6b6b59SJacob Faibussowitsch }
4100e6b6b59SJacob Faibussowitsch
41110450e9eSJacob Faibussowitsch // PetscClangLinter pragma disable: -fdoc-section-header-unknown
412030f984aSJacob Faibussowitsch /*@C
413811af0c4SBarry Smith PetscDeviceContextDuplicate - Duplicates a `PetscDeviceContext` object
414030f984aSJacob Faibussowitsch
4150e6b6b59SJacob Faibussowitsch Not Collective
416030f984aSJacob Faibussowitsch
417030f984aSJacob Faibussowitsch Input Parameter:
418811af0c4SBarry Smith . dctx - The `PetscDeviceContext` to duplicate
419030f984aSJacob Faibussowitsch
4206aad120cSJose E. Roman Output Parameter:
421811af0c4SBarry Smith . dctxdup - The duplicated `PetscDeviceContext`
422030f984aSJacob Faibussowitsch
4232fe279fdSBarry Smith Level: beginner
4242fe279fdSBarry Smith
4250e6b6b59SJacob Faibussowitsch Notes:
4260e6b6b59SJacob Faibussowitsch This is a shorthand method for creating a `PetscDeviceContext` with the exact same settings as
4270e6b6b59SJacob Faibussowitsch another. Note however that `dctxdup` does not share any of the underlying data with `dctx`,
4280e6b6b59SJacob Faibussowitsch (including its current stream-state) they are completely separate objects.
4290e6b6b59SJacob Faibussowitsch
4300e6b6b59SJacob Faibussowitsch There is no implied ordering between `dctx` or `dctxdup`.
4310e6b6b59SJacob Faibussowitsch
4320e6b6b59SJacob Faibussowitsch DAG representation:
4330e6b6b59SJacob Faibussowitsch .vb
4340e6b6b59SJacob Faibussowitsch time ->
4350e6b6b59SJacob Faibussowitsch
4360e6b6b59SJacob Faibussowitsch -> dctx - |= CALL =| - dctx ---->
4370e6b6b59SJacob Faibussowitsch - dctxdup ->
4380e6b6b59SJacob Faibussowitsch .ve
439030f984aSJacob Faibussowitsch
4400e6b6b59SJacob Faibussowitsch .seealso: `PetscDeviceContextCreate()`, `PetscDeviceContextSetDevice()`,
4410e6b6b59SJacob Faibussowitsch `PetscDeviceContextSetStreamType()`
442030f984aSJacob Faibussowitsch @*/
PetscDeviceContextDuplicate(PetscDeviceContext dctx,PetscDeviceContext * dctxdup)443d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDeviceContextDuplicate(PetscDeviceContext dctx, PetscDeviceContext *dctxdup)
444d71ae5a4SJacob Faibussowitsch {
445d9acb416SHong Zhang auto stype = PETSC_STREAM_DEFAULT;
446030f984aSJacob Faibussowitsch
447030f984aSJacob Faibussowitsch PetscFunctionBegin;
4480e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextGetOptionalNullContext_Internal(&dctx));
4494f572ea9SToby Isaac PetscAssertPointer(dctxdup, 2);
4500e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextGetStreamType(dctx, &stype));
4510e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextDuplicate_Private(dctx, stype, dctxdup));
4523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
453030f984aSJacob Faibussowitsch }
454030f984aSJacob Faibussowitsch
455030f984aSJacob Faibussowitsch /*@C
456811af0c4SBarry Smith PetscDeviceContextQueryIdle - Returns whether or not a `PetscDeviceContext` is idle
457030f984aSJacob Faibussowitsch
4580e6b6b59SJacob Faibussowitsch Not Collective
459030f984aSJacob Faibussowitsch
460030f984aSJacob Faibussowitsch Input Parameter:
4610e6b6b59SJacob Faibussowitsch . dctx - The `PetscDeviceContext`
462030f984aSJacob Faibussowitsch
463030f984aSJacob Faibussowitsch Output Parameter:
4640e6b6b59SJacob Faibussowitsch . idle - `PETSC_TRUE` if `dctx` has NO work, `PETSC_FALSE` if it has work
465030f984aSJacob Faibussowitsch
4662fe279fdSBarry Smith Level: intermediate
4672fe279fdSBarry Smith
468811af0c4SBarry Smith Note:
469ef657721SJacob Faibussowitsch This routine only refers a singular context and does NOT take any of its children into
4700e6b6b59SJacob Faibussowitsch account. That is, if `dctx` is idle but has dependents who do have work this routine still
471811af0c4SBarry Smith returns `PETSC_TRUE`.
472030f984aSJacob Faibussowitsch
473db781477SPatrick Sanan .seealso: `PetscDeviceContextCreate()`, `PetscDeviceContextWaitForContext()`, `PetscDeviceContextFork()`
474030f984aSJacob Faibussowitsch @*/
PetscDeviceContextQueryIdle(PetscDeviceContext dctx,PetscBool * idle)475d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDeviceContextQueryIdle(PetscDeviceContext dctx, PetscBool *idle)
476d71ae5a4SJacob Faibussowitsch {
477030f984aSJacob Faibussowitsch PetscFunctionBegin;
4780e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextGetOptionalNullContext_Internal(&dctx));
4794f572ea9SToby Isaac PetscAssertPointer(idle, 2);
4806a4a1270SPierre Jolivet PetscCall(PetscLogEventBegin(DCONTEXT_QueryIdle, dctx, nullptr, nullptr, nullptr));
481dbbe0bcdSBarry Smith PetscUseTypeMethod(dctx, query, idle);
4826a4a1270SPierre Jolivet PetscCall(PetscLogEventEnd(DCONTEXT_QueryIdle, dctx, nullptr, nullptr, nullptr));
4830e6b6b59SJacob 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"));
4843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
485030f984aSJacob Faibussowitsch }
486030f984aSJacob Faibussowitsch
48710450e9eSJacob Faibussowitsch // PetscClangLinter pragma disable: -fdoc-section-header-unknown
488030f984aSJacob Faibussowitsch /*@C
489030f984aSJacob Faibussowitsch PetscDeviceContextWaitForContext - Make one context wait for another context to finish
490030f984aSJacob Faibussowitsch
4910e6b6b59SJacob Faibussowitsch Not Collective
492030f984aSJacob Faibussowitsch
493030f984aSJacob Faibussowitsch Input Parameters:
494811af0c4SBarry Smith + dctxa - The `PetscDeviceContext` object that is waiting
495811af0c4SBarry Smith - dctxb - The `PetscDeviceContext` object that is being waited on
496030f984aSJacob Faibussowitsch
4972fe279fdSBarry Smith Level: beginner
4982fe279fdSBarry Smith
499030f984aSJacob Faibussowitsch Notes:
5000e6b6b59SJacob Faibussowitsch Serializes two `PetscDeviceContext`s. Serialization is performed asynchronously; the host
5010e6b6b59SJacob Faibussowitsch does not wait for the serialization to actually occur.
502811af0c4SBarry Smith
5030e6b6b59SJacob Faibussowitsch This routine uses only the state of `dctxb` at the moment this routine was called, so any
5040e6b6b59SJacob Faibussowitsch future work queued will not affect `dctxa`. It is safe to pass the same context to both
5050e6b6b59SJacob Faibussowitsch arguments (in which case this routine does nothing).
5060e6b6b59SJacob Faibussowitsch
5070e6b6b59SJacob Faibussowitsch DAG representation:
5080e6b6b59SJacob Faibussowitsch .vb
5090e6b6b59SJacob Faibussowitsch time ->
5100e6b6b59SJacob Faibussowitsch
5110e6b6b59SJacob Faibussowitsch -> dctxa ---/- |= CALL =| - dctxa ->
5120e6b6b59SJacob Faibussowitsch /
5130e6b6b59SJacob Faibussowitsch -> dctxb -/------------------------>
5140e6b6b59SJacob Faibussowitsch .ve
515030f984aSJacob Faibussowitsch
5160e6b6b59SJacob Faibussowitsch .N ASYNC_API
5170e6b6b59SJacob Faibussowitsch
518db781477SPatrick Sanan .seealso: `PetscDeviceContextCreate()`, `PetscDeviceContextQueryIdle()`, `PetscDeviceContextJoin()`
519030f984aSJacob Faibussowitsch @*/
PetscDeviceContextWaitForContext(PetscDeviceContext dctxa,PetscDeviceContext dctxb)520d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDeviceContextWaitForContext(PetscDeviceContext dctxa, PetscDeviceContext dctxb)
521d71ae5a4SJacob Faibussowitsch {
522dcf958e2SJacob Faibussowitsch PetscObjectId bid;
5230e6b6b59SJacob Faibussowitsch
524030f984aSJacob Faibussowitsch PetscFunctionBegin;
5250e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextGetOptionalNullContext_Internal(&dctxa));
5260e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextGetOptionalNullContext_Internal(&dctxb));
527030f984aSJacob Faibussowitsch PetscCheckCompatibleDeviceContexts(dctxa, 1, dctxb, 2);
5283ba16761SJacob Faibussowitsch if (dctxa == dctxb) PetscFunctionReturn(PETSC_SUCCESS);
529dcf958e2SJacob Faibussowitsch bid = PetscObjectCast(dctxb)->id;
5306a4a1270SPierre Jolivet PetscCall(PetscLogEventBegin(DCONTEXT_WaitForCtx, dctxa, dctxb, nullptr, nullptr));
531dbbe0bcdSBarry Smith PetscUseTypeMethod(dctxa, waitforcontext, dctxb);
532dcf958e2SJacob Faibussowitsch PetscCallCXX(CxxDataCast(dctxa)->upstream()[bid] = CxxDataCast(dctxb)->weak_snapshot());
5336a4a1270SPierre Jolivet PetscCall(PetscLogEventEnd(DCONTEXT_WaitForCtx, dctxa, dctxb, nullptr, nullptr));
534dcf958e2SJacob Faibussowitsch PetscCall(PetscInfo(dctxa, "dctx %" PetscInt64_FMT " waiting on dctx %" PetscInt64_FMT "\n", PetscObjectCast(dctxa)->id, bid));
535dcf958e2SJacob Faibussowitsch PetscCall(PetscObjectStateIncrease(PetscObjectCast(dctxa)));
5363ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
537030f984aSJacob Faibussowitsch }
538030f984aSJacob Faibussowitsch
53910450e9eSJacob Faibussowitsch // PetscClangLinter pragma disable: -fdoc-section-header-unknown
5400e6b6b59SJacob Faibussowitsch /*@C
5410e6b6b59SJacob Faibussowitsch PetscDeviceContextForkWithStreamType - Create a set of dependent child contexts from a parent
5420e6b6b59SJacob Faibussowitsch context with a prescribed `PetscStreamType`
5430e6b6b59SJacob Faibussowitsch
5440e6b6b59SJacob Faibussowitsch Not Collective, Asynchronous
5450e6b6b59SJacob Faibussowitsch
5460e6b6b59SJacob Faibussowitsch Input Parameters:
5470e6b6b59SJacob Faibussowitsch + dctx - The parent `PetscDeviceContext`
5480e6b6b59SJacob Faibussowitsch . stype - The prescribed `PetscStreamType`
5490e6b6b59SJacob Faibussowitsch - n - The number of children to create
5500e6b6b59SJacob Faibussowitsch
5510e6b6b59SJacob Faibussowitsch Output Parameter:
5520e6b6b59SJacob Faibussowitsch . dsub - The created child context(s)
5530e6b6b59SJacob Faibussowitsch
5542fe279fdSBarry Smith Level: intermediate
5552fe279fdSBarry Smith
5560e6b6b59SJacob Faibussowitsch Notes:
5570e6b6b59SJacob Faibussowitsch This routine creates `n` edges of a DAG from a source node which are causally dependent on the
5580e6b6b59SJacob Faibussowitsch source node. This causal dependency is established as-if by calling
5590e6b6b59SJacob Faibussowitsch `PetscDeviceContextWaitForContext()` on every child.
5600e6b6b59SJacob Faibussowitsch
5610e6b6b59SJacob Faibussowitsch `dsub` is allocated by this routine and has its lifetime bounded by `dctx`. That is, `dctx`
5620e6b6b59SJacob Faibussowitsch expects to free `dsub` (via `PetscDeviceContextJoin()`) before it itself is destroyed.
5630e6b6b59SJacob Faibussowitsch
5640e6b6b59SJacob Faibussowitsch This routine only accounts for work queued on `dctx` up until calling this routine, any
5650e6b6b59SJacob Faibussowitsch subsequent work enqueued on `dctx` has no effect on `dsub`.
5660e6b6b59SJacob Faibussowitsch
5670e6b6b59SJacob Faibussowitsch The `PetscStreamType` of `dctx` does not have to equal `stype`. In fact, it is often the case
5680e6b6b59SJacob Faibussowitsch that they are different. This is useful in cases where a routine can locally exploit stream
5690e6b6b59SJacob Faibussowitsch parallelism without needing to worry about what stream type the incoming `PetscDeviceContext`
5700e6b6b59SJacob Faibussowitsch carries.
5710e6b6b59SJacob Faibussowitsch
5720e6b6b59SJacob Faibussowitsch DAG representation:
5730e6b6b59SJacob Faibussowitsch .vb
5740e6b6b59SJacob Faibussowitsch time ->
5750e6b6b59SJacob Faibussowitsch
5760e6b6b59SJacob Faibussowitsch -> dctx - |= CALL =| -\----> dctx ------>
5770e6b6b59SJacob Faibussowitsch \---> dsub[0] --->
5780e6b6b59SJacob Faibussowitsch \--> ... ------->
5790e6b6b59SJacob Faibussowitsch \-> dsub[n-1] ->
5800e6b6b59SJacob Faibussowitsch .ve
5810e6b6b59SJacob Faibussowitsch
5820e6b6b59SJacob Faibussowitsch .N ASYNC_API
5830e6b6b59SJacob Faibussowitsch
5840e6b6b59SJacob Faibussowitsch .seealso: `PetscDeviceContextJoin()`, `PetscDeviceContextSynchronize()`,
5850e6b6b59SJacob Faibussowitsch `PetscDeviceContextQueryIdle()`, `PetscDeviceContextWaitForContext()`
5860e6b6b59SJacob Faibussowitsch @*/
PetscDeviceContextForkWithStreamType(PetscDeviceContext dctx,PetscStreamType stype,PetscInt n,PetscDeviceContext ** dsub)587d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDeviceContextForkWithStreamType(PetscDeviceContext dctx, PetscStreamType stype, PetscInt n, PetscDeviceContext **dsub)
588d71ae5a4SJacob Faibussowitsch {
5890e6b6b59SJacob Faibussowitsch // debugging only
5900e6b6b59SJacob Faibussowitsch std::string idList;
5910e6b6b59SJacob Faibussowitsch auto ninput = n;
5920e6b6b59SJacob Faibussowitsch
5930e6b6b59SJacob Faibussowitsch PetscFunctionBegin;
5940e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextGetOptionalNullContext_Internal(&dctx));
5950e6b6b59SJacob Faibussowitsch PetscAssert(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of contexts requested %" PetscInt_FMT " < 0", n);
5964f572ea9SToby Isaac PetscAssertPointer(dsub, 4);
5970e6b6b59SJacob Faibussowitsch *dsub = nullptr;
5980e6b6b59SJacob Faibussowitsch /* reserve 4 chars per id, 2 for number and 2 for ', ' separator */
5990e6b6b59SJacob Faibussowitsch if (PetscDefined(USE_DEBUG_AND_INFO)) PetscCallCXX(idList.reserve(4 * n));
6006a4a1270SPierre Jolivet PetscCall(PetscLogEventBegin(DCONTEXT_Fork, dctx, nullptr, nullptr, nullptr));
6010e6b6b59SJacob Faibussowitsch /* update child totals */
6020e6b6b59SJacob Faibussowitsch dctx->numChildren += n;
6030e6b6b59SJacob Faibussowitsch /* now to find out if we have room */
6040e6b6b59SJacob Faibussowitsch if (dctx->numChildren > dctx->maxNumChildren) {
6050e6b6b59SJacob Faibussowitsch const auto numChildren = dctx->numChildren;
6060e6b6b59SJacob Faibussowitsch auto &maxNumChildren = dctx->maxNumChildren;
6070e6b6b59SJacob Faibussowitsch auto numAllocated = numChildren;
6080e6b6b59SJacob Faibussowitsch
6090e6b6b59SJacob Faibussowitsch /* no room, either from having too many kids or not having any */
6100e6b6b59SJacob Faibussowitsch if (auto &childIDs = dctx->childIDs) {
6110e6b6b59SJacob Faibussowitsch // the difference is backwards because we have not updated maxNumChildren yet
6120e6b6b59SJacob Faibussowitsch numAllocated -= maxNumChildren;
6130e6b6b59SJacob Faibussowitsch /* have existing children, must reallocate them */
6140e6b6b59SJacob Faibussowitsch PetscCall(PetscRealloc(numChildren * sizeof(*childIDs), &childIDs));
6150e6b6b59SJacob Faibussowitsch /* clear the extra memory since realloc doesn't do it for us */
6160e6b6b59SJacob Faibussowitsch PetscCall(PetscArrayzero(std::next(childIDs, maxNumChildren), numAllocated));
6170e6b6b59SJacob Faibussowitsch } else {
6180e6b6b59SJacob Faibussowitsch /* have no children */
6190e6b6b59SJacob Faibussowitsch PetscCall(PetscCalloc1(numChildren, &childIDs));
6200e6b6b59SJacob Faibussowitsch }
6210e6b6b59SJacob Faibussowitsch /* update total number of children */
6220e6b6b59SJacob Faibussowitsch maxNumChildren = numChildren;
6230e6b6b59SJacob Faibussowitsch }
6240e6b6b59SJacob Faibussowitsch PetscCall(PetscMalloc1(n, dsub));
6250e6b6b59SJacob Faibussowitsch for (PetscInt i = 0; ninput && (i < dctx->numChildren); ++i) {
6260e6b6b59SJacob Faibussowitsch auto &childID = dctx->childIDs[i];
6270e6b6b59SJacob Faibussowitsch /* empty child slot */
6280e6b6b59SJacob Faibussowitsch if (!childID) {
6290e6b6b59SJacob Faibussowitsch auto &childctx = (*dsub)[i];
6300e6b6b59SJacob Faibussowitsch
6310e6b6b59SJacob Faibussowitsch /* create the child context in the image of its parent */
6320e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextDuplicate_Private(dctx, stype, &childctx));
6330e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextWaitForContext(childctx, dctx));
6340e6b6b59SJacob Faibussowitsch /* register the child with its parent */
6350e6b6b59SJacob Faibussowitsch PetscCall(PetscObjectGetId(PetscObjectCast(childctx), &childID));
6360e6b6b59SJacob Faibussowitsch if (PetscDefined(USE_DEBUG_AND_INFO)) {
6370e6b6b59SJacob Faibussowitsch PetscCallCXX(idList += std::to_string(childID));
6380e6b6b59SJacob Faibussowitsch if (ninput != 1) PetscCallCXX(idList += ", ");
6390e6b6b59SJacob Faibussowitsch }
6400e6b6b59SJacob Faibussowitsch --ninput;
6410e6b6b59SJacob Faibussowitsch }
6420e6b6b59SJacob Faibussowitsch }
6436a4a1270SPierre Jolivet PetscCall(PetscLogEventEnd(DCONTEXT_Fork, dctx, nullptr, nullptr, nullptr));
6440e6b6b59SJacob Faibussowitsch PetscCall(PetscDebugInfo(dctx, "Forked %" PetscInt_FMT " children from parent %" PetscInt64_FMT " with IDs: %s\n", n, PetscObjectCast(dctx)->id, idList.c_str()));
6453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
6460e6b6b59SJacob Faibussowitsch }
6470e6b6b59SJacob Faibussowitsch
648030f984aSJacob Faibussowitsch /*@C
649030f984aSJacob Faibussowitsch PetscDeviceContextFork - Create a set of dependent child contexts from a parent context
650030f984aSJacob Faibussowitsch
651030f984aSJacob Faibussowitsch Not Collective, Asynchronous
652030f984aSJacob Faibussowitsch
653030f984aSJacob Faibussowitsch Input Parameters:
654811af0c4SBarry Smith + dctx - The parent `PetscDeviceContext`
655030f984aSJacob Faibussowitsch - n - The number of children to create
656030f984aSJacob Faibussowitsch
657030f984aSJacob Faibussowitsch Output Parameter:
658030f984aSJacob Faibussowitsch . dsub - The created child context(s)
659030f984aSJacob Faibussowitsch
6602fe279fdSBarry Smith Level: beginner
6612fe279fdSBarry Smith
662030f984aSJacob Faibussowitsch Notes:
6630e6b6b59SJacob Faibussowitsch Behaves identically to `PetscDeviceContextForkWithStreamType()` except that the prescribed
6640e6b6b59SJacob Faibussowitsch `PetscStreamType` is taken from `dctx`. In effect this routine is shorthand for\:
665030f984aSJacob Faibussowitsch
666030f984aSJacob Faibussowitsch .vb
6670e6b6b59SJacob Faibussowitsch PetscStreamType stype;
668030f984aSJacob Faibussowitsch
6690e6b6b59SJacob Faibussowitsch PetscDeviceContextGetStreamType(dctx, &stype);
6700e6b6b59SJacob Faibussowitsch PetscDeviceContextForkWithStreamType(dctx, stype, ...);
671030f984aSJacob Faibussowitsch .ve
672030f984aSJacob Faibussowitsch
6730e6b6b59SJacob Faibussowitsch .N ASYNC_API
6740e6b6b59SJacob Faibussowitsch
6750e6b6b59SJacob Faibussowitsch .seealso: `PetscDeviceContextForkWithStreamType()`, `PetscDeviceContextJoin()`,
6760e6b6b59SJacob Faibussowitsch `PetscDeviceContextSynchronize()`, `PetscDeviceContextQueryIdle()`
677030f984aSJacob Faibussowitsch @*/
PetscDeviceContextFork(PetscDeviceContext dctx,PetscInt n,PetscDeviceContext ** dsub)678d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDeviceContextFork(PetscDeviceContext dctx, PetscInt n, PetscDeviceContext **dsub)
679d71ae5a4SJacob Faibussowitsch {
680d9acb416SHong Zhang auto stype = PETSC_STREAM_DEFAULT;
681030f984aSJacob Faibussowitsch
682030f984aSJacob Faibussowitsch PetscFunctionBegin;
6830e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextGetOptionalNullContext_Internal(&dctx));
6840e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextGetStreamType(dctx, &stype));
6850e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextForkWithStreamType(dctx, stype, n, dsub));
6863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
687030f984aSJacob Faibussowitsch }
688030f984aSJacob Faibussowitsch
68910450e9eSJacob Faibussowitsch // PetscClangLinter pragma disable: -fdoc-section-header-unknown
690030f984aSJacob Faibussowitsch /*@C
6915181c4f9SJacob Faibussowitsch PetscDeviceContextJoin - Converge a set of child contexts
692030f984aSJacob Faibussowitsch
693030f984aSJacob Faibussowitsch Not Collective, Asynchronous
694030f984aSJacob Faibussowitsch
695030f984aSJacob Faibussowitsch Input Parameters:
696811af0c4SBarry Smith + dctx - A `PetscDeviceContext` to converge on
697030f984aSJacob Faibussowitsch . n - The number of sub contexts to converge
698030f984aSJacob Faibussowitsch . joinMode - The type of join to perform
699030f984aSJacob Faibussowitsch - dsub - The sub contexts to converge
700030f984aSJacob Faibussowitsch
7012fe279fdSBarry Smith Level: beginner
7022fe279fdSBarry Smith
703030f984aSJacob Faibussowitsch Notes:
7040e6b6b59SJacob Faibussowitsch If `PetscDeviceContextFork()` creates `n` edges from a source node which all depend on the source
7050e6b6b59SJacob Faibussowitsch node, then this routine is the exact mirror. That is, it creates a node (represented in `dctx`)
70635cb6cd3SPierre Jolivet which receives `n` edges (and optionally destroys them) which is dependent on the completion
7070e6b6b59SJacob Faibussowitsch of all incoming edges.
708030f984aSJacob Faibussowitsch
7090e6b6b59SJacob Faibussowitsch If `joinMode` is `PETSC_DEVICE_CONTEXT_JOIN_DESTROY`. All contexts in `dsub` will be
7100e6b6b59SJacob Faibussowitsch destroyed by this routine. Thus all sub contexts must have been created with the `dctx`
7110e6b6b59SJacob Faibussowitsch passed to this routine.
712030f984aSJacob Faibussowitsch
7130e6b6b59SJacob Faibussowitsch If `joinMode` is `PETSC_DEVICE_CONTEXT_JOIN_SYNC`. All sub contexts will additionally wait on
7140e6b6b59SJacob Faibussowitsch `dctx` after converging. This has the effect of "synchronizing" the outgoing edges. Note the
7150e6b6b59SJacob Faibussowitsch sync suffix does NOT refer to the host, i.e. this routine does NOT call
7160e6b6b59SJacob Faibussowitsch `PetscDeviceSynchronize()`.
717030f984aSJacob Faibussowitsch
7180e6b6b59SJacob Faibussowitsch If `joinMode` is `PETSC_DEVICE_CONTEXT_JOIN_NO_SYNC`. `dctx` waits for all sub contexts but
7190e6b6b59SJacob Faibussowitsch the sub contexts do not wait for one another or `dctx` afterwards.
720030f984aSJacob Faibussowitsch
721030f984aSJacob Faibussowitsch DAG representations:
722811af0c4SBarry Smith If `joinMode` is `PETSC_DEVICE_CONTEXT_JOIN_DESTROY`
723030f984aSJacob Faibussowitsch .vb
724030f984aSJacob Faibussowitsch time ->
725030f984aSJacob Faibussowitsch
7260e6b6b59SJacob Faibussowitsch -> dctx ---------/- |= CALL =| - dctx ->
727030f984aSJacob Faibussowitsch -> dsub[0] -----/
728030f984aSJacob Faibussowitsch -> ... -------/
729030f984aSJacob Faibussowitsch -> dsub[n-1] -/
730030f984aSJacob Faibussowitsch .ve
731811af0c4SBarry Smith If `joinMode` is `PETSC_DEVICE_CONTEXT_JOIN_SYNC`
732030f984aSJacob Faibussowitsch .vb
733030f984aSJacob Faibussowitsch time ->
734030f984aSJacob Faibussowitsch
7350e6b6b59SJacob Faibussowitsch -> dctx ---------/- |= CALL =| -\----> dctx ------>
736030f984aSJacob Faibussowitsch -> dsub[0] -----/ \---> dsub[0] --->
737030f984aSJacob Faibussowitsch -> ... -------/ \--> ... ------->
738030f984aSJacob Faibussowitsch -> dsub[n-1] -/ \-> dsub[n-1] ->
739030f984aSJacob Faibussowitsch .ve
7400e6b6b59SJacob Faibussowitsch If `joinMode` is `PETSC_DEVICE_CONTEXT_JOIN_NO_SYNC`
7410e6b6b59SJacob Faibussowitsch .vb
7420e6b6b59SJacob Faibussowitsch time ->
743030f984aSJacob Faibussowitsch
7440e6b6b59SJacob Faibussowitsch -> dctx ----------/- |= CALL =| - dctx ->
7450e6b6b59SJacob Faibussowitsch -> dsub[0] ------/----------------------->
7460e6b6b59SJacob Faibussowitsch -> ... --------/------------------------>
7470e6b6b59SJacob Faibussowitsch -> dsub[n-1] --/------------------------->
7480e6b6b59SJacob Faibussowitsch .ve
749030f984aSJacob Faibussowitsch
7500e6b6b59SJacob Faibussowitsch .N ASYNC_API
7510e6b6b59SJacob Faibussowitsch
7520e6b6b59SJacob Faibussowitsch .seealso: `PetscDeviceContextFork()`, `PetscDeviceContextForkWithStreamType()`,
7530e6b6b59SJacob Faibussowitsch `PetscDeviceContextSynchronize()`, `PetscDeviceContextJoinMode`
754030f984aSJacob Faibussowitsch @*/
PetscDeviceContextJoin(PetscDeviceContext dctx,PetscInt n,PetscDeviceContextJoinMode joinMode,PetscDeviceContext ** dsub)755d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDeviceContextJoin(PetscDeviceContext dctx, PetscInt n, PetscDeviceContextJoinMode joinMode, PetscDeviceContext **dsub)
756d71ae5a4SJacob Faibussowitsch {
7570e6b6b59SJacob Faibussowitsch // debugging only
7580e6b6b59SJacob Faibussowitsch std::string idList;
759030f984aSJacob Faibussowitsch
760030f984aSJacob Faibussowitsch PetscFunctionBegin;
7610e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextGetOptionalNullContext_Internal(&dctx));
762030f984aSJacob Faibussowitsch /* validity of dctx is checked in the wait-for loop */
7634f572ea9SToby Isaac PetscAssertPointer(dsub, 4);
764bf025ffbSJacob Faibussowitsch PetscAssert(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of contexts merged %" PetscInt_FMT " < 0", n);
765030f984aSJacob Faibussowitsch /* reserve 4 chars per id, 2 for number and 2 for ', ' separator */
7660e6b6b59SJacob Faibussowitsch if (PetscDefined(USE_DEBUG_AND_INFO)) PetscCallCXX(idList.reserve(4 * n));
767030f984aSJacob Faibussowitsch /* first dctx waits on all the incoming edges */
7686a4a1270SPierre Jolivet PetscCall(PetscLogEventBegin(DCONTEXT_Join, dctx, nullptr, nullptr, nullptr));
769030f984aSJacob Faibussowitsch for (PetscInt i = 0; i < n; ++i) {
770030f984aSJacob Faibussowitsch PetscCheckCompatibleDeviceContexts(dctx, 1, (*dsub)[i], 4);
7719566063dSJacob Faibussowitsch PetscCall(PetscDeviceContextWaitForContext(dctx, (*dsub)[i]));
7720e6b6b59SJacob Faibussowitsch if (PetscDefined(USE_DEBUG_AND_INFO)) {
7730e6b6b59SJacob Faibussowitsch PetscCallCXX(idList += std::to_string(PetscObjectCast((*dsub)[i])->id));
7740e6b6b59SJacob Faibussowitsch if (i + 1 < n) PetscCallCXX(idList += ", ");
7750e6b6b59SJacob Faibussowitsch }
776030f984aSJacob Faibussowitsch }
777030f984aSJacob Faibussowitsch
778030f984aSJacob Faibussowitsch /* now we handle the aftermath */
779030f984aSJacob Faibussowitsch switch (joinMode) {
7809371c9d4SSatish Balay case PETSC_DEVICE_CONTEXT_JOIN_DESTROY: {
7810e6b6b59SJacob Faibussowitsch const auto children = dctx->childIDs;
7820e6b6b59SJacob Faibussowitsch const auto maxchild = dctx->maxNumChildren;
7830e6b6b59SJacob Faibussowitsch auto &nchild = dctx->numChildren;
784030f984aSJacob Faibussowitsch PetscInt j = 0;
785030f984aSJacob Faibussowitsch
7860e6b6b59SJacob 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);
787030f984aSJacob Faibussowitsch /* update child count while it's still fresh in memory */
7880e6b6b59SJacob Faibussowitsch nchild -= n;
7890e6b6b59SJacob Faibussowitsch for (PetscInt i = 0; i < maxchild; ++i) {
7900e6b6b59SJacob Faibussowitsch if (children[i] && (children[i] == PetscObjectCast((*dsub)[j])->id)) {
791030f984aSJacob Faibussowitsch /* child is one of ours, can destroy it */
7929566063dSJacob Faibussowitsch PetscCall(PetscDeviceContextDestroy((*dsub) + j));
793030f984aSJacob Faibussowitsch /* reset the child slot */
7940e6b6b59SJacob Faibussowitsch children[i] = 0;
795030f984aSJacob Faibussowitsch if (++j == n) break;
796030f984aSJacob Faibussowitsch }
797030f984aSJacob Faibussowitsch }
7980e6b6b59SJacob Faibussowitsch /* gone through the loop but did not find every child */
79915229ffcSPierre Jolivet 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 in", n - j);
8009566063dSJacob Faibussowitsch PetscCall(PetscFree(*dsub));
8019371c9d4SSatish Balay } break;
802030f984aSJacob Faibussowitsch case PETSC_DEVICE_CONTEXT_JOIN_SYNC:
8039566063dSJacob Faibussowitsch for (PetscInt i = 0; i < n; ++i) PetscCall(PetscDeviceContextWaitForContext((*dsub)[i], dctx));
804d71ae5a4SJacob Faibussowitsch case PETSC_DEVICE_CONTEXT_JOIN_NO_SYNC:
805d71ae5a4SJacob Faibussowitsch break;
806d71ae5a4SJacob Faibussowitsch default:
807d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown PetscDeviceContextJoinMode given");
808030f984aSJacob Faibussowitsch }
8096a4a1270SPierre Jolivet PetscCall(PetscLogEventEnd(DCONTEXT_Join, dctx, nullptr, nullptr, nullptr));
810030f984aSJacob Faibussowitsch
8110e6b6b59SJacob 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()));
8123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
813030f984aSJacob Faibussowitsch }
814030f984aSJacob Faibussowitsch
81510450e9eSJacob Faibussowitsch // PetscClangLinter pragma disable: -fdoc-section-header-unknown
816030f984aSJacob Faibussowitsch /*@C
8170e6b6b59SJacob Faibussowitsch PetscDeviceContextSynchronize - Block the host until all work queued on a
8180e6b6b59SJacob Faibussowitsch `PetscDeviceContext` has finished
819030f984aSJacob Faibussowitsch
8200e6b6b59SJacob Faibussowitsch Not Collective
821030f984aSJacob Faibussowitsch
8222fe279fdSBarry Smith Input Parameter:
823811af0c4SBarry Smith . dctx - The `PetscDeviceContext` to synchronize
824030f984aSJacob Faibussowitsch
8252fe279fdSBarry Smith Level: beginner
8262fe279fdSBarry Smith
8270e6b6b59SJacob Faibussowitsch Notes:
8280e6b6b59SJacob Faibussowitsch The host will not return from this routine until `dctx` is idle. Any and all memory
8290e6b6b59SJacob Faibussowitsch operations queued on or otherwise associated with (either explicitly or implicitly via
8300e6b6b59SJacob Faibussowitsch dependencies) are guaranteed to have finished and be globally visible on return.
8310e6b6b59SJacob Faibussowitsch
8320e6b6b59SJacob Faibussowitsch In effect, this routine serves as memory and execution barrier.
8330e6b6b59SJacob Faibussowitsch
8340e6b6b59SJacob Faibussowitsch DAG representation:
8350e6b6b59SJacob Faibussowitsch .vb
8360e6b6b59SJacob Faibussowitsch time ->
8370e6b6b59SJacob Faibussowitsch
8380e6b6b59SJacob Faibussowitsch -> dctx - |= CALL =| - dctx ->
8390e6b6b59SJacob Faibussowitsch .ve
8400e6b6b59SJacob Faibussowitsch
841db781477SPatrick Sanan .seealso: `PetscDeviceContextFork()`, `PetscDeviceContextJoin()`, `PetscDeviceContextQueryIdle()`
842030f984aSJacob Faibussowitsch @*/
PetscDeviceContextSynchronize(PetscDeviceContext dctx)843d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDeviceContextSynchronize(PetscDeviceContext dctx)
844d71ae5a4SJacob Faibussowitsch {
845030f984aSJacob Faibussowitsch PetscFunctionBegin;
8460e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextGetOptionalNullContext_Internal(&dctx));
8476a4a1270SPierre Jolivet PetscCall(PetscLogEventBegin(DCONTEXT_Sync, dctx, nullptr, nullptr, nullptr));
848030f984aSJacob Faibussowitsch /* if it isn't setup there is nothing to sync on */
8490e6b6b59SJacob Faibussowitsch if (dctx->setup) {
8502f85e401SJacob Faibussowitsch PetscUseTypeMethod(dctx, synchronize);
8510e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextSyncClearMap_Internal(dctx));
8520e6b6b59SJacob Faibussowitsch }
8536a4a1270SPierre Jolivet PetscCall(PetscLogEventEnd(DCONTEXT_Sync, dctx, nullptr, nullptr, nullptr));
8543ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
855030f984aSJacob Faibussowitsch }
856030f984aSJacob Faibussowitsch
8570e6b6b59SJacob Faibussowitsch /* every device type has a vector of null PetscDeviceContexts -- one for each device */
8580e6b6b59SJacob Faibussowitsch static auto nullContexts = std::array<std::vector<PetscDeviceContext>, PETSC_DEVICE_MAX>{};
8590e6b6b59SJacob Faibussowitsch static auto nullContextsFinalizer = false;
860030f984aSJacob Faibussowitsch
PetscDeviceContextGetNullContextForDevice_Private(PetscBool user_set_device,PetscDevice device,PetscDeviceContext * dctx)861d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscDeviceContextGetNullContextForDevice_Private(PetscBool user_set_device, PetscDevice device, PetscDeviceContext *dctx)
862d71ae5a4SJacob Faibussowitsch {
8630e6b6b59SJacob Faibussowitsch PetscInt devid;
8640e6b6b59SJacob Faibussowitsch PetscDeviceType dtype;
865a4af0ceeSJacob Faibussowitsch
866030f984aSJacob Faibussowitsch PetscFunctionBegin;
8670e6b6b59SJacob Faibussowitsch PetscValidDevice(device, 2);
8684f572ea9SToby Isaac PetscAssertPointer(dctx, 3);
8690e6b6b59SJacob Faibussowitsch if (PetscUnlikely(!nullContextsFinalizer)) {
8703048253cSJacob Faibussowitsch nullContextsFinalizer = true;
8713048253cSJacob Faibussowitsch PetscCall(PetscRegisterFinalize([] {
8720e6b6b59SJacob Faibussowitsch PetscFunctionBegin;
8730e6b6b59SJacob Faibussowitsch for (auto &&dvec : nullContexts) {
8740e6b6b59SJacob Faibussowitsch for (auto &&dctx : dvec) PetscCall(PetscDeviceContextDestroy(&dctx));
8750e6b6b59SJacob Faibussowitsch PetscCallCXX(dvec.clear());
876030f984aSJacob Faibussowitsch }
8770e6b6b59SJacob Faibussowitsch nullContextsFinalizer = false;
8783ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
8793048253cSJacob Faibussowitsch }));
8800e6b6b59SJacob Faibussowitsch }
8810e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceGetDeviceId(device, &devid));
8820e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceGetType(device, &dtype));
8830e6b6b59SJacob Faibussowitsch {
8840e6b6b59SJacob Faibussowitsch auto &ctxlist = nullContexts[dtype];
8850e6b6b59SJacob Faibussowitsch
8860e6b6b59SJacob Faibussowitsch PetscCheck(devid >= 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Device ID (%" PetscInt_FMT ") must be positive", devid);
8870e6b6b59SJacob Faibussowitsch // need to resize the container if not big enough because incrementing the iterator in
8880e6b6b59SJacob Faibussowitsch // std::next() (if we haven't initialized that ctx yet) may cause it to fall outside the
8890e6b6b59SJacob Faibussowitsch // current size of the container.
8900e6b6b59SJacob Faibussowitsch if (static_cast<std::size_t>(devid) >= ctxlist.size()) PetscCallCXX(ctxlist.resize(devid + 1));
8910e6b6b59SJacob Faibussowitsch if (PetscUnlikely(!ctxlist[devid])) {
8920e6b6b59SJacob Faibussowitsch // we have not seen this device before
8930e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextCreate(dctx));
894403f9ca4SJacob Faibussowitsch PetscCall(PetscInfo(*dctx, "Initializing null PetscDeviceContext (of type %s) for device %" PetscInt_FMT "\n", PetscDeviceTypes[dtype], devid));
8950e6b6b59SJacob Faibussowitsch {
8960e6b6b59SJacob Faibussowitsch const auto pobj = PetscObjectCast(*dctx);
8970e6b6b59SJacob Faibussowitsch const auto name = "null context " + std::to_string(devid);
8980e6b6b59SJacob Faibussowitsch const auto prefix = "null_context_" + std::to_string(devid) + '_';
8990e6b6b59SJacob Faibussowitsch
9000e6b6b59SJacob Faibussowitsch PetscCall(PetscObjectSetName(pobj, name.c_str()));
9010e6b6b59SJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix(pobj, prefix.c_str()));
9020e6b6b59SJacob Faibussowitsch }
903d9acb416SHong Zhang PetscCall(PetscDeviceContextSetStreamType(*dctx, PETSC_STREAM_DEFAULT));
9040e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextSetDevice_Private(*dctx, device, user_set_device));
9050e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextSetUp(*dctx));
9060e6b6b59SJacob Faibussowitsch // would use ctxlist.cbegin() but GCC 4.8 can't handle const iterator insert!
9070e6b6b59SJacob Faibussowitsch PetscCallCXX(ctxlist.insert(std::next(ctxlist.begin(), devid), *dctx));
9080e6b6b59SJacob Faibussowitsch } else *dctx = ctxlist[devid];
9090e6b6b59SJacob Faibussowitsch }
9103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
911030f984aSJacob Faibussowitsch }
912030f984aSJacob Faibussowitsch
9130e6b6b59SJacob Faibussowitsch /*
9140e6b6b59SJacob Faibussowitsch Gets the "NULL" context for the current PetscDeviceType and PetscDevice. NULL contexts are
9150e6b6b59SJacob Faibussowitsch guaranteed to always be globally blocking.
9160e6b6b59SJacob Faibussowitsch */
PetscDeviceContextGetNullContext_Internal(PetscDeviceContext * dctx)917d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDeviceContextGetNullContext_Internal(PetscDeviceContext *dctx)
918d71ae5a4SJacob Faibussowitsch {
9190e6b6b59SJacob Faibussowitsch PetscDeviceContext gctx;
9200e6b6b59SJacob Faibussowitsch PetscDevice gdev = nullptr;
921030f984aSJacob Faibussowitsch
922a4af0ceeSJacob Faibussowitsch PetscFunctionBegin;
9234f572ea9SToby Isaac PetscAssertPointer(dctx, 1);
9240e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextGetCurrentContext(&gctx));
9250e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextGetDevice(gctx, &gdev));
9260e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextGetNullContextForDevice_Private(gctx->usersetdevice, gdev, dctx));
9273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
928030f984aSJacob Faibussowitsch }
929030f984aSJacob Faibussowitsch
930030f984aSJacob Faibussowitsch /*@C
931811af0c4SBarry Smith PetscDeviceContextSetFromOptions - Configure a `PetscDeviceContext` from the options database
932030f984aSJacob Faibussowitsch
9330e6b6b59SJacob Faibussowitsch Collective on `comm` or `dctx`
934030f984aSJacob Faibussowitsch
935030f984aSJacob Faibussowitsch Input Parameters:
9360e6b6b59SJacob Faibussowitsch + comm - MPI communicator on which to query the options database (optional)
937811af0c4SBarry Smith - dctx - The `PetscDeviceContext` to configure
938030f984aSJacob Faibussowitsch
939030f984aSJacob Faibussowitsch Output Parameter:
940811af0c4SBarry Smith . dctx - The `PetscDeviceContext`
941030f984aSJacob Faibussowitsch
9423c7db156SBarry Smith Options Database Keys:
9430e6b6b59SJacob Faibussowitsch + -device_context_stream_type - type of stream to create inside the `PetscDeviceContext` -
9440e6b6b59SJacob Faibussowitsch `PetscDeviceContextSetStreamType()`
945811af0c4SBarry Smith - -device_context_device_type - the type of `PetscDevice` to attach by default - `PetscDeviceType`
946030f984aSJacob Faibussowitsch
9472fe279fdSBarry Smith Level: beginner
9482fe279fdSBarry Smith
9492fe279fdSBarry Smith Note:
9500e6b6b59SJacob Faibussowitsch The user may pass `MPI_COMM_NULL` for `comm` in which case the communicator of `dctx` is
9510e6b6b59SJacob Faibussowitsch used (which is always `PETSC_COMM_SELF`).
9520e6b6b59SJacob Faibussowitsch
9530e6b6b59SJacob Faibussowitsch .seealso: `PetscDeviceContextSetStreamType()`, `PetscDeviceContextSetDevice()`,
9540e6b6b59SJacob Faibussowitsch `PetscDeviceContextView()`
955030f984aSJacob Faibussowitsch @*/
PetscDeviceContextSetFromOptions(MPI_Comm comm,PetscDeviceContext dctx)956d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDeviceContextSetFromOptions(MPI_Comm comm, PetscDeviceContext dctx)
957d71ae5a4SJacob Faibussowitsch {
9580e6b6b59SJacob Faibussowitsch const auto pobj = PetscObjectCast(dctx);
9590e6b6b59SJacob Faibussowitsch auto dtype = std::make_pair(PETSC_DEVICE_DEFAULT(), PETSC_FALSE);
9600e6b6b59SJacob Faibussowitsch auto stype = std::make_pair(PETSC_DEVICE_CONTEXT_DEFAULT_STREAM_TYPE, PETSC_FALSE);
961e6b8bd2aSJacob Faibussowitsch MPI_Comm old_comm = PETSC_COMM_SELF;
962030f984aSJacob Faibussowitsch
963030f984aSJacob Faibussowitsch PetscFunctionBegin;
9640e6b6b59SJacob Faibussowitsch // do not user getoptionalnullcontext here, the user is not allowed to set it from options!
9650e6b6b59SJacob Faibussowitsch PetscValidDeviceContext(dctx, 2);
9660e6b6b59SJacob Faibussowitsch /* set the device type first */
9670e6b6b59SJacob Faibussowitsch if (const auto device = dctx->device) PetscCall(PetscDeviceGetType(device, &dtype.first));
9680e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextGetStreamType(dctx, &stype.first));
9690e6b6b59SJacob Faibussowitsch
9700e6b6b59SJacob Faibussowitsch if (comm == MPI_COMM_NULL) {
9710e6b6b59SJacob Faibussowitsch PetscCall(PetscObjectGetComm(pobj, &comm));
9720e6b6b59SJacob Faibussowitsch } else {
9730e6b6b59SJacob Faibussowitsch // briefly set the communicator for dctx (it is always PETSC_COMM_SELF) so
9740e6b6b59SJacob Faibussowitsch // PetscObjectOptionsBegin() behaves as if dctx had comm
9750e6b6b59SJacob Faibussowitsch old_comm = Petsc::util::exchange(pobj->comm, comm);
9760e6b6b59SJacob Faibussowitsch }
9770e6b6b59SJacob Faibussowitsch
9780e6b6b59SJacob Faibussowitsch PetscObjectOptionsBegin(pobj);
9790e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextQueryOptions_Internal(PetscOptionsObject, dtype, stype));
980d0609cedSBarry Smith PetscOptionsEnd();
9810e6b6b59SJacob Faibussowitsch // reset the comm (should be PETSC_COMM_SELF)
9820e6b6b59SJacob Faibussowitsch if (comm != MPI_COMM_NULL) pobj->comm = old_comm;
9830e6b6b59SJacob Faibussowitsch if (dtype.second) PetscCall(PetscDeviceContextSetDefaultDeviceForType_Internal(dctx, dtype.first));
9840e6b6b59SJacob Faibussowitsch if (stype.second) PetscCall(PetscDeviceContextSetStreamType(dctx, stype.first));
9850e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextSetUp(dctx));
9863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
9870e6b6b59SJacob Faibussowitsch }
9880e6b6b59SJacob Faibussowitsch
989ffeef943SBarry Smith /*@
9900e6b6b59SJacob Faibussowitsch PetscDeviceContextView - View a `PetscDeviceContext`
9910e6b6b59SJacob Faibussowitsch
9920e6b6b59SJacob Faibussowitsch Collective on `viewer`
9930e6b6b59SJacob Faibussowitsch
9940e6b6b59SJacob Faibussowitsch Input Parameters:
9950e6b6b59SJacob Faibussowitsch + dctx - The `PetscDeviceContext`
9960e6b6b59SJacob Faibussowitsch - viewer - The `PetscViewer` to view `dctx` with (may be `NULL`)
9970e6b6b59SJacob Faibussowitsch
9982fe279fdSBarry Smith Level: beginner
9992fe279fdSBarry Smith
10002fe279fdSBarry Smith Note:
10010e6b6b59SJacob Faibussowitsch If `viewer` is `NULL`, `PETSC_VIEWER_STDOUT_WORLD` is used instead, in which case this
10020e6b6b59SJacob Faibussowitsch routine is collective on `PETSC_COMM_WORLD`.
10030e6b6b59SJacob Faibussowitsch
10040e6b6b59SJacob Faibussowitsch .seealso: `PetscDeviceContextViewFromOptions()`, `PetscDeviceView()`, `PETSC_VIEWER_STDOUT_WORLD`, `PetscDeviceContextCreate()`
10050e6b6b59SJacob Faibussowitsch @*/
PetscDeviceContextView(PetscDeviceContext dctx,PetscViewer viewer)1006d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDeviceContextView(PetscDeviceContext dctx, PetscViewer viewer)
1007d71ae5a4SJacob Faibussowitsch {
1008*9f196a02SMartin Diehl PetscBool isascii;
10090e6b6b59SJacob Faibussowitsch
10100e6b6b59SJacob Faibussowitsch PetscFunctionBegin;
10110e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextGetOptionalNullContext_Internal(&dctx));
10120e6b6b59SJacob Faibussowitsch if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PETSC_COMM_WORLD, &viewer));
10130e6b6b59SJacob Faibussowitsch PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1014*9f196a02SMartin Diehl PetscCall(PetscObjectTypeCompare(PetscObjectCast(viewer), PETSCVIEWERASCII, &isascii));
1015*9f196a02SMartin Diehl if (isascii) {
1016d9acb416SHong Zhang auto stype = PETSC_STREAM_DEFAULT;
10170e6b6b59SJacob Faibussowitsch PetscViewer sub;
10180e6b6b59SJacob Faibussowitsch
10190e6b6b59SJacob Faibussowitsch PetscCall(PetscViewerGetSubViewer(viewer, PETSC_COMM_SELF, &sub));
10200e6b6b59SJacob Faibussowitsch PetscCall(PetscObjectPrintClassNamePrefixType(PetscObjectCast(dctx), sub));
10210e6b6b59SJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(sub));
10220e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextGetStreamType(dctx, &stype));
10230e6b6b59SJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(sub, "stream type: %s\n", PetscStreamTypes[stype]));
10240e6b6b59SJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(sub, "children: %" PetscInt_FMT "\n", dctx->numChildren));
10250e6b6b59SJacob Faibussowitsch if (const auto nchild = dctx->numChildren) {
10260e6b6b59SJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(sub));
10270e6b6b59SJacob Faibussowitsch for (PetscInt i = 0; i < nchild; ++i) {
10280e6b6b59SJacob Faibussowitsch if (i == nchild - 1) {
10290e6b6b59SJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(sub, "%" PetscInt64_FMT, dctx->childIDs[i]));
10300e6b6b59SJacob Faibussowitsch } else {
10310e6b6b59SJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(sub, "%" PetscInt64_FMT ", ", dctx->childIDs[i]));
10320e6b6b59SJacob Faibussowitsch }
10330e6b6b59SJacob Faibussowitsch }
10340e6b6b59SJacob Faibussowitsch }
10350e6b6b59SJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(sub));
10360e6b6b59SJacob Faibussowitsch PetscCall(PetscViewerRestoreSubViewer(viewer, PETSC_COMM_SELF, &sub));
10370e6b6b59SJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer));
10380e6b6b59SJacob Faibussowitsch }
10390e6b6b59SJacob Faibussowitsch if (const auto device = dctx->device) PetscCall(PetscDeviceView(device, viewer));
1040*9f196a02SMartin Diehl if (isascii) PetscCall(PetscViewerASCIIPopTab(viewer));
10413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
10420e6b6b59SJacob Faibussowitsch }
10430e6b6b59SJacob Faibussowitsch
1044ffeef943SBarry Smith /*@
10450e6b6b59SJacob Faibussowitsch PetscDeviceContextViewFromOptions - View a `PetscDeviceContext` from options
10460e6b6b59SJacob Faibussowitsch
10470e6b6b59SJacob Faibussowitsch Input Parameters:
10480e6b6b59SJacob Faibussowitsch + dctx - The `PetscDeviceContext` to view
10490e6b6b59SJacob Faibussowitsch . obj - Optional `PetscObject` to associate (may be `NULL`)
10500e6b6b59SJacob Faibussowitsch - name - The command line option
10510e6b6b59SJacob Faibussowitsch
10520e6b6b59SJacob Faibussowitsch Level: beginner
10530e6b6b59SJacob Faibussowitsch
10540e6b6b59SJacob Faibussowitsch .seealso: `PetscDeviceContextView()`, `PetscObjectViewFromOptions()`, `PetscDeviceContextCreate()`
10550e6b6b59SJacob Faibussowitsch @*/
PetscDeviceContextViewFromOptions(PetscDeviceContext dctx,PetscObject obj,const char name[])1056d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDeviceContextViewFromOptions(PetscDeviceContext dctx, PetscObject obj, const char name[])
1057d71ae5a4SJacob Faibussowitsch {
10580e6b6b59SJacob Faibussowitsch PetscFunctionBegin;
10590e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceContextGetOptionalNullContext_Internal(&dctx));
10600e6b6b59SJacob Faibussowitsch if (obj) PetscValidHeader(obj, 2);
10614f572ea9SToby Isaac PetscAssertPointer(name, 3);
10620e6b6b59SJacob Faibussowitsch PetscCall(PetscObjectViewFromOptions(PetscObjectCast(dctx), obj, name));
10633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1064030f984aSJacob Faibussowitsch }
106531d47070SJunchao Zhang
106631d47070SJunchao Zhang /*@C
106731d47070SJunchao Zhang PetscDeviceContextGetStreamHandle - Return a handle to the underlying stream of the current device context
106831d47070SJunchao Zhang
10698a4d221bSJacob Faibussowitsch Input Parameter:
10708a4d221bSJacob Faibussowitsch . dctx - The `PetscDeviceContext` to get the stream from
10718a4d221bSJacob Faibussowitsch
10728a4d221bSJacob Faibussowitsch Output Parameter:
10738a4d221bSJacob Faibussowitsch . handle - A pointer to the handle to the stream
107431d47070SJunchao Zhang
107531d47070SJunchao Zhang Level: developer
107631d47070SJunchao Zhang
107731d47070SJunchao Zhang Note:
107831d47070SJunchao Zhang This routine is dangerous. It exists only for the most experienced users and
1079baca6076SPierre Jolivet internal PETSc development.
108031d47070SJunchao Zhang
108131d47070SJunchao Zhang There is no way for PETSc's auto-dependency system to track what the caller does with the
108231d47070SJunchao Zhang stream.
108331d47070SJunchao Zhang
108431d47070SJunchao Zhang If the user uses the stream to copy memory that was previously modified by PETSc, or launches
108531d47070SJunchao Zhang kernels that modify memory with the stream, it is the users responsibility to inform PETSc of
108631d47070SJunchao Zhang their actions via `PetscDeviceContextMarkIntentFromID()`. Failure to do so may introduce a
108731d47070SJunchao Zhang race condition. This race condition may manifest in nondeterministic ways.
108831d47070SJunchao Zhang
108931d47070SJunchao Zhang Alternatively, the user may synchronize the stream immediately before and after use. This is
109031d47070SJunchao Zhang the safest option.
109131d47070SJunchao Zhang
109231d47070SJunchao Zhang Example Usage:
109331d47070SJunchao Zhang .vb
109431d47070SJunchao Zhang PetscDeviceContext dctx;
109531d47070SJunchao Zhang PetscDeviceType type;
109631d47070SJunchao Zhang void *handle;
109731d47070SJunchao Zhang
109831d47070SJunchao Zhang PetscDeviceContextGetCurrentContext(&dctx);
109931d47070SJunchao Zhang PetscDeviceContextGetStreamHandle(dctx, &handle);
110031d47070SJunchao Zhang PetscDeviceContextGetDeviceType(dctx, &type);
110131d47070SJunchao Zhang
110231d47070SJunchao Zhang if (type == PETSC_DEVICE_CUDA) {
11031d4998e7SJacob Faibussowitsch cudaStream_t stream = *(cudaStream_t *)handle;
110431d47070SJunchao Zhang
110531d47070SJunchao Zhang my_cuda_kernel<<<1, 2, 3, stream>>>();
110631d47070SJunchao Zhang }
110731d47070SJunchao Zhang .ve
11088a4d221bSJacob Faibussowitsch Alternatively, if type of `PetscDeviceContext` is known (for example `PETSC_DEVICE_HIP`), the
11098a4d221bSJacob Faibussowitsch user may pass in a pointer to stream handle directly\:
11108a4d221bSJacob Faibussowitsch .vb
11118a4d221bSJacob Faibussowitsch hipStream_t *stream;
11128a4d221bSJacob Faibussowitsch
11138a4d221bSJacob Faibussowitsch // note the cast to void **
11148a4d221bSJacob Faibussowitsch PetscDeviceContextGetStreamHandle(dctx, (void **)&stream);
11158a4d221bSJacob Faibussowitsch // note the dereference
11168a4d221bSJacob Faibussowitsch my_hip_kernel<<<1, 2, 3, *stream>>>();
11178a4d221bSJacob Faibussowitsch .ve
111831d47070SJunchao Zhang
111931d47070SJunchao Zhang .N ASYNC_API
112031d47070SJunchao Zhang
112131d47070SJunchao Zhang .seealso: `PetscDeviceContext`
112231d47070SJunchao Zhang @*/
PetscDeviceContextGetStreamHandle(PetscDeviceContext dctx,void ** handle)11238a4d221bSJacob Faibussowitsch PetscErrorCode PetscDeviceContextGetStreamHandle(PetscDeviceContext dctx, void **handle)
112431d47070SJunchao Zhang {
112531d47070SJunchao Zhang PetscFunctionBegin;
112631d47070SJunchao Zhang PetscCall(PetscDeviceContextGetOptionalNullContext_Internal(&dctx));
11274f572ea9SToby Isaac PetscAssertPointer(handle, 2);
11288a4d221bSJacob Faibussowitsch PetscCall(PetscDeviceContextGetStreamHandle_Internal(dctx, handle));
112931d47070SJunchao Zhang PetscFunctionReturn(PETSC_SUCCESS);
113031d47070SJunchao Zhang }
1131