xref: /petsc/src/sys/objects/device/interface/dcontext.cxx (revision 01d2d390730c28cfe35baf9a99c995b559d5489f)
1030f984aSJacob Faibussowitsch #include <petsc/private/deviceimpl.h> /*I "petscdevice.h" I*/
2030f984aSJacob Faibussowitsch #include "objpool.hpp"
3030f984aSJacob Faibussowitsch 
4030f984aSJacob Faibussowitsch /* Define the allocator */
5030f984aSJacob Faibussowitsch struct PetscDeviceContextAllocator : Petsc::Allocator<PetscDeviceContext>
6030f984aSJacob Faibussowitsch {
7030f984aSJacob Faibussowitsch   static PetscInt PetscDeviceContextID;
8030f984aSJacob Faibussowitsch 
9030f984aSJacob Faibussowitsch   PETSC_NODISCARD PetscErrorCode create(PetscDeviceContext *dctx) noexcept
10030f984aSJacob Faibussowitsch   {
11030f984aSJacob Faibussowitsch     PetscDeviceContext dc;
12030f984aSJacob Faibussowitsch     PetscErrorCode     ierr;
13030f984aSJacob Faibussowitsch 
14030f984aSJacob Faibussowitsch     PetscFunctionBegin;
15030f984aSJacob Faibussowitsch     ierr           = PetscNew(&dc);CHKERRQ(ierr);
16030f984aSJacob Faibussowitsch     dc->id         = PetscDeviceContextID++;
17030f984aSJacob Faibussowitsch     dc->idle       = PETSC_TRUE;
18030f984aSJacob Faibussowitsch     dc->streamType = PETSC_STREAM_DEFAULT_BLOCKING;
19030f984aSJacob Faibussowitsch     *dctx          = dc;
20030f984aSJacob Faibussowitsch     PetscFunctionReturn(0);
21030f984aSJacob Faibussowitsch   }
22030f984aSJacob Faibussowitsch 
23030f984aSJacob Faibussowitsch   PETSC_NODISCARD PetscErrorCode destroy(PetscDeviceContext &dctx) const noexcept
24030f984aSJacob Faibussowitsch   {
25030f984aSJacob Faibussowitsch     PetscErrorCode ierr;
26030f984aSJacob Faibussowitsch 
27030f984aSJacob Faibussowitsch     PetscFunctionBegin;
28030f984aSJacob Faibussowitsch     if (PetscUnlikelyDebug(dctx->numChildren)) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Device context still has %D un-restored children, must call PetscDeviceContextRestore() on all children before destroying",dctx->numChildren);
29030f984aSJacob Faibussowitsch     if (dctx->ops->destroy) {ierr = (*dctx->ops->destroy)(dctx);CHKERRQ(ierr);}
30030f984aSJacob Faibussowitsch     ierr = PetscDeviceDestroy(&dctx->device);CHKERRQ(ierr);
31030f984aSJacob Faibussowitsch     ierr = PetscFree(dctx->childIDs);CHKERRQ(ierr);
32030f984aSJacob Faibussowitsch     ierr = PetscFree(dctx);CHKERRQ(ierr);
33030f984aSJacob Faibussowitsch     PetscFunctionReturn(0);
34030f984aSJacob Faibussowitsch   }
35030f984aSJacob Faibussowitsch 
36030f984aSJacob Faibussowitsch   PETSC_NODISCARD PetscErrorCode reset(PetscDeviceContext &dctx) const noexcept
37030f984aSJacob Faibussowitsch   {
38030f984aSJacob Faibussowitsch     PetscErrorCode ierr;
39030f984aSJacob Faibussowitsch 
40030f984aSJacob Faibussowitsch     PetscFunctionBegin;
41030f984aSJacob Faibussowitsch     /* don't deallocate the child array, rather just zero it out */
42030f984aSJacob Faibussowitsch     ierr = PetscArrayzero(dctx->childIDs,dctx->maxNumChildren);CHKERRQ(ierr);
43030f984aSJacob Faibussowitsch     dctx->setup       = PETSC_FALSE;
44030f984aSJacob Faibussowitsch     dctx->numChildren = 0;
45030f984aSJacob Faibussowitsch     dctx->idle        = PETSC_TRUE;
46030f984aSJacob Faibussowitsch     dctx->streamType  = PETSC_STREAM_DEFAULT_BLOCKING;
47030f984aSJacob Faibussowitsch     PetscFunctionReturn(0);
48030f984aSJacob Faibussowitsch   }
49030f984aSJacob Faibussowitsch 
50030f984aSJacob Faibussowitsch   PETSC_NODISCARD PetscErrorCode finalize(void) noexcept
51030f984aSJacob Faibussowitsch   {
52030f984aSJacob Faibussowitsch     PetscFunctionBegin;
53030f984aSJacob Faibussowitsch     PetscDeviceContextID = 0;
54030f984aSJacob Faibussowitsch     PetscFunctionReturn(0);
55030f984aSJacob Faibussowitsch   }
56030f984aSJacob Faibussowitsch };
57030f984aSJacob Faibussowitsch PetscInt PetscDeviceContextAllocator::PetscDeviceContextID = 0;
58030f984aSJacob Faibussowitsch 
59030f984aSJacob Faibussowitsch static Petsc::ObjectPool<PetscDeviceContext,PetscDeviceContextAllocator> contextPool;
60030f984aSJacob Faibussowitsch 
61030f984aSJacob Faibussowitsch /*@C
62030f984aSJacob Faibussowitsch   PetscDeviceContextCreate - Creates a PetscDeviceContext
63030f984aSJacob Faibussowitsch 
64030f984aSJacob Faibussowitsch   Not Collective, Asynchronous
65030f984aSJacob Faibussowitsch 
66*01d2d390SJose E. Roman   Output Paramemter:
67030f984aSJacob Faibussowitsch . dctx - The PetscDeviceContext
68030f984aSJacob Faibussowitsch 
69030f984aSJacob Faibussowitsch   Notes:
70030f984aSJacob Faibussowitsch   Unlike almost every other PETSc class it is advised that most users use
71030f984aSJacob Faibussowitsch   PetscDeviceContextDuplicate() rather than this routine to create new contexts. Contexts
72030f984aSJacob Faibussowitsch   of different types are incompatible with one another; using
73030f984aSJacob Faibussowitsch   PetscDeviceContextDuplicate() ensures compatible types.
74030f984aSJacob Faibussowitsch 
75030f984aSJacob Faibussowitsch   Level: beginner
76030f984aSJacob Faibussowitsch 
77030f984aSJacob Faibussowitsch .seealso: PetscDeviceContextDuplicate(), PetscDeviceContextSetDevice(),
785181c4f9SJacob Faibussowitsch PetscDeviceContextSetStreamType(), PetscDeviceContextSetUp(),
795181c4f9SJacob Faibussowitsch PetscDeviceContextSetFromOptions(), PetscDeviceContextDestroy()
80030f984aSJacob Faibussowitsch @*/
81030f984aSJacob Faibussowitsch PetscErrorCode PetscDeviceContextCreate(PetscDeviceContext *dctx)
82030f984aSJacob Faibussowitsch {
83030f984aSJacob Faibussowitsch   PetscErrorCode ierr;
84030f984aSJacob Faibussowitsch 
85030f984aSJacob Faibussowitsch   PetscFunctionBegin;
86030f984aSJacob Faibussowitsch   PetscValidPointer(dctx,1);
87030f984aSJacob Faibussowitsch   ierr = PetscDeviceInitializePackage();CHKERRQ(ierr);
88030f984aSJacob Faibussowitsch   ierr = contextPool.get(*dctx);CHKERRQ(ierr);
89030f984aSJacob Faibussowitsch   PetscFunctionReturn(0);
90030f984aSJacob Faibussowitsch }
91030f984aSJacob Faibussowitsch 
92030f984aSJacob Faibussowitsch /*@C
93030f984aSJacob Faibussowitsch   PetscDeviceContextDestroy - Frees a PetscDeviceContext
94030f984aSJacob Faibussowitsch 
95030f984aSJacob Faibussowitsch   Not Collective, Asynchronous
96030f984aSJacob Faibussowitsch 
97030f984aSJacob Faibussowitsch   Input Parameters:
98030f984aSJacob Faibussowitsch . dctx - The PetscDeviceContext
99030f984aSJacob Faibussowitsch 
100030f984aSJacob Faibussowitsch   Notes:
101030f984aSJacob Faibussowitsch   No implicit synchronization occurs due to this routine, all resources are released completely asynchronously
102030f984aSJacob Faibussowitsch   w.r.t. the host. If one needs to guarantee access to the data produced on this contexts stream one should perform the
103030f984aSJacob Faibussowitsch   appropriate synchronization before calling this routine.
104030f984aSJacob Faibussowitsch 
105030f984aSJacob Faibussowitsch   Developer Notes:
106030f984aSJacob Faibussowitsch   The context is never actually "destroyed", only returned to an ever growing pool of
107030f984aSJacob Faibussowitsch   contexts. There are currently no safeguards on the size of the pool, this should perhaps
108030f984aSJacob Faibussowitsch   be implemented.
109030f984aSJacob Faibussowitsch 
110030f984aSJacob Faibussowitsch   Level: beginner
111030f984aSJacob Faibussowitsch 
112030f984aSJacob Faibussowitsch .seealso: PetscDeviceContextCreate(), PetscDeviceContextSetDevice(), PetscDeviceContextSetUp(), PetscDeviceContextSynchronize()
113030f984aSJacob Faibussowitsch @*/
114030f984aSJacob Faibussowitsch PetscErrorCode PetscDeviceContextDestroy(PetscDeviceContext *dctx)
115030f984aSJacob Faibussowitsch {
116030f984aSJacob Faibussowitsch   PetscErrorCode ierr;
117030f984aSJacob Faibussowitsch 
118030f984aSJacob Faibussowitsch   PetscFunctionBegin;
119030f984aSJacob Faibussowitsch   if (!*dctx) PetscFunctionReturn(0);
120030f984aSJacob Faibussowitsch   /* use move assignment whenever possible */
121030f984aSJacob Faibussowitsch   ierr = contextPool.reclaim(std::move(*dctx));CHKERRQ(ierr);
122030f984aSJacob Faibussowitsch   PetscFunctionReturn(0);
123030f984aSJacob Faibussowitsch }
124030f984aSJacob Faibussowitsch 
125030f984aSJacob Faibussowitsch /*@C
126030f984aSJacob Faibussowitsch   PetscDeviceContextSetStreamType - Set the implementation type of the underlying stream for a PetscDeviceContext
127030f984aSJacob Faibussowitsch 
128030f984aSJacob Faibussowitsch   Not Collective, Asynchronous
129030f984aSJacob Faibussowitsch 
130*01d2d390SJose E. Roman   Input Parameters:
131030f984aSJacob Faibussowitsch + dctx - The PetscDeviceContext
132030f984aSJacob Faibussowitsch - type - The PetscStreamType
133030f984aSJacob Faibussowitsch 
134030f984aSJacob Faibussowitsch   Notes:
135030f984aSJacob Faibussowitsch   See PetscStreamType in include/petscdevicetypes.h for more information on the available
136030f984aSJacob Faibussowitsch   types and their interactions. If the PetscDeviceContext was previously set up and stream
137030f984aSJacob Faibussowitsch   type was changed, you must call PetscDeviceContextSetUp() again after this routine.
138030f984aSJacob Faibussowitsch 
139030f984aSJacob Faibussowitsch   Level: intermediate
140030f984aSJacob Faibussowitsch 
1415181c4f9SJacob Faibussowitsch .seealso: PetscDeviceContextGetStreamType(), PetscDeviceContextCreate(), PetscDeviceContextSetUp(), PetscDeviceContextSetFromOptions()
142030f984aSJacob Faibussowitsch @*/
143030f984aSJacob Faibussowitsch PetscErrorCode PetscDeviceContextSetStreamType(PetscDeviceContext dctx, PetscStreamType type)
144030f984aSJacob Faibussowitsch {
145030f984aSJacob Faibussowitsch   PetscFunctionBegin;
146030f984aSJacob Faibussowitsch   PetscValidDeviceContext(dctx,1);
147030f984aSJacob Faibussowitsch   PetscValidStreamType(type,2);
148030f984aSJacob Faibussowitsch   /* only need to do complex swapping if the object has already been setup */
149030f984aSJacob Faibussowitsch   if (dctx->setup && (dctx->streamType != type)) {
150030f984aSJacob Faibussowitsch     PetscErrorCode ierr;
151030f984aSJacob Faibussowitsch 
152030f984aSJacob Faibussowitsch     ierr = (*dctx->ops->changestreamtype)(dctx,type);CHKERRQ(ierr);
153030f984aSJacob Faibussowitsch     dctx->setup = PETSC_FALSE;
154030f984aSJacob Faibussowitsch   }
155030f984aSJacob Faibussowitsch   dctx->streamType = type;
156030f984aSJacob Faibussowitsch   PetscFunctionReturn(0);
157030f984aSJacob Faibussowitsch }
158030f984aSJacob Faibussowitsch 
159030f984aSJacob Faibussowitsch /*@C
160030f984aSJacob Faibussowitsch   PetscDeviceContextGetStreamType - Get the implementation type of the underlying stream for a PetscDeviceContext
161030f984aSJacob Faibussowitsch 
162030f984aSJacob Faibussowitsch   Not Collective, Asynchronous
163030f984aSJacob Faibussowitsch 
164*01d2d390SJose E. Roman   Input Parameter:
165030f984aSJacob Faibussowitsch . dctx - The PetscDeviceContext
166030f984aSJacob Faibussowitsch 
167030f984aSJacob Faibussowitsch   Output Parameter:
168030f984aSJacob Faibussowitsch . type - The PetscStreamType
169030f984aSJacob Faibussowitsch 
170030f984aSJacob Faibussowitsch   Notes:
171030f984aSJacob Faibussowitsch   See PetscStreamType in include/petscdevicetypes.h for more information on the available types and their interactions
172030f984aSJacob Faibussowitsch 
173030f984aSJacob Faibussowitsch   Level: intermediate
174030f984aSJacob Faibussowitsch 
1755181c4f9SJacob Faibussowitsch .seealso: PetscDeviceContextSetStreamType(), PetscDeviceContextCreate(), PetscDeviceContextSetFromOptions()
176030f984aSJacob Faibussowitsch @*/
177030f984aSJacob Faibussowitsch PetscErrorCode PetscDeviceContextGetStreamType(PetscDeviceContext dctx, PetscStreamType *type)
178030f984aSJacob Faibussowitsch {
179030f984aSJacob Faibussowitsch   PetscFunctionBegin;
180030f984aSJacob Faibussowitsch   PetscValidDeviceContext(dctx,1);
181030f984aSJacob Faibussowitsch   PetscValidIntPointer(type,2);
182030f984aSJacob Faibussowitsch   *type = dctx->streamType;
183030f984aSJacob Faibussowitsch   PetscFunctionReturn(0);
184030f984aSJacob Faibussowitsch }
185030f984aSJacob Faibussowitsch 
186030f984aSJacob Faibussowitsch /*@C
187030f984aSJacob Faibussowitsch   PetscDeviceContextSetDevice - Set the underlying device for the PetscDeviceContext
188030f984aSJacob Faibussowitsch 
189030f984aSJacob Faibussowitsch   Not Collective, Possibly Synchronous
190030f984aSJacob Faibussowitsch 
191*01d2d390SJose E. Roman   Input Parameters:
192030f984aSJacob Faibussowitsch + dctx   - The PetscDeviceContext
193030f984aSJacob Faibussowitsch - device - The PetscDevice
194030f984aSJacob Faibussowitsch 
195030f984aSJacob Faibussowitsch   Notes:
196030f984aSJacob Faibussowitsch   This routine is effectively PetscDeviceContext's "set-type" (so every PetscDeviceContext
197030f984aSJacob Faibussowitsch   must also have an attached PetscDevice). Unlike the usual set-type semantics, it is
198030f984aSJacob Faibussowitsch   not stricly necessary to set a contexts device to enable usage, any created device
199030f984aSJacob Faibussowitsch   contexts will always come equipped with the "default" device.
200030f984aSJacob Faibussowitsch 
2015181c4f9SJacob Faibussowitsch   This routine may initialize the backend device and incur synchronization.
2025181c4f9SJacob Faibussowitsch 
203030f984aSJacob Faibussowitsch   Level: intermediate
204030f984aSJacob Faibussowitsch 
2055181c4f9SJacob Faibussowitsch .seealso: PetscDeviceCreate(), PetscDeviceConfigure(), PetscDeviceContextGetDevice()
206030f984aSJacob Faibussowitsch @*/
207030f984aSJacob Faibussowitsch PetscErrorCode PetscDeviceContextSetDevice(PetscDeviceContext dctx, PetscDevice device)
208030f984aSJacob Faibussowitsch {
209030f984aSJacob Faibussowitsch   PetscErrorCode ierr;
210030f984aSJacob Faibussowitsch 
211030f984aSJacob Faibussowitsch   PetscFunctionBegin;
212030f984aSJacob Faibussowitsch   PetscValidDeviceContext(dctx,1);
213030f984aSJacob Faibussowitsch   PetscValidDevice(device,2);
214030f984aSJacob Faibussowitsch   if (dctx->device == device) PetscFunctionReturn(0);
215030f984aSJacob Faibussowitsch   ierr = PetscDeviceDestroy(&dctx->device);CHKERRQ(ierr);
216030f984aSJacob Faibussowitsch   ierr = PetscMemzero(dctx->ops,sizeof(*dctx->ops));CHKERRQ(ierr);
217030f984aSJacob Faibussowitsch   ierr = (*device->ops->createcontext)(dctx);CHKERRQ(ierr);
218030f984aSJacob Faibussowitsch   dctx->device = PetscDeviceReference(device);
219030f984aSJacob Faibussowitsch   dctx->setup  = PETSC_FALSE;
220030f984aSJacob Faibussowitsch   PetscFunctionReturn(0);
221030f984aSJacob Faibussowitsch }
222030f984aSJacob Faibussowitsch 
223030f984aSJacob Faibussowitsch /*@C
224030f984aSJacob Faibussowitsch   PetscDeviceContextGetDevice - Get the underlying PetscDevice for a PetscDeviceContext
225030f984aSJacob Faibussowitsch 
226030f984aSJacob Faibussowitsch   Not Collective, Asynchronous
227030f984aSJacob Faibussowitsch 
228030f984aSJacob Faibussowitsch   Input Parameter:
229030f984aSJacob Faibussowitsch . dctx - the PetscDeviceContext
230030f984aSJacob Faibussowitsch 
231030f984aSJacob Faibussowitsch   Output Parameter:
232030f984aSJacob Faibussowitsch . device - The PetscDevice
233030f984aSJacob Faibussowitsch 
234030f984aSJacob Faibussowitsch   Notes:
235030f984aSJacob Faibussowitsch   This is a borrowed reference, the user should not destroy the device.
236030f984aSJacob Faibussowitsch 
237030f984aSJacob Faibussowitsch .seealso: PetscDeviceContextSetDevice(), PetscDevice
238030f984aSJacob Faibussowitsch @*/
239030f984aSJacob Faibussowitsch PetscErrorCode PetscDeviceContextGetDevice(PetscDeviceContext dctx, PetscDevice *device)
240030f984aSJacob Faibussowitsch {
241030f984aSJacob Faibussowitsch   PetscFunctionBegin;
242030f984aSJacob Faibussowitsch   PetscValidDeviceContext(dctx,1);
243030f984aSJacob Faibussowitsch   PetscValidPointer(device,2);
244030f984aSJacob Faibussowitsch   *device = dctx->device;
245030f984aSJacob Faibussowitsch   PetscFunctionReturn(0);
246030f984aSJacob Faibussowitsch }
247030f984aSJacob Faibussowitsch 
248030f984aSJacob Faibussowitsch /*@C
249030f984aSJacob Faibussowitsch   PetscDeviceContextSetUp - Prepares a PetscDeviceContext for use
250030f984aSJacob Faibussowitsch 
251030f984aSJacob Faibussowitsch   Not Collective, Asynchronous
252030f984aSJacob Faibussowitsch 
253*01d2d390SJose E. Roman   Input Parameter:
254030f984aSJacob Faibussowitsch . dctx - The PetscDeviceContext
255030f984aSJacob Faibussowitsch 
256030f984aSJacob Faibussowitsch   Developer Notes:
257030f984aSJacob Faibussowitsch   This routine is usually the stage where a PetscDeviceContext acquires device-side data structures such as streams,
258030f984aSJacob Faibussowitsch   events, and (possibly) handles.
259030f984aSJacob Faibussowitsch 
260030f984aSJacob Faibussowitsch   Level: beginner
261030f984aSJacob Faibussowitsch 
2625181c4f9SJacob Faibussowitsch .seealso: PetscDeviceContextCreate(), PetscDeviceContextSetDevice(), PetscDeviceContextDestroy(), PetscDeviceContextSetFromOptions()
263030f984aSJacob Faibussowitsch @*/
264030f984aSJacob Faibussowitsch PetscErrorCode PetscDeviceContextSetUp(PetscDeviceContext dctx)
265030f984aSJacob Faibussowitsch {
266030f984aSJacob Faibussowitsch   PetscErrorCode ierr;
267030f984aSJacob Faibussowitsch 
268030f984aSJacob Faibussowitsch   PetscFunctionBegin;
269030f984aSJacob Faibussowitsch   PetscValidDeviceContext(dctx,1);
270030f984aSJacob Faibussowitsch   if (!dctx->device) {
271030f984aSJacob Faibussowitsch     ierr = PetscInfo2(NULL,"PetscDeviceContext %d did not have an explicitly attached PetscDevice, using default with type %s\n",dctx->id,PetscDeviceKinds[PETSC_DEVICE_DEFAULT]);CHKERRQ(ierr);
272030f984aSJacob Faibussowitsch     ierr = PetscDeviceContextSetDevice(dctx,PetscDeviceDefault_Internal());CHKERRQ(ierr);
273030f984aSJacob Faibussowitsch   }
274030f984aSJacob Faibussowitsch   if (dctx->setup) PetscFunctionReturn(0);
275030f984aSJacob Faibussowitsch   ierr = (*dctx->ops->setup)(dctx);CHKERRQ(ierr);
276030f984aSJacob Faibussowitsch   dctx->setup = PETSC_TRUE;
277030f984aSJacob Faibussowitsch   PetscFunctionReturn(0);
278030f984aSJacob Faibussowitsch }
279030f984aSJacob Faibussowitsch 
280030f984aSJacob Faibussowitsch /*@C
281030f984aSJacob Faibussowitsch   PetscDeviceContextDuplicate - Duplicates a PetscDeviceContext object
282030f984aSJacob Faibussowitsch 
283030f984aSJacob Faibussowitsch   Not Collective, Asynchronous
284030f984aSJacob Faibussowitsch 
285030f984aSJacob Faibussowitsch   Input Parameter:
286030f984aSJacob Faibussowitsch . dctx - The PetscDeviceContext to duplicate
287030f984aSJacob Faibussowitsch 
288030f984aSJacob Faibussowitsch   Output Paramter:
289030f984aSJacob Faibussowitsch . strmdup - The duplicated PetscDeviceContext
290030f984aSJacob Faibussowitsch 
291030f984aSJacob Faibussowitsch   Notes:
292030f984aSJacob Faibussowitsch   This is a shorthand method for creating a PetscDeviceContext with the exact same
293030f984aSJacob Faibussowitsch   settings as another. Note however that the duplicated PetscDeviceContext does not "share"
294030f984aSJacob Faibussowitsch   any of the underlying data with the original, (including its current stream-state) they
295030f984aSJacob Faibussowitsch   are completely separate objects.
296030f984aSJacob Faibussowitsch 
297030f984aSJacob Faibussowitsch   Level: beginner
298030f984aSJacob Faibussowitsch 
299030f984aSJacob Faibussowitsch .seealso: PetscDeviceContextCreate(), PetscDeviceContextSetDevice(), PetscDeviceContextSetStreamType()
300030f984aSJacob Faibussowitsch @*/
301030f984aSJacob Faibussowitsch PetscErrorCode PetscDeviceContextDuplicate(PetscDeviceContext dctx, PetscDeviceContext *dctxdup)
302030f984aSJacob Faibussowitsch {
303030f984aSJacob Faibussowitsch   PetscErrorCode ierr;
304030f984aSJacob Faibussowitsch 
305030f984aSJacob Faibussowitsch   PetscFunctionBegin;
306030f984aSJacob Faibussowitsch   PetscValidDeviceContext(dctx,1);
307030f984aSJacob Faibussowitsch   PetscValidPointer(dctxdup,2);
308030f984aSJacob Faibussowitsch   ierr = PetscDeviceContextCreate(dctxdup);CHKERRQ(ierr);
309030f984aSJacob Faibussowitsch   ierr = PetscDeviceContextSetDevice(*dctxdup,dctx->device);CHKERRQ(ierr);
310030f984aSJacob Faibussowitsch   ierr = PetscDeviceContextSetStreamType(*dctxdup,dctx->streamType);CHKERRQ(ierr);
311030f984aSJacob Faibussowitsch   ierr = PetscDeviceContextSetUp(*dctxdup);CHKERRQ(ierr);
312030f984aSJacob Faibussowitsch   PetscFunctionReturn(0);
313030f984aSJacob Faibussowitsch }
314030f984aSJacob Faibussowitsch 
315030f984aSJacob Faibussowitsch /*@C
316030f984aSJacob Faibussowitsch   PetscDeviceContextQueryIdle - Returns whether or not a PetscDeviceContext is idle
317030f984aSJacob Faibussowitsch 
318030f984aSJacob Faibussowitsch   Not Collective, Asynchronous
319030f984aSJacob Faibussowitsch 
320030f984aSJacob Faibussowitsch   Input Parameter:
321030f984aSJacob Faibussowitsch . dctx - The PetscDeviceContext object
322030f984aSJacob Faibussowitsch 
323030f984aSJacob Faibussowitsch   Output Parameter:
324030f984aSJacob Faibussowitsch . idle - PETSC_TRUE if PetscDeviceContext has NO work, PETSC_FALSE if it has work
325030f984aSJacob Faibussowitsch 
326030f984aSJacob Faibussowitsch   Notes:
327030f984aSJacob Faibussowitsch   This routine only refers a singular context and does NOT take any of its children into account. That is, if dctx is
328030f984aSJacob Faibussowitsch   idle but has dependents who do have work, this routine still returns PETSC_TRUE.
329030f984aSJacob Faibussowitsch 
330030f984aSJacob Faibussowitsch   Results of PetscDeviceContextQueryIdle() are cached on return, allowing this function to be called repeatedly in an
331030f984aSJacob Faibussowitsch   efficient manner. When debug mode is enabled this cache is verified on every call to
332030f984aSJacob Faibussowitsch   this routine, but is blindly believed when debugging is disabled.
333030f984aSJacob Faibussowitsch 
334030f984aSJacob Faibussowitsch   Level: intermediate
335030f984aSJacob Faibussowitsch 
336030f984aSJacob Faibussowitsch .seealso: PetscDeviceContextCreate(), PetscDeviceContextWaitForContext(), PetscDeviceContextFork()
337030f984aSJacob Faibussowitsch @*/
338030f984aSJacob Faibussowitsch PetscErrorCode PetscDeviceContextQueryIdle(PetscDeviceContext dctx, PetscBool *idle)
339030f984aSJacob Faibussowitsch {
340030f984aSJacob Faibussowitsch   PetscErrorCode ierr;
341030f984aSJacob Faibussowitsch 
342030f984aSJacob Faibussowitsch   PetscFunctionBegin;
343030f984aSJacob Faibussowitsch   PetscValidDeviceContext(dctx,1);
344030f984aSJacob Faibussowitsch   PetscValidBoolPointer(idle,2);
345030f984aSJacob Faibussowitsch   if (dctx->idle) {
346030f984aSJacob Faibussowitsch     *idle = PETSC_TRUE;
347030f984aSJacob Faibussowitsch     ierr = PetscDeviceContextValidateIdle_Internal(dctx);CHKERRQ(ierr);
348030f984aSJacob Faibussowitsch   } else {
349030f984aSJacob Faibussowitsch     ierr = (*dctx->ops->query)(dctx,idle);CHKERRQ(ierr);
350030f984aSJacob Faibussowitsch     dctx->idle = *idle;
351030f984aSJacob Faibussowitsch   }
352030f984aSJacob Faibussowitsch   PetscFunctionReturn(0);
353030f984aSJacob Faibussowitsch }
354030f984aSJacob Faibussowitsch 
355030f984aSJacob Faibussowitsch /*@C
356030f984aSJacob Faibussowitsch   PetscDeviceContextWaitForContext - Make one context wait for another context to finish
357030f984aSJacob Faibussowitsch 
358030f984aSJacob Faibussowitsch   Not Collective, Asynchronous
359030f984aSJacob Faibussowitsch 
360030f984aSJacob Faibussowitsch   Input Parameters:
361030f984aSJacob Faibussowitsch + dctxa - The PetscDeviceContext object that is waiting
362030f984aSJacob Faibussowitsch - dctxb - The PetscDeviceContext object that is being waited on
363030f984aSJacob Faibussowitsch 
364030f984aSJacob Faibussowitsch   Notes:
365030f984aSJacob Faibussowitsch   Serializes two PetscDeviceContexts. This routine uses only the state of dctxb at the moment this routine was
366030f984aSJacob Faibussowitsch   called, so any future work queued will not affect dctxa. It is safe to pass the same context to both arguments.
367030f984aSJacob Faibussowitsch 
368030f984aSJacob Faibussowitsch   Level: beginner
369030f984aSJacob Faibussowitsch 
370030f984aSJacob Faibussowitsch .seealso: PetscDeviceContextCreate(), PetscDeviceContextQueryIdle(), PetscDeviceContextJoin()
371030f984aSJacob Faibussowitsch @*/
372030f984aSJacob Faibussowitsch PetscErrorCode PetscDeviceContextWaitForContext(PetscDeviceContext dctxa, PetscDeviceContext dctxb)
373030f984aSJacob Faibussowitsch {
374030f984aSJacob Faibussowitsch   PetscErrorCode ierr;
375030f984aSJacob Faibussowitsch 
376030f984aSJacob Faibussowitsch   PetscFunctionBegin;
377030f984aSJacob Faibussowitsch   PetscCheckCompatibleDeviceContexts(dctxa,1,dctxb,2);
378030f984aSJacob Faibussowitsch   if (dctxa == dctxb) PetscFunctionReturn(0);
379030f984aSJacob Faibussowitsch   if (dctxb->idle) {
380030f984aSJacob Faibussowitsch     /* No need to do the extra function lookup and event record if the stream were waiting on isn't doing anything */
381030f984aSJacob Faibussowitsch     ierr = PetscDeviceContextValidateIdle_Internal(dctxb);CHKERRQ(ierr);
382030f984aSJacob Faibussowitsch   } else {
383030f984aSJacob Faibussowitsch     ierr = (*dctxa->ops->waitforctx)(dctxa,dctxb);CHKERRQ(ierr);
384030f984aSJacob Faibussowitsch   }
385030f984aSJacob Faibussowitsch   PetscFunctionReturn(0);
386030f984aSJacob Faibussowitsch }
387030f984aSJacob Faibussowitsch 
388030f984aSJacob Faibussowitsch /*@C
389030f984aSJacob Faibussowitsch   PetscDeviceContextFork - Create a set of dependent child contexts from a parent context
390030f984aSJacob Faibussowitsch 
391030f984aSJacob Faibussowitsch   Not Collective, Asynchronous
392030f984aSJacob Faibussowitsch 
393030f984aSJacob Faibussowitsch   Input Parameters:
394030f984aSJacob Faibussowitsch + dctx - The parent PetscDeviceContext
395030f984aSJacob Faibussowitsch - n    - The number of children to create
396030f984aSJacob Faibussowitsch 
397030f984aSJacob Faibussowitsch   Output Parameter:
398030f984aSJacob Faibussowitsch . dsub - The created child context(s)
399030f984aSJacob Faibussowitsch 
400030f984aSJacob Faibussowitsch   Notes:
401030f984aSJacob Faibussowitsch   This routine creates n edges of a DAG from a source node which are causally dependent on the source node, meaning
402030f984aSJacob Faibussowitsch   that work queued on child contexts will not start until the parent context finishes its work. This accounts for work
403030f984aSJacob Faibussowitsch   queued on the parent up until calling this function, any subsequent work enqueued on the parent has no effect on the children.
404030f984aSJacob Faibussowitsch 
405030f984aSJacob Faibussowitsch   Any children created with this routine have their lifetimes bounded by the parent. That is, the parent context expects
406030f984aSJacob Faibussowitsch   to free all of it's children (and ONLY its children) before itself is freed.
407030f984aSJacob Faibussowitsch 
408030f984aSJacob Faibussowitsch   DAG representation:
409030f984aSJacob Faibussowitsch .vb
410030f984aSJacob Faibussowitsch   time ->
411030f984aSJacob Faibussowitsch 
412030f984aSJacob Faibussowitsch   -> dctx \----> dctx ------>
413030f984aSJacob Faibussowitsch            \---> dsub[0] --->
414030f984aSJacob Faibussowitsch             \--> ... ------->
415030f984aSJacob Faibussowitsch              \-> dsub[n-1] ->
416030f984aSJacob Faibussowitsch .ve
417030f984aSJacob Faibussowitsch 
418030f984aSJacob Faibussowitsch   Level: intermediate
419030f984aSJacob Faibussowitsch 
420030f984aSJacob Faibussowitsch .seealso: PetscDeviceContextJoin(), PetscDeviceContextSynchronize(), PetscDeviceContextQueryIdle()
421030f984aSJacob Faibussowitsch @*/
422030f984aSJacob Faibussowitsch PetscErrorCode PetscDeviceContextFork(PetscDeviceContext dctx, PetscInt n, PetscDeviceContext **dsub)
423030f984aSJacob Faibussowitsch {
424030f984aSJacob Faibussowitsch #if defined(PETSC_USE_DEBUG) && defined(PETSC_USE_INFO)
425030f984aSJacob Faibussowitsch   const PetscInt      nBefore = n;
426030f984aSJacob Faibussowitsch   static std::string  idList;
427030f984aSJacob Faibussowitsch #endif
428030f984aSJacob Faibussowitsch   PetscDeviceContext *dsubTmp = nullptr;
429030f984aSJacob Faibussowitsch   PetscInt            i = 0;
430030f984aSJacob Faibussowitsch   PetscErrorCode      ierr;
431030f984aSJacob Faibussowitsch 
432030f984aSJacob Faibussowitsch   PetscFunctionBegin;
433030f984aSJacob Faibussowitsch   PetscValidDeviceContext(dctx,1);
434030f984aSJacob Faibussowitsch   PetscValidPointer(dsub,3);
435030f984aSJacob Faibussowitsch   if (PetscUnlikelyDebug(n < 0)) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Number of contexts requested %D < 0",n);
436030f984aSJacob Faibussowitsch #if defined(PETSC_USE_DEBUG) && defined(PETSC_USE_INFO)
437030f984aSJacob Faibussowitsch   /* reserve 4 chars per id, 2 for number and 2 for ', ' separator */
438030f984aSJacob Faibussowitsch   idList.reserve(4*n);
439030f984aSJacob Faibussowitsch #endif
440030f984aSJacob Faibussowitsch   /* update child totals */
441030f984aSJacob Faibussowitsch   dctx->numChildren += n;
442030f984aSJacob Faibussowitsch   /* now to find out if we have room */
443030f984aSJacob Faibussowitsch   if (dctx->numChildren > dctx->maxNumChildren) {
444030f984aSJacob Faibussowitsch     /* no room, either from having too many kids or not having any */
445030f984aSJacob Faibussowitsch     if (dctx->childIDs) {
446030f984aSJacob Faibussowitsch       /* have existing children, must reallocate them */
447030f984aSJacob Faibussowitsch       ierr = PetscRealloc(dctx->numChildren*sizeof(*dctx->childIDs),&dctx->childIDs);CHKERRQ(ierr);
448030f984aSJacob Faibussowitsch       /* clear the extra memory since realloc doesn't do it for us */
449030f984aSJacob Faibussowitsch       ierr = PetscArrayzero((dctx->childIDs)+(dctx->maxNumChildren),(dctx->numChildren)-(dctx->maxNumChildren));CHKERRQ(ierr);
450030f984aSJacob Faibussowitsch     } else {
451030f984aSJacob Faibussowitsch       /* have no children */
452030f984aSJacob Faibussowitsch       ierr = PetscCalloc1(dctx->numChildren,&dctx->childIDs);CHKERRQ(ierr);
453030f984aSJacob Faibussowitsch     }
454030f984aSJacob Faibussowitsch     /* update total number of children */
455030f984aSJacob Faibussowitsch     dctx->maxNumChildren = dctx->numChildren;
456030f984aSJacob Faibussowitsch   }
457030f984aSJacob Faibussowitsch   ierr = PetscMalloc1(n,&dsubTmp);CHKERRQ(ierr);
458030f984aSJacob Faibussowitsch   while (n) {
459030f984aSJacob Faibussowitsch     /* empty child slot */
460030f984aSJacob Faibussowitsch     if (!(dctx->childIDs[i])) {
461030f984aSJacob Faibussowitsch       /* create the child context in the image of its parent */
462030f984aSJacob Faibussowitsch       ierr = PetscDeviceContextDuplicate(dctx,dsubTmp+i);CHKERRQ(ierr);
463030f984aSJacob Faibussowitsch       ierr = PetscDeviceContextWaitForContext(dsubTmp[i],dctx);CHKERRQ(ierr);
464030f984aSJacob Faibussowitsch       /* register the child with its parent */
465030f984aSJacob Faibussowitsch       dctx->childIDs[i] = dsubTmp[i]->id;
466030f984aSJacob Faibussowitsch #if defined(PETSC_USE_DEBUG) && defined(PETSC_USE_INFO)
467030f984aSJacob Faibussowitsch       idList += std::to_string(dsubTmp[i]->id);
468030f984aSJacob Faibussowitsch       if (n != 1) idList += ", ";
469030f984aSJacob Faibussowitsch #endif
470030f984aSJacob Faibussowitsch       --n;
471030f984aSJacob Faibussowitsch     }
472030f984aSJacob Faibussowitsch     ++i;
473030f984aSJacob Faibussowitsch   }
474030f984aSJacob Faibussowitsch #if defined(PETSC_USE_DEBUG) && defined(PETSC_USE_INFO)
475030f984aSJacob Faibussowitsch   ierr = PetscInfo3(NULL,"Forked %D children from parent %D with IDs: %s\n",nBefore,dctx->id,idList.c_str());CHKERRQ(ierr);
476030f984aSJacob Faibussowitsch   /* resets the size but doesn't deallocate the memory */
477030f984aSJacob Faibussowitsch   idList.clear();
478030f984aSJacob Faibussowitsch #endif
479030f984aSJacob Faibussowitsch   /* pass the children back to caller */
480030f984aSJacob Faibussowitsch   *dsub = dsubTmp;
481030f984aSJacob Faibussowitsch   PetscFunctionReturn(0);
482030f984aSJacob Faibussowitsch }
483030f984aSJacob Faibussowitsch 
484030f984aSJacob Faibussowitsch /*@C
4855181c4f9SJacob Faibussowitsch   PetscDeviceContextJoin - Converge a set of child contexts
486030f984aSJacob Faibussowitsch 
487030f984aSJacob Faibussowitsch   Not Collective, Asynchronous
488030f984aSJacob Faibussowitsch 
489030f984aSJacob Faibussowitsch   Input Parameters:
490030f984aSJacob Faibussowitsch + dctx         - A PetscDeviceContext to converge on
491030f984aSJacob Faibussowitsch . n            - The number of sub contexts to converge
492030f984aSJacob Faibussowitsch . joinMode     - The type of join to perform
493030f984aSJacob Faibussowitsch - dsub         - The sub contexts to converge
494030f984aSJacob Faibussowitsch 
495030f984aSJacob Faibussowitsch   Notes:
496030f984aSJacob Faibussowitsch   If PetscDeviceContextFork() creates n edges from a source node which all depend on the
497030f984aSJacob Faibussowitsch   source node, then this routine is the exact mirror. That is, it creates a node
498030f984aSJacob Faibussowitsch   (represented in dctx) which recieves n edges (and optionally destroys them) which is
499030f984aSJacob Faibussowitsch   dependent on the completion of all incoming edges.
500030f984aSJacob Faibussowitsch 
501030f984aSJacob Faibussowitsch   If joinMode is PETSC_DEVICE_CONTEXT_JOIN_DESTROY all contexts in dsub will be destroyed
502030f984aSJacob Faibussowitsch   by this routine. Thus all sub contexts must have been created with the dctx passed to
503030f984aSJacob Faibussowitsch   this routine.
504030f984aSJacob Faibussowitsch 
505030f984aSJacob Faibussowitsch   if joinMode is PETSC_DEVICE_CONTEXT_JOIN_NO_SYNC dctx waits for all sub contexts but the
506030f984aSJacob Faibussowitsch   sub contexts do not wait for one another afterwards.
507030f984aSJacob Faibussowitsch 
508030f984aSJacob Faibussowitsch   If joinMode is PETSC_DEVICE_CONTEXT_JOIN_SYNC all sub contexts will additionally
509030f984aSJacob Faibussowitsch   wait on dctx after converging. This has the effect of "synchronizing" the outgoing
510030f984aSJacob Faibussowitsch   edges.
511030f984aSJacob Faibussowitsch 
512030f984aSJacob Faibussowitsch   DAG representations:
513030f984aSJacob Faibussowitsch   If joinMode is PETSC_DEVICE_CONTEXT_JOIN_DESTROY
514030f984aSJacob Faibussowitsch .vb
515030f984aSJacob Faibussowitsch   time ->
516030f984aSJacob Faibussowitsch 
517030f984aSJacob Faibussowitsch   -> dctx ---------/- dctx ->
518030f984aSJacob Faibussowitsch   -> dsub[0] -----/
519030f984aSJacob Faibussowitsch   ->  ... -------/
520030f984aSJacob Faibussowitsch   -> dsub[n-1] -/
521030f984aSJacob Faibussowitsch .ve
522030f984aSJacob Faibussowitsch   If joinMode is PETSC_DEVICE_CONTEXT_JOIN_NO_SYNC
523030f984aSJacob Faibussowitsch .vb
524030f984aSJacob Faibussowitsch   time ->
525030f984aSJacob Faibussowitsch 
526030f984aSJacob Faibussowitsch   -> dctx ---------/- dctx ->
527030f984aSJacob Faibussowitsch   -> dsub[0] -----/--------->
528030f984aSJacob Faibussowitsch   ->  ... -------/---------->
529030f984aSJacob Faibussowitsch   -> dsub[n-1] -/----------->
530030f984aSJacob Faibussowitsch .ve
531030f984aSJacob Faibussowitsch   If joinMode is PETSC_DEVICE_CONTEXT_JOIN_SYNC
532030f984aSJacob Faibussowitsch .vb
533030f984aSJacob Faibussowitsch   time ->
534030f984aSJacob Faibussowitsch 
535030f984aSJacob Faibussowitsch   -> dctx ---------/- dctx -\----> dctx ------>
536030f984aSJacob Faibussowitsch   -> dsub[0] -----/          \---> dsub[0] --->
537030f984aSJacob Faibussowitsch   ->  ... -------/            \--> ... ------->
538030f984aSJacob Faibussowitsch   -> dsub[n-1] -/              \-> dsub[n-1] ->
539030f984aSJacob Faibussowitsch .ve
540030f984aSJacob Faibussowitsch 
541030f984aSJacob Faibussowitsch   Level: intermediate
542030f984aSJacob Faibussowitsch 
543030f984aSJacob Faibussowitsch .seealso: PetscDeviceContextFork(), PetscDeviceContextSynchronize(), PetscDeviceContextJoinMode
544030f984aSJacob Faibussowitsch @*/
545030f984aSJacob Faibussowitsch PetscErrorCode PetscDeviceContextJoin(PetscDeviceContext dctx, PetscInt n, PetscDeviceContextJoinMode joinMode, PetscDeviceContext **dsub)
546030f984aSJacob Faibussowitsch {
547030f984aSJacob Faibussowitsch #if defined(PETSC_USE_DEBUG) && defined(PETSC_USE_INFO)
548030f984aSJacob Faibussowitsch   static std::string idList;
549030f984aSJacob Faibussowitsch #endif
550030f984aSJacob Faibussowitsch   PetscErrorCode     ierr;
551030f984aSJacob Faibussowitsch 
552030f984aSJacob Faibussowitsch   PetscFunctionBegin;
553030f984aSJacob Faibussowitsch   /* validity of dctx is checked in the wait-for loop */
554030f984aSJacob Faibussowitsch   PetscValidPointer(dsub,4);
555030f984aSJacob Faibussowitsch   if (PetscUnlikelyDebug(n < 0)) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Number of contexts merged %D < 0",n);
556030f984aSJacob Faibussowitsch #if defined(PETSC_USE_DEBUG) && defined(PETSC_USE_INFO)
557030f984aSJacob Faibussowitsch   /* reserve 4 chars per id, 2 for number and 2 for ', ' separator */
558030f984aSJacob Faibussowitsch   idList.reserve(4*n);
559030f984aSJacob Faibussowitsch #endif
560030f984aSJacob Faibussowitsch   /* first dctx waits on all the incoming edges */
561030f984aSJacob Faibussowitsch   for (PetscInt i = 0; i < n; ++i) {
562030f984aSJacob Faibussowitsch     PetscCheckCompatibleDeviceContexts(dctx,1,(*dsub)[i],4);
563030f984aSJacob Faibussowitsch     ierr = PetscDeviceContextWaitForContext(dctx,(*dsub)[i]);CHKERRQ(ierr);
564030f984aSJacob Faibussowitsch #if defined(PETSC_USE_DEBUG) && defined(PETSC_USE_INFO)
565030f984aSJacob Faibussowitsch     idList += std::to_string((*dsub)[i]->id);
566030f984aSJacob Faibussowitsch     if (i+1 < n) idList += ", ";
567030f984aSJacob Faibussowitsch #endif
568030f984aSJacob Faibussowitsch   }
569030f984aSJacob Faibussowitsch 
570030f984aSJacob Faibussowitsch   /* now we handle the aftermath */
571030f984aSJacob Faibussowitsch   switch (joinMode) {
572030f984aSJacob Faibussowitsch   case PETSC_DEVICE_CONTEXT_JOIN_DESTROY:
573030f984aSJacob Faibussowitsch     {
574030f984aSJacob Faibussowitsch       PetscInt j = 0;
575030f984aSJacob Faibussowitsch 
576030f984aSJacob Faibussowitsch       if (PetscUnlikelyDebug(n > dctx->numChildren)) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Trying to destroy %D children of a parent context that only has %D children, likely trying to restore to wrong parent",n,dctx->numChildren);
577030f984aSJacob Faibussowitsch       /* update child count while it's still fresh in memory */
578030f984aSJacob Faibussowitsch       dctx->numChildren -= n;
579030f984aSJacob Faibussowitsch       for (PetscInt i = 0; i < dctx->maxNumChildren; ++i) {
580030f984aSJacob Faibussowitsch         if (dctx->childIDs[i] && (dctx->childIDs[i] == (*dsub)[j]->id)) {
581030f984aSJacob Faibussowitsch           /* child is one of ours, can destroy it */
582030f984aSJacob Faibussowitsch           ierr = PetscDeviceContextDestroy((*dsub)+j);CHKERRQ(ierr);
583030f984aSJacob Faibussowitsch           /* reset the child slot */
584030f984aSJacob Faibussowitsch           dctx->childIDs[i] = 0;
585030f984aSJacob Faibussowitsch           if (++j == n) break;
586030f984aSJacob Faibussowitsch         }
587030f984aSJacob Faibussowitsch       }
588030f984aSJacob Faibussowitsch       /* gone through the loop but did not find every child, if this triggers (or well, doesn't) on perf-builds we leak the remaining contexts memory */
589030f984aSJacob Faibussowitsch       if (PetscUnlikelyDebug(j != n)) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"%D contexts still remain after destroy, this may be because you are trying to restore to the wrong parent context, or the device contexts are not in the same order as they were checked out out in.",n-j);
590030f984aSJacob Faibussowitsch       ierr = PetscFree(*dsub);CHKERRQ(ierr);
591030f984aSJacob Faibussowitsch     }
592030f984aSJacob Faibussowitsch     break;
593030f984aSJacob Faibussowitsch   case PETSC_DEVICE_CONTEXT_JOIN_SYNC:
594030f984aSJacob Faibussowitsch     for (PetscInt i = 0; i < n; ++i) {
595030f984aSJacob Faibussowitsch       ierr = PetscDeviceContextWaitForContext((*dsub)[i],dctx);CHKERRQ(ierr);
596030f984aSJacob Faibussowitsch     }
597030f984aSJacob Faibussowitsch   case PETSC_DEVICE_CONTEXT_JOIN_NO_SYNC:
598030f984aSJacob Faibussowitsch     break;
599030f984aSJacob Faibussowitsch   default:
600030f984aSJacob Faibussowitsch     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Unknown PetscDeviceContextJoinMode given");
601030f984aSJacob Faibussowitsch     break;
602030f984aSJacob Faibussowitsch   }
603030f984aSJacob Faibussowitsch 
604030f984aSJacob Faibussowitsch #if defined(PETSC_USE_DEBUG) && defined(PETSC_USE_INFO)
605030f984aSJacob Faibussowitsch   ierr = PetscInfo4(NULL,"Joined %D ctxs to ctx %D, mode %s with IDs: %s\n",n,dctx->id,PetscDeviceContextJoinModes[joinMode],idList.c_str());CHKERRQ(ierr);
606030f984aSJacob Faibussowitsch   idList.clear();
607030f984aSJacob Faibussowitsch #endif
608030f984aSJacob Faibussowitsch   PetscFunctionReturn(0);
609030f984aSJacob Faibussowitsch }
610030f984aSJacob Faibussowitsch 
611030f984aSJacob Faibussowitsch /*@C
6125181c4f9SJacob Faibussowitsch   PetscDeviceContextSynchronize - Block the host until all work queued on or associated with a PetscDeviceContext has finished
613030f984aSJacob Faibussowitsch 
614030f984aSJacob Faibussowitsch   Not Collective, Synchronous
615030f984aSJacob Faibussowitsch 
616030f984aSJacob Faibussowitsch   Input Parameters:
617030f984aSJacob Faibussowitsch . dctx - The PetscDeviceContext to synchronize
618030f984aSJacob Faibussowitsch 
619030f984aSJacob Faibussowitsch   Level: beginner
620030f984aSJacob Faibussowitsch 
621030f984aSJacob Faibussowitsch .seealso: PetscDeviceContextFork(), PetscDeviceContextJoin(), PetscDeviceContextQueryIdle()
622030f984aSJacob Faibussowitsch @*/
623030f984aSJacob Faibussowitsch PetscErrorCode PetscDeviceContextSynchronize(PetscDeviceContext dctx)
624030f984aSJacob Faibussowitsch {
625030f984aSJacob Faibussowitsch   PetscErrorCode ierr;
626030f984aSJacob Faibussowitsch 
627030f984aSJacob Faibussowitsch   PetscFunctionBegin;
628030f984aSJacob Faibussowitsch   PetscValidDeviceContext(dctx,1);
629030f984aSJacob Faibussowitsch   /* if it isn't setup there is nothing to sync on */
630030f984aSJacob Faibussowitsch   if (dctx->setup) {ierr = (*dctx->ops->synchronize)(dctx);CHKERRQ(ierr);}
631030f984aSJacob Faibussowitsch   dctx->idle = PETSC_TRUE;
632030f984aSJacob Faibussowitsch   PetscFunctionReturn(0);
633030f984aSJacob Faibussowitsch }
634030f984aSJacob Faibussowitsch 
635030f984aSJacob Faibussowitsch static PetscDeviceContext globalContext      = nullptr;
636030f984aSJacob Faibussowitsch static PetscBool          globalContextSetup = PETSC_FALSE;
637030f984aSJacob Faibussowitsch static PetscStreamType    defaultStreamType  = PETSC_STREAM_DEFAULT_BLOCKING;
638030f984aSJacob Faibussowitsch 
639030f984aSJacob Faibussowitsch /* automatically registered to PetscFinalize() when first context is instantiated, do not
640030f984aSJacob Faibussowitsch    call */
641030f984aSJacob Faibussowitsch static PetscErrorCode PetscDeviceContextDestroyGlobalContext_Private(void)
642030f984aSJacob Faibussowitsch {
643030f984aSJacob Faibussowitsch   PetscErrorCode ierr;
644030f984aSJacob Faibussowitsch 
645030f984aSJacob Faibussowitsch   PetscFunctionBegin;
646030f984aSJacob Faibussowitsch   ierr = PetscDeviceContextSynchronize(globalContext);CHKERRQ(ierr);
647030f984aSJacob Faibussowitsch   ierr = PetscDeviceContextDestroy(&globalContext);CHKERRQ(ierr);
648030f984aSJacob Faibussowitsch   /* reset everything to defaults */
649030f984aSJacob Faibussowitsch   defaultStreamType  = PETSC_STREAM_DEFAULT_BLOCKING;
650030f984aSJacob Faibussowitsch   globalContextSetup = PETSC_FALSE;
651030f984aSJacob Faibussowitsch   PetscFunctionReturn(0);
652030f984aSJacob Faibussowitsch }
653030f984aSJacob Faibussowitsch 
654030f984aSJacob Faibussowitsch /* creates and initializes the root context in PetscInitialize() but does not call
655030f984aSJacob Faibussowitsch    SetUp() as the user may wish to change types after PetscInitialize() */
656030f984aSJacob Faibussowitsch PetscErrorCode PetscDeviceContextInitializeRootContext_Internal(MPI_Comm comm, const char prefix[])
657030f984aSJacob Faibussowitsch {
658030f984aSJacob Faibussowitsch   PetscErrorCode ierr;
659030f984aSJacob Faibussowitsch 
660030f984aSJacob Faibussowitsch   PetscFunctionBegin;
661030f984aSJacob Faibussowitsch   ierr = PetscInfo1(NULL,"Initializing root PetscDeviceContext with PetscDeviceKind %s\n",PetscDeviceKinds[PETSC_DEVICE_DEFAULT]);CHKERRQ(ierr);
662030f984aSJacob Faibussowitsch   ierr = PetscDeviceContextCreate(&globalContext);CHKERRQ(ierr);
663030f984aSJacob Faibussowitsch   if (PetscUnlikelyDebug(globalContext->id != 0)) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"The root current PetscDeviceContext should have id = 0, however it has id = %D",globalContext->id);
664030f984aSJacob Faibussowitsch   ierr = PetscDeviceContextSetDevice(globalContext,PetscDeviceDefault_Internal());CHKERRQ(ierr);
665030f984aSJacob Faibussowitsch   ierr = PetscDeviceContextSetStreamType(globalContext,defaultStreamType);CHKERRQ(ierr);
666030f984aSJacob Faibussowitsch   ierr = PetscDeviceContextSetFromOptions(comm,prefix,globalContext);CHKERRQ(ierr);
667030f984aSJacob Faibussowitsch   ierr = PetscRegisterFinalize(PetscDeviceContextDestroyGlobalContext_Private);CHKERRQ(ierr);
668030f984aSJacob Faibussowitsch   PetscFunctionReturn(0);
669030f984aSJacob Faibussowitsch }
670030f984aSJacob Faibussowitsch 
671030f984aSJacob Faibussowitsch /*@C
6725181c4f9SJacob Faibussowitsch   PetscDeviceContextGetCurrentContext - Get the current active PetscDeviceContext
673030f984aSJacob Faibussowitsch 
674030f984aSJacob Faibussowitsch   Not Collective, Asynchronous
675030f984aSJacob Faibussowitsch 
676030f984aSJacob Faibussowitsch   Output Parameter:
677030f984aSJacob Faibussowitsch . dctx - The PetscDeviceContext
678030f984aSJacob Faibussowitsch 
679030f984aSJacob Faibussowitsch   Notes:
680030f984aSJacob Faibussowitsch   The user generally should not destroy contexts retrieved with this routine unless they themselves have created
681030f984aSJacob Faibussowitsch   them. There exists no protection against destroying the root context.
682030f984aSJacob Faibussowitsch 
683030f984aSJacob Faibussowitsch   Developer Notes:
684030f984aSJacob Faibussowitsch   This routine creates the "root" context the first time it is called, registering its
685030f984aSJacob Faibussowitsch   destructor to PetscFinalize(). The root context is synchronized before being destroyed.
686030f984aSJacob Faibussowitsch 
687030f984aSJacob Faibussowitsch   Level: beginner
688030f984aSJacob Faibussowitsch 
689030f984aSJacob Faibussowitsch .seealso: PetscDeviceContextSetCurrentContext(), PetscDeviceContextFork(),
690030f984aSJacob Faibussowitsch PetscDeviceContextJoin(), PetscDeviceContextCreate()
691030f984aSJacob Faibussowitsch @*/
692030f984aSJacob Faibussowitsch PetscErrorCode PetscDeviceContextGetCurrentContext(PetscDeviceContext *dctx)
693030f984aSJacob Faibussowitsch {
694030f984aSJacob Faibussowitsch   PetscFunctionBegin;
695030f984aSJacob Faibussowitsch   PetscValidPointer(dctx,1);
696030f984aSJacob Faibussowitsch   if (PetscUnlikely(!globalContextSetup)) {
697030f984aSJacob Faibussowitsch     PetscErrorCode ierr;
698030f984aSJacob Faibussowitsch 
699030f984aSJacob Faibussowitsch     /* if there is no available device backend, PetscDeviceInitializePackage() will fire a
700030f984aSJacob Faibussowitsch        PETSC_ERR_SUP_SYS error. */
701030f984aSJacob Faibussowitsch     ierr = PetscDeviceInitializePackage();CHKERRQ(ierr);
702030f984aSJacob Faibussowitsch     ierr = PetscDeviceContextSetUp(globalContext);CHKERRQ(ierr);
703030f984aSJacob Faibussowitsch     globalContextSetup = PETSC_TRUE;
704030f984aSJacob Faibussowitsch   }
705030f984aSJacob Faibussowitsch   *dctx = globalContext;
706030f984aSJacob Faibussowitsch   PetscFunctionReturn(0);
707030f984aSJacob Faibussowitsch }
708030f984aSJacob Faibussowitsch 
709030f984aSJacob Faibussowitsch /*@C
7105181c4f9SJacob Faibussowitsch   PetscDeviceContextSetCurrentContext - Set the current active PetscDeviceContext
711030f984aSJacob Faibussowitsch 
712030f984aSJacob Faibussowitsch   Not Collective, Asynchronous
713030f984aSJacob Faibussowitsch 
714030f984aSJacob Faibussowitsch   Input Parameter:
715030f984aSJacob Faibussowitsch . dctx - The PetscDeviceContext
716030f984aSJacob Faibussowitsch 
717030f984aSJacob Faibussowitsch   Notes:
718030f984aSJacob Faibussowitsch   The old context is not stored in any way by this routine; if one is overriding a context that they themselves do not
719030f984aSJacob Faibussowitsch   control, one should take care to temporarily store it by calling PetscDeviceContextGetCurrentContext() before calling
720030f984aSJacob Faibussowitsch   this routine.
721030f984aSJacob Faibussowitsch 
722030f984aSJacob Faibussowitsch   Level: beginner
723030f984aSJacob Faibussowitsch 
724030f984aSJacob Faibussowitsch .seealso: PetscDeviceContextGetCurrentContext(), PetscDeviceContextFork(),
725030f984aSJacob Faibussowitsch PetscDeviceContextJoin(), PetscDeviceContextCreate()
726030f984aSJacob Faibussowitsch @*/
727030f984aSJacob Faibussowitsch PetscErrorCode PetscDeviceContextSetCurrentContext(PetscDeviceContext dctx)
728030f984aSJacob Faibussowitsch {
729030f984aSJacob Faibussowitsch   PetscErrorCode ierr;
730030f984aSJacob Faibussowitsch 
731030f984aSJacob Faibussowitsch   PetscFunctionBegin;
732030f984aSJacob Faibussowitsch   PetscValidDeviceContext(dctx,1);
733030f984aSJacob Faibussowitsch   globalContext = dctx;
734030f984aSJacob Faibussowitsch   ierr = PetscInfo1(NULL,"Set global device context id %D\n",dctx->id);CHKERRQ(ierr);
735030f984aSJacob Faibussowitsch   PetscFunctionReturn(0);
736030f984aSJacob Faibussowitsch }
737030f984aSJacob Faibussowitsch 
738030f984aSJacob Faibussowitsch /*@C
739030f984aSJacob Faibussowitsch   PetscDeviceContextSetFromOptions - Configure a PetscDeviceContext from the options database
740030f984aSJacob Faibussowitsch 
741030f984aSJacob Faibussowitsch   Collective on comm, Asynchronous
742030f984aSJacob Faibussowitsch 
743030f984aSJacob Faibussowitsch   Input Parameters:
744030f984aSJacob Faibussowitsch + comm   - MPI communicator on which to query the options database
745030f984aSJacob Faibussowitsch . prefix - prefix to prepend to all options database queries, NULL if not needed
746030f984aSJacob Faibussowitsch - dctx   - The PetscDeviceContext to configure
747030f984aSJacob Faibussowitsch 
748030f984aSJacob Faibussowitsch   Output Parameter:
749030f984aSJacob Faibussowitsch . dctx - The PetscDeviceContext
750030f984aSJacob Faibussowitsch 
751030f984aSJacob Faibussowitsch   Options Database:
7525181c4f9SJacob Faibussowitsch . -device_context_device_kind - the kind of PetscDevice to attach by default - PetscDeviceKind
753030f984aSJacob Faibussowitsch . -device_context_stream_type - type of stream to create inside the PetscDeviceContext -
754030f984aSJacob Faibussowitsch   PetscDeviceContextSetStreamType()
755030f984aSJacob Faibussowitsch 
756030f984aSJacob Faibussowitsch   Level: beginner
757030f984aSJacob Faibussowitsch 
7585181c4f9SJacob Faibussowitsch .seealso: PetscDeviceContextSetStreamType(), PetscDeviceContextSetDevice()
759030f984aSJacob Faibussowitsch @*/
760030f984aSJacob Faibussowitsch PetscErrorCode PetscDeviceContextSetFromOptions(MPI_Comm comm, const char prefix[], PetscDeviceContext dctx)
761030f984aSJacob Faibussowitsch {
762030f984aSJacob Faibussowitsch   PetscBool      flag;
763030f984aSJacob Faibussowitsch   PetscInt       stype,dkind;
764030f984aSJacob Faibussowitsch   PetscErrorCode ierr;
765030f984aSJacob Faibussowitsch 
766030f984aSJacob Faibussowitsch   PetscFunctionBegin;
767030f984aSJacob Faibussowitsch   if (prefix) {PetscValidCharPointer(prefix,2);}
768030f984aSJacob Faibussowitsch   PetscValidDeviceContext(dctx,3);
769030f984aSJacob Faibussowitsch   ierr = PetscOptionsBegin(comm,prefix,"PetscDeviceContext Options","Sys");CHKERRQ(ierr);
770030f984aSJacob Faibussowitsch   ierr = PetscOptionsEList("-device_context_device_kind","Underlying PetscDevice","PetscDeviceContextSetDevice",PetscDeviceKinds+1,PETSC_DEVICE_MAX-1,dctx->device ? PetscDeviceKinds[dctx->device->kind] : PetscDeviceKinds[PETSC_DEVICE_DEFAULT],&dkind,&flag);CHKERRQ(ierr);
771030f984aSJacob Faibussowitsch   if (flag) {
772030f984aSJacob Faibussowitsch     ierr = PetscDeviceContextSetDevice(dctx,PetscDeviceDefaultKind_Internal(static_cast<PetscDeviceKind>(dkind+1)));CHKERRQ(ierr);
773030f984aSJacob Faibussowitsch   }
774030f984aSJacob Faibussowitsch   ierr = PetscOptionsEList("-device_context_stream_type","PetscDeviceContext PetscStreamType","PetscDeviceContextSetStreamType",PetscStreamTypes,3,PetscStreamTypes[dctx->streamType],&stype,&flag);CHKERRQ(ierr);
775030f984aSJacob Faibussowitsch   if (flag) {
776030f984aSJacob Faibussowitsch     ierr = PetscDeviceContextSetStreamType(dctx,static_cast<PetscStreamType>(stype));CHKERRQ(ierr);
777030f984aSJacob Faibussowitsch   }
778030f984aSJacob Faibussowitsch   ierr = PetscOptionsEnd();CHKERRQ(ierr);
779030f984aSJacob Faibussowitsch   PetscFunctionReturn(0);
780030f984aSJacob Faibussowitsch }
781