Actual source code: petscdevice.h

      1: #pragma once

      3: #include <petscdevicetypes.h>
      4: #include <petscviewertypes.h>

      6: #if PETSC_CPP_VERSION >= 11 // C++11
      7:   #define PETSC_DEVICE_ALIGNOF(...) alignof(decltype(__VA_ARGS__))
      8: #elif PETSC_C_VERSION >= 11 // C11
      9:   #ifdef __GNUC__
     10:     #define PETSC_DEVICE_ALIGNOF(...) _Alignof(__typeof__(__VA_ARGS__))
     11:   #else
     12:     #include <stddef.h> // max_align_t
     13:     // Note we cannot just do _Alignof(expression) since clang warns that "'_Alignof' applied to an
     14:     // expression is a GNU extension", so we just default to max_align_t which is ultra safe
     15:     #define PETSC_DEVICE_ALIGNOF(...) _Alignof(max_align_t)
     16:   #endif // __GNUC__
     17: #else
     18:   #define PETSC_DEVICE_ALIGNOF(...) PETSC_MEMALIGN
     19: #endif

     21: /* MANSEC = Sys */
     22: /* SUBMANSEC = Device */

     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: PETSC_EXTERN PetscErrorCode  PetscDeviceCreate(PetscDeviceType, PetscInt, PetscDevice *);
     37: PETSC_EXTERN PetscErrorCode  PetscDeviceDestroy(PetscDevice *);
     38: PETSC_EXTERN PetscErrorCode  PetscDeviceConfigure(PetscDevice);
     39: PETSC_EXTERN PetscErrorCode  PetscDeviceView(PetscDevice, PetscViewer);
     40: PETSC_EXTERN PetscErrorCode  PetscDeviceGetType(PetscDevice, PetscDeviceType *);
     41: PETSC_EXTERN PetscErrorCode  PetscDeviceGetDeviceId(PetscDevice, PetscInt *);
     42: PETSC_EXTERN PetscDeviceType PETSC_DEVICE_DEFAULT(void);
     43: PETSC_EXTERN PetscErrorCode  PetscDeviceSetDefaultDeviceType(PetscDeviceType);
     44: PETSC_EXTERN PetscErrorCode  PetscDeviceInitialize(PetscDeviceType);
     45: PETSC_EXTERN PetscBool       PetscDeviceInitialized(PetscDeviceType);

     47: /* PetscDeviceContext */
     48: PETSC_EXTERN PetscErrorCode PetscDeviceContextCreate(PetscDeviceContext *);
     49: PETSC_EXTERN PetscErrorCode PetscDeviceContextDestroy(PetscDeviceContext *);
     50: PETSC_EXTERN PetscErrorCode PetscDeviceContextSetStreamType(PetscDeviceContext, PetscStreamType);
     51: PETSC_EXTERN PetscErrorCode PetscDeviceContextGetStreamType(PetscDeviceContext, PetscStreamType *);
     52: PETSC_EXTERN PetscErrorCode PetscDeviceContextSetDevice(PetscDeviceContext, PetscDevice);
     53: PETSC_EXTERN PetscErrorCode PetscDeviceContextGetDevice(PetscDeviceContext, PetscDevice *);
     54: PETSC_EXTERN PetscErrorCode PetscDeviceContextGetDeviceType(PetscDeviceContext, PetscDeviceType *);
     55: PETSC_EXTERN PetscErrorCode PetscDeviceContextSetUp(PetscDeviceContext);
     56: PETSC_EXTERN PetscErrorCode PetscDeviceContextDuplicate(PetscDeviceContext, PetscDeviceContext *);
     57: PETSC_EXTERN PetscErrorCode PetscDeviceContextQueryIdle(PetscDeviceContext, PetscBool *);
     58: PETSC_EXTERN PetscErrorCode PetscDeviceContextWaitForContext(PetscDeviceContext, PetscDeviceContext);
     59: PETSC_EXTERN PetscErrorCode PetscDeviceContextForkWithStreamType(PetscDeviceContext, PetscStreamType, PetscInt, PetscDeviceContext **);
     60: PETSC_EXTERN PetscErrorCode PetscDeviceContextFork(PetscDeviceContext, PetscInt, PetscDeviceContext **);
     61: PETSC_EXTERN PetscErrorCode PetscDeviceContextJoin(PetscDeviceContext, PetscInt, PetscDeviceContextJoinMode, PetscDeviceContext **);
     62: PETSC_EXTERN PetscErrorCode PetscDeviceContextSynchronize(PetscDeviceContext);
     63: PETSC_EXTERN PetscErrorCode PetscDeviceContextSetFromOptions(MPI_Comm, PetscDeviceContext);
     64: PETSC_EXTERN PetscErrorCode PetscDeviceContextView(PetscDeviceContext, PetscViewer);
     65: PETSC_EXTERN PetscErrorCode PetscDeviceContextViewFromOptions(PetscDeviceContext, PetscObject, const char[]);
     66: PETSC_EXTERN PetscErrorCode PetscDeviceContextGetCurrentContext(PetscDeviceContext *);
     67: PETSC_EXTERN PetscErrorCode PetscDeviceContextSetCurrentContext(PetscDeviceContext);
     68: PETSC_EXTERN PetscErrorCode PetscDeviceContextGetStreamHandle(PetscDeviceContext, void **);

     70: /* memory */
     71: PETSC_EXTERN PetscErrorCode PetscDeviceAllocate_Private(PetscDeviceContext, PetscBool, PetscMemType, size_t, size_t, void **PETSC_RESTRICT);
     72: PETSC_EXTERN PetscErrorCode PetscDeviceDeallocate_Private(PetscDeviceContext, void *PETSC_RESTRICT);
     73: PETSC_EXTERN PetscErrorCode PetscDeviceMemcpy(PetscDeviceContext, void *PETSC_RESTRICT, const void *PETSC_RESTRICT, size_t);
     74: PETSC_EXTERN PetscErrorCode PetscDeviceMemset(PetscDeviceContext, void *PETSC_RESTRICT, PetscInt, size_t);

     76: /*MC
     77:   PetscDeviceMalloc - Allocate device-aware memory

     79:   Synopsis:
     80: #include <petscdevice.h>
     81:   PetscErrorCode PetscDeviceMalloc(PetscDeviceContext dctx, PetscMemType mtype, size_t n, Type **ptr)

     83:   Not Collective, Asynchronous, Auto-dependency aware

     85:   Input Parameters:
     86: + dctx  - The `PetscDeviceContext` used to allocate the memory
     87: . mtype - The type of memory to allocate
     88: - n     - The amount (in elements) to allocate

     90:   Output Parameter:
     91: . ptr - The pointer to store the result in

     93:   Level: beginner

     95:   Notes:
     96:   Memory allocated with this function must be freed with `PetscDeviceFree()`.

     98:   If `n` is zero, then `ptr` is set to `PETSC_NULLPTR`.

    100:   This routine falls back to using `PetscMalloc1()` if PETSc was not configured with device
    101:   support. The user should note that `mtype` is ignored in this case, as `PetscMalloc1()`
    102:   allocates only host memory.

    104:   This routine uses the `sizeof()` of the memory type requested to determine the total memory
    105:   to be allocated, therefore you should not multiply the number of elements requested by the
    106:   `sizeof()` the type\:

    108: .vb
    109:   PetscInt *arr;

    111:   // correct
    112:   PetscDeviceMalloc(dctx,PETSC_MEMTYPE_DEVICE,n,&arr);

    114:   // incorrect
    115:   PetscDeviceMalloc(dctx,PETSC_MEMTYPE_DEVICE,n*sizeof(*arr),&arr);
    116: .ve

    118:   Note result stored `ptr` is immediately valid and the user may freely inspect or manipulate
    119:   its value on function return, i.e.\:

    121: .vb
    122:   PetscInt *ptr;

    124:   PetscDeviceMalloc(dctx, PETSC_MEMTYPE_DEVICE, 20, &ptr);

    126:   PetscInt *sub_ptr = ptr + 10; // OK, no need to synchronize

    128:   ptr[0] = 10; // ERROR, directly accessing contents of ptr is undefined until synchronization
    129: .ve

    131:   DAG representation:
    132: .vb
    133:   time ->

    135:   -> dctx - |= CALL =| -\- dctx -->
    136:                          \- ptr ->
    137: .ve

    139: .N ASYNC_API

    141: .seealso: `PetscDeviceFree()`, `PetscDeviceCalloc()`, `PetscDeviceArrayCopy()`,
    142: `PetscDeviceArrayZero()`
    143: M*/
    144: #define PetscDeviceMalloc(dctx, mtype, n, ptr) PetscDeviceAllocate_Private((dctx), PETSC_FALSE, (mtype), (size_t)(n) * sizeof(**(ptr)), PETSC_DEVICE_ALIGNOF(**(ptr)), (void **)(ptr))

    146: /*MC
    147:   PetscDeviceCalloc - Allocate zeroed device-aware memory

    149:   Synopsis:
    150: #include <petscdevice.h>
    151:   PetscErrorCode PetscDeviceCalloc(PetscDeviceContext dctx, PetscMemType mtype, size_t n, Type **ptr)

    153:   Not Collective, Asynchronous, Auto-dependency aware

    155:   Input Parameters:
    156: + dctx  - The `PetscDeviceContext` used to allocate the memory
    157: . mtype - The type of memory to allocate
    158: - n     - The amount (in elements) to allocate

    160:   Output Parameter:
    161: . ptr - The pointer to store the result in

    163:   Level: beginner

    165:   Notes:
    166:   Has identical usage to `PetscDeviceMalloc()` except that the memory is zeroed before it is
    167:   returned. See `PetscDeviceMalloc()` for further discussion.

    169:   This routine falls back to using `PetscCalloc1()` if PETSc was not configured with device
    170:   support. The user should note that `mtype` is ignored in this case, as `PetscCalloc1()`
    171:   allocates only host memory.

    173: .N ASYNC_API

    175: .seealso: `PetscDeviceFree()`, `PetscDeviceMalloc()`, `PetscDeviceArrayCopy()`,
    176: `PetscDeviceArrayZero()`
    177: M*/
    178: #define PetscDeviceCalloc(dctx, mtype, n, ptr) PetscDeviceAllocate_Private((dctx), PETSC_TRUE, (mtype), (size_t)(n) * sizeof(**(ptr)), PETSC_DEVICE_ALIGNOF(**(ptr)), (void **)(ptr))

    180: /*MC
    181:   PetscDeviceFree - Free device-aware memory obtained with  `PetscDeviceMalloc()` or `PetscDeviceCalloc()`

    183:   Synopsis:
    184: #include <petscdevice.h>
    185:   PetscErrorCode PetscDeviceFree(PetscDeviceContext dctx, void *ptr)

    187:   Not Collective, Asynchronous, Auto-dependency aware

    189:   Input Parameters:
    190: + dctx - The `PetscDeviceContext` used to free the memory
    191: - ptr  - The pointer to free, may be `NULL`

    193:   Level: beginner

    195:   Notes:
    196:   `ptr` is set to `PETSC_NULLPTR` on successful deallocation.

    198:   `ptr` must have been allocated using `PetscDeviceMalloc()`, `PetscDeviceCalloc()` not `PetscMalloc()` or related routines

    200:   This routine falls back to using `PetscFree()` if PETSc was not configured with device
    201:   support. The user should note that `PetscFree()` frees only host memory.

    203:   DAG representation:
    204: .vb
    205:   time ->

    207:   -> dctx -/- |= CALL =| - dctx ->
    208:   -> ptr -/
    209: .ve

    211: .N ASYNC_API

    213: .seealso: `PetscDeviceMalloc()`, `PetscDeviceCalloc()`
    214: M*/
    215: #define PetscDeviceFree(dctx, ptr) ((PetscErrorCode)(PetscDeviceDeallocate_Private((dctx), (ptr)) || ((ptr) = PETSC_NULLPTR, PETSC_SUCCESS)))

    217: /*MC
    218:   PetscDeviceArrayCopy - Copy memory in a device-aware manner

    220:   Synopsis:
    221: #include <petscdevice.h>
    222:   PetscErrorCode PetscDeviceArrayCopy(PetscDeviceContext dctx, void *dest, const void *src, size_t n)

    224:   Not Collective, Asynchronous, Auto-dependency aware

    226:   Input Parameters:
    227: + dctx - The `PetscDeviceContext` used to copy the memory
    228: . dest - The pointer to copy to
    229: . src  - The pointer to copy from
    230: - n    - The amount (in elements) to copy

    232:   Notes:
    233:   Both `dest` and `src` must have been allocated using `PetscDeviceMalloc()` or
    234:   `PetscDeviceCalloc()`.

    236:   This uses the `sizeof()` of the `src` memory type requested to determine the total memory to
    237:   be copied, therefore you should not multiply the number of elements by the `sizeof()` the
    238:   type\:

    240: .vb
    241:   PetscInt *to,*from;

    243:   // correct
    244:   PetscDeviceArrayCopy(dctx,to,from,n);

    246:   // incorrect
    247:   PetscDeviceArrayCopy(dctx,to,from,n*sizeof(*from));
    248: .ve

    250:   See `PetscDeviceMemcpy()` for further discussion.

    252:   Level: beginner

    254: .N ASYNC_API

    256: .seealso: `PetscDeviceMalloc()`, `PetscDeviceCalloc()`, `PetscDeviceFree()`,
    257: `PetscDeviceArrayZero()`, `PetscDeviceMemcpy()`
    258: M*/
    259: #define PetscDeviceArrayCopy(dctx, dest, src, n) PetscDeviceMemcpy((dctx), (dest), (src), (size_t)(n) * sizeof(*(src)))

    261: /*MC
    262:   PetscDeviceArrayZero - Zero memory in a device-aware manner

    264:   Synopsis:
    265: #include <petscdevice.h>
    266:   PetscErrorCode PetscDeviceArrayZero(PetscDeviceContext dctx, void *ptr, size_t n)

    268:   Not Collective, Asynchronous, Auto-dependency aware

    270:   Input Parameters:
    271: + dctx  - The `PetscDeviceContext` used to zero the memory
    272: . ptr   - The pointer to the memory
    273: - n     - The amount (in elements) to zero

    275:   Level: beginner

    277:   Notes:
    278:   `ptr` must have been allocated using `PetscDeviceMalloc()` or `PetscDeviceCalloc()`.

    280:   This uses the `sizeof()` of the memory type requested to determine the total memory to be
    281:   zeroed, therefore you should not multiply the number of elements by the `sizeof()` the type\:

    283: .vb
    284:   PetscInt *ptr;

    286:   // correct
    287:   PetscDeviceArrayZero(dctx,ptr,n);

    289:   // incorrect
    290:   PetscDeviceArrayZero(dctx,ptr,n*sizeof(*ptr));
    291: .ve

    293:   See `PetscDeviceMemset()` for further discussion.

    295: .N ASYNC_API

    297: .seealso: `PetscDeviceMalloc()`, `PetscDeviceCalloc()`, `PetscDeviceFree()`,
    298: `PetscDeviceArrayCopy()`, `PetscDeviceMemset()`
    299: M*/
    300: #define PetscDeviceArrayZero(dctx, ptr, n) PetscDeviceMemset((dctx), (ptr), 0, (size_t)(n) * sizeof(*(ptr)))