Actual source code: petscdevice.h
1: #ifndef PETSCDEVICE_H
2: #define PETSCDEVICE_H
4: #include <petscdevicetypes.h>
5: #include <petscviewertypes.h>
7: #if PETSC_CPP_VERSION >= 11 // C++11
8: #define PETSC_DEVICE_ALIGNOF(...) alignof(decltype(__VA_ARGS__))
9: #elif PETSC_C_VERSION >= 11 // C11
10: #ifdef __GNUC__
11: #define PETSC_DEVICE_ALIGNOF(...) _Alignof(__typeof__(__VA_ARGS__))
12: #else
13: #include <stddef.h> // max_align_t
14: // Note we cannot just do _Alignof(expression) since clang warns that "'_Alignof' applied to an
15: // expression is a GNU extension", so we just default to max_align_t which is ultra safe
16: #define PETSC_DEVICE_ALIGNOF(...) _Alignof(max_align_t)
17: #endif // __GNUC__
18: #else
19: #define PETSC_DEVICE_ALIGNOF(...) PETSC_MEMALIGN
20: #endif
22: /* SUBMANSEC = Sys */
24: // REVIEW ME: this should probably go somewhere better, configure-time?
25: #define PETSC_HAVE_HOST 1
27: /* logging support */
28: PETSC_EXTERN PetscClassId PETSC_DEVICE_CLASSID;
29: PETSC_EXTERN PetscClassId PETSC_DEVICE_CONTEXT_CLASSID;
31: PETSC_EXTERN PetscErrorCode PetscDeviceInitializePackage(void);
32: PETSC_EXTERN PetscErrorCode PetscDeviceFinalizePackage(void);
33: PETSC_EXTERN PetscErrorCode PetscGetMemType(const void *, PetscMemType *);
35: /* PetscDevice */
36: #if PetscDefined(HAVE_CXX)
37: PETSC_EXTERN PetscErrorCode PetscDeviceCreate(PetscDeviceType, PetscInt, PetscDevice *);
38: PETSC_EXTERN PetscErrorCode PetscDeviceDestroy(PetscDevice *);
39: PETSC_EXTERN PetscErrorCode PetscDeviceConfigure(PetscDevice);
40: PETSC_EXTERN PetscErrorCode PetscDeviceView(PetscDevice, PetscViewer);
41: PETSC_EXTERN PetscErrorCode PetscDeviceGetType(PetscDevice, PetscDeviceType *);
42: PETSC_EXTERN PetscErrorCode PetscDeviceGetDeviceId(PetscDevice, PetscInt *);
43: PETSC_EXTERN PetscDeviceType PETSC_DEVICE_DEFAULT(void);
44: PETSC_EXTERN PetscErrorCode PetscDeviceSetDefaultDeviceType(PetscDeviceType);
45: PETSC_EXTERN PetscErrorCode PetscDeviceInitialize(PetscDeviceType);
46: PETSC_EXTERN PetscBool PetscDeviceInitialized(PetscDeviceType);
47: #else
48: #define PetscDeviceCreate(PetscDeviceType, PetscInt, dev) (*(dev) = PETSC_NULLPTR, 0)
49: #define PetscDeviceDestroy(dev) (*(dev) = PETSC_NULLPTR, 0)
50: #define PetscDeviceConfigure(PetscDevice) 0
51: #define PetscDeviceView(PetscDevice, PetscViewer) 0
52: #define PetscDeviceGetType(PetscDevice, type) (*(type) = PETSC_DEVICE_DEFAULT(), 0)
53: #define PetscDeviceGetDeviceId(PetscDevice, id) (*(id) = 0)
54: #define PETSC_DEVICE_DEFAULT() PETSC_DEVICE_HOST
55: #define PetscDeviceSetDefaultDeviceType(PetscDeviceType) 0
56: #define PetscDeviceInitialize(PetscDeviceType) 0
57: #define PetscDeviceInitialized(dtype) ((dtype) == PETSC_DEVICE_HOST)
58: #endif /* PetscDefined(HAVE_CXX) */
60: /* PetscDeviceContext */
61: #if PetscDefined(HAVE_CXX)
62: PETSC_EXTERN PetscErrorCode PetscDeviceContextCreate(PetscDeviceContext *);
63: PETSC_EXTERN PetscErrorCode PetscDeviceContextDestroy(PetscDeviceContext *);
64: PETSC_EXTERN PetscErrorCode PetscDeviceContextSetStreamType(PetscDeviceContext, PetscStreamType);
65: PETSC_EXTERN PetscErrorCode PetscDeviceContextGetStreamType(PetscDeviceContext, PetscStreamType *);
66: PETSC_EXTERN PetscErrorCode PetscDeviceContextSetDevice(PetscDeviceContext, PetscDevice);
67: PETSC_EXTERN PetscErrorCode PetscDeviceContextGetDevice(PetscDeviceContext, PetscDevice *);
68: PETSC_EXTERN PetscErrorCode PetscDeviceContextGetDeviceType(PetscDeviceContext, PetscDeviceType *);
69: PETSC_EXTERN PetscErrorCode PetscDeviceContextSetUp(PetscDeviceContext);
70: PETSC_EXTERN PetscErrorCode PetscDeviceContextDuplicate(PetscDeviceContext, PetscDeviceContext *);
71: PETSC_EXTERN PetscErrorCode PetscDeviceContextQueryIdle(PetscDeviceContext, PetscBool *);
72: PETSC_EXTERN PetscErrorCode PetscDeviceContextWaitForContext(PetscDeviceContext, PetscDeviceContext);
73: PETSC_EXTERN PetscErrorCode PetscDeviceContextForkWithStreamType(PetscDeviceContext, PetscStreamType, PetscInt, PetscDeviceContext **);
74: PETSC_EXTERN PetscErrorCode PetscDeviceContextFork(PetscDeviceContext, PetscInt, PetscDeviceContext **);
75: PETSC_EXTERN PetscErrorCode PetscDeviceContextJoin(PetscDeviceContext, PetscInt, PetscDeviceContextJoinMode, PetscDeviceContext **);
76: PETSC_EXTERN PetscErrorCode PetscDeviceContextSynchronize(PetscDeviceContext);
77: PETSC_EXTERN PetscErrorCode PetscDeviceContextSetFromOptions(MPI_Comm, PetscDeviceContext);
78: PETSC_EXTERN PetscErrorCode PetscDeviceContextView(PetscDeviceContext, PetscViewer);
79: PETSC_EXTERN PetscErrorCode PetscDeviceContextViewFromOptions(PetscDeviceContext, PetscObject, PetscViewer);
80: PETSC_EXTERN PetscErrorCode PetscDeviceContextGetCurrentContext(PetscDeviceContext *);
81: PETSC_EXTERN PetscErrorCode PetscDeviceContextSetCurrentContext(PetscDeviceContext);
82: #else
83: #define PetscDeviceContextCreate(dctx) (*(dctx) = PETSC_NULLPTR, 0)
84: #define PetscDeviceContextDestroy(dctx) (*(dctx) = PETSC_NULLPTR, 0)
85: #define PetscDeviceContextSetStreamType(PetscDeviceContext, PetscStreamType) 0
86: #define PetscDeviceContextGetStreamType(PetscDeviceContext, type) (*(type) = PETSC_STREAM_GLOBAL_BLOCKING, 0)
87: #define PetscDeviceContextSetDevice(PetscDeviceContext, PetscDevice) 0
88: #define PetscDeviceContextGetDevice(PetscDeviceContext, device) (*(device) = PETSC_NULLPTR, 0)
89: #define PetscDeviceContextGetDeviceType(PetscDeviceContext, type) (*(type) = PETSC_DEVICE_DEFAULT())
90: #define PetscDeviceContextSetUp(PetscDeviceContext) 0
91: #define PetscDeviceContextDuplicate(PetscDeviceContextl, PetscDeviceContextr) (*(PetscDeviceContextr) = PETSC_NULLPTR, 0)
92: #define PetscDeviceContextQueryIdle(PetscDeviceContext, idle) (*(idle) = PETSC_TRUE, 0)
93: #define PetscDeviceContextWaitForContext(PetscDeviceContextl, PetscDeviceContextr) 0
94: #define PetscDeviceContextForkWithStreamType(PetscDeviceContextp, PetscStreamType, PetscInt, PetscDeviceContextc) (*(PetscDeviceContextc) = PETSC_NULLPTR, 0)
95: #define PetscDeviceContextFork(PetscDeviceContextp, PetscInt, PetscDeviceContextc) (*(PetscDeviceContextc) = PETSC_NULLPTR, 0)
96: #define PetscDeviceContextJoin(PetscDeviceContextp, PetscInt, PetscDeviceContextJoinMode, PetscDeviceContextc) (*(PetscDeviceContextc) = PETSC_NULLPTR, 0)
97: #define PetscDeviceContextSynchronize(PetscDeviceContext) 0
98: #define PetscDeviceContextSetFromOptions(MPI_Comm, PetscDeviceContext) 0
99: #define PetscDeviceContextView(PetscDeviceContext, PetscViewer) 0
100: #define PetscDeviceContextViewFromOptions(PetscDeviceContext, PetscObject, PetscViewer) 0
101: #define PetscDeviceContextGetCurrentContext(dctx) (*(dctx) = PETSC_NULLPTR, 0)
102: #define PetscDeviceContextSetCurrentContext(PetscDeviceContext) 0
103: #endif /* PetscDefined(HAVE_CXX) */
105: /* memory */
106: #if PetscDefined(HAVE_CXX)
107: PETSC_EXTERN PetscErrorCode PetscDeviceAllocate_Private(PetscDeviceContext, PetscBool, PetscMemType, size_t, size_t, void **PETSC_RESTRICT);
108: PETSC_EXTERN PetscErrorCode PetscDeviceDeallocate_Private(PetscDeviceContext, void *PETSC_RESTRICT);
109: PETSC_EXTERN PetscErrorCode PetscDeviceMemcpy(PetscDeviceContext, void *PETSC_RESTRICT, const void *PETSC_RESTRICT, size_t);
110: PETSC_EXTERN PetscErrorCode PetscDeviceMemset(PetscDeviceContext, void *PETSC_RESTRICT, PetscInt, size_t);
111: #else
112: #include <string.h> // memset()
113: #define PetscDeviceAllocate_Private(PetscDeviceContext, clear, PetscMemType, size, alignment, ptr) PetscMallocA(1, (clear), __LINE__, PETSC_FUNCTION_NAME, __FILE__, (size), (ptr))
114: #define PetscDeviceDeallocate_Private(PetscDeviceContext, ptr) PetscFree((ptr))
115: #define PetscDeviceMemcpy(PetscDeviceContext, dest, src, size) PetscMemcpy((dest), (src), (size))
116: #define PetscDeviceMemset(PetscDeviceContext, ptr, v, size) ((void)memset((ptr), (unsigned char)(v), (size)), 0)
117: #endif /* PetscDefined(HAVE_CXX) */
119: /*MC
120: PetscDeviceMalloc - Allocate device-aware memory
122: Synopsis:
123: #include <petscdevice.h>
124: PetscErrorCode PetscDeviceMalloc(PetscDeviceContext dctx, PetscMemType mtype, size_t n, Type **ptr)
126: Not Collective, Asynchronous, Auto-dependency aware
128: Input Parameters:
129: + dctx - The `PetscDeviceContext` used to allocate the memory
130: . mtype - The type of memory to allocate
131: - n - The amount (in elements) to allocate
133: Output Parameter:
134: . ptr - The pointer to store the result in
136: Notes:
137: Memory allocated with this function must be freed with `PetscDeviceFree()`.
139: If `n` is zero, then `ptr` is set to `PETSC_NULLPTR`.
141: This routine falls back to using `PetscMalloc1()` if PETSc was not configured with device
142: support. The user should note that `mtype` is ignored in this case, as `PetscMalloc1()`
143: allocates only host memory.
145: This routine uses the `sizeof()` of the memory type requested to determine the total memory
146: to be allocated, therefore you should not multiply the number of elements requested by the
147: `sizeof()` the type\:
149: .vb
150: PetscInt *arr;
152: // correct
153: PetscDeviceMalloc(dctx,PETSC_MEMTYPE_DEVICE,n,&arr);
155: // incorrect
156: PetscDeviceMalloc(dctx,PETSC_MEMTYPE_DEVICE,n*sizeof(*arr),&arr);
157: .ve
159: Note result stored `ptr` is immediately valid and the user may freely inspect or manipulate
160: its value on function return, i.e.\:
162: .vb
163: PetscInt *ptr;
165: PetscDeviceMalloc(dctx, PETSC_MEMTYPE_DEVICE, 20, &ptr);
167: PetscInt *sub_ptr = ptr + 10; // OK, no need to synchronize
169: ptr[0] = 10; // ERROR, directly accessing contents of ptr is undefined until synchronization
170: .ve
172: DAG representation:
173: .vb
174: time ->
176: -> dctx - |= CALL =| -\- dctx -->
177: \- ptr ->
178: .ve
180: Level: beginner
182: .N ASYNC_API
184: .seealso: `PetscDeviceFree()`, `PetscDeviceCalloc()`, `PetscDeviceArrayCopy()`,
185: `PetscDeviceArrayZero()`
186: M*/
187: #define PetscDeviceMalloc(dctx, mtype, n, ptr) PetscDeviceAllocate_Private((dctx), PETSC_FALSE, (mtype), (size_t)(n) * sizeof(**(ptr)), PETSC_DEVICE_ALIGNOF(**(ptr)), (void **)(ptr))
189: /*MC
190: PetscDeviceCalloc - Allocate zeroed device-aware memory
192: Synopsis:
193: #include <petscdevice.h>
194: PetscErrorCode PetscDeviceCalloc(PetscDeviceContext dctx, PetscMemType mtype, size_t n, Type **ptr)
196: Not Collective, Asynchronous, Auto-dependency aware
198: Input Parameters:
199: + dctx - The `PetscDeviceContext` used to allocate the memory
200: . mtype - The type of memory to allocate
201: - n - The amount (in elements) to allocate
203: Output Parameter:
204: . ptr - The pointer to store the result in
206: Notes:
207: Has identical usage to `PetscDeviceMalloc()` except that the memory is zeroed before it is
208: returned. See `PetscDeviceMalloc()` for further discussion.
210: This routine falls back to using `PetscCalloc1()` if PETSc was not configured with device
211: support. The user should note that `mtype` is ignored in this case, as `PetscCalloc1()`
212: allocates only host memory.
214: Level: beginner
216: .N ASYNC_API
218: .seealso: `PetscDeviceFree()`, `PetscDeviceMalloc()`, `PetscDeviceArrayCopy()`,
219: `PetscDeviceArrayZero()`
220: M*/
221: #define PetscDeviceCalloc(dctx, mtype, n, ptr) PetscDeviceAllocate_Private((dctx), PETSC_TRUE, (mtype), (size_t)(n) * sizeof(**(ptr)), PETSC_DEVICE_ALIGNOF(**(ptr)), (void **)(ptr))
223: /*MC
224: PetscDeviceFree - Free device-aware memory
226: Synopsis:
227: #include <petscdevice.h>
228: PetscErrorCode PetscDeviceFree(PetscDeviceContext dctx, void *ptr)
230: Not Collective, Asynchronous, Auto-dependency aware
232: Input Parameters:
233: + dctx - The `PetscDeviceContext` used to free the memory
234: - ptr - The pointer to free
236: Notes:
237: `ptr` may be `NULL`, and is set to `PETSC_NULLPTR` on successful deallocation.
239: `ptr` must have been allocated using `PetscDeviceMalloc()`, `PetscDeviceCalloc()`.
241: This routine falls back to using `PetscFree()` if PETSc was not configured with device
242: support. The user should note that `PetscFree()` frees only host memory.
244: DAG representation:
245: .vb
246: time ->
248: -> dctx -/- |= CALL =| - dctx ->
249: -> ptr -/
250: .ve
252: Level: beginner
254: .N ASYNC_API
256: .seealso: `PetscDeviceMalloc()`, `PetscDeviceCalloc()`
257: M*/
258: #define PetscDeviceFree(dctx, ptr) (PetscDeviceDeallocate_Private((dctx), (ptr)) || ((ptr) = PETSC_NULLPTR, 0))
260: /*MC
261: PetscDeviceArrayCopy - Copy memory in a device-aware manner
263: Synopsis:
264: #include <petscdevice.h>
265: PetscErrorCode PetscDeviceArrayCopy(PetscDeviceContext dctx, void *dest, const void *src, size_t n)
267: Not Collective, Asynchronous, Auto-dependency aware
269: Input Parameters:
270: + dctx - The `PetscDeviceContext` used to copy the memory
271: . dest - The pointer to copy to
272: . src - The pointer to copy from
273: - n - The amount (in elements) to copy
275: Notes:
276: Both `dest` and `src` must have been allocated using any of `PetscDeviceMalloc()`,
277: `PetscDeviceCalloc()`.
279: This uses the `sizeof()` of the `src` memory type requested to determine the total memory to
280: be copied, therefore you should not multiply the number of elements by the `sizeof()` the
281: type\:
283: .vb
284: PetscInt *to,*from;
286: // correct
287: PetscDeviceArrayCopy(dctx,to,from,n);
289: // incorrect
290: PetscDeviceArrayCopy(dctx,to,from,n*sizeof(*from));
291: .ve
293: See `PetscDeviceMemcpy()` for further discussion.
295: Level: beginner
297: .N ASYNC_API
299: .seealso: `PetscDeviceMalloc()`, `PetscDeviceCalloc()`, `PetscDeviceFree()`,
300: `PetscDeviceArrayZero()`, `PetscDeviceMemcpy()`
301: M*/
302: #define PetscDeviceArrayCopy(dctx, dest, src, n) PetscDeviceMemcpy((dctx), (dest), (src), (size_t)(n) * sizeof(*(src)))
304: /*MC
305: PetscDeviceArrayZero - Zero memory in a device-aware manner
307: Synopsis:
308: #include <petscdevice.h>
309: PetscErrorCode PetscDeviceArrayZero(PetscDeviceContext dctx, void *ptr, size_t n)
311: Not Collective, Asynchronous, Auto-dependency aware
313: Input Parameters:
314: + dctx - The `PetscDeviceContext` used to zero the memory
315: . ptr - The pointer to the memory
316: - n - The amount (in elements) to zero
318: Notes:
319: `ptr` must have been allocated using `PetscDeviceMalloc()` or `PetscDeviceCalloc()`.
321: This uses the `sizeof()` of the memory type requested to determine the total memory to be
322: zeroed, therefore you should not multiply the number of elements by the `sizeof()` the type\:
324: .vb
325: PetscInt *ptr;
327: // correct
328: PetscDeviceArrayZero(dctx,ptr,n);
330: // incorrect
331: PetscDeviceArrayZero(dctx,ptr,n*sizeof(*ptr));
332: .ve
334: See `PetscDeviceMemset()` for further discussion.
336: Level: beginner
338: .N ASYNC_API
340: .seealso: `PetscDeviceMalloc()`, `PetscDeviceCalloc()`, `PetscDeviceFree()`,
341: `PetscDeviceArrayCopy()`, `PetscDeviceMemset()`
342: M*/
343: #define PetscDeviceArrayZero(dctx, ptr, n) PetscDeviceMemset((dctx), (ptr), 0, (size_t)(n) * sizeof(*(ptr)))
345: #endif /* PETSCDEVICE_H */