1030f984aSJacob Faibussowitsch #if !defined(PETSCDEVICECONTEXTCUPM_HPP) 2030f984aSJacob Faibussowitsch #define PETSCDEVICECONTEXTCUPM_HPP 3030f984aSJacob Faibussowitsch 4*a4af0ceeSJacob Faibussowitsch #include <petsc/private/deviceimpl.h> 5030f984aSJacob Faibussowitsch #include <petsc/private/cupminterface.hpp> 6030f984aSJacob Faibussowitsch 7030f984aSJacob Faibussowitsch #if !defined(PETSC_HAVE_CXX_DIALECT_CXX11) 8030f984aSJacob Faibussowitsch #error PetscDeviceContext backends for CUDA and HIP requires C++11 9030f984aSJacob Faibussowitsch #endif 10030f984aSJacob Faibussowitsch 11*a4af0ceeSJacob Faibussowitsch #include <array> 12*a4af0ceeSJacob Faibussowitsch 13*a4af0ceeSJacob Faibussowitsch namespace Petsc 14*a4af0ceeSJacob Faibussowitsch { 15*a4af0ceeSJacob Faibussowitsch 16*a4af0ceeSJacob Faibussowitsch namespace detail 17*a4af0ceeSJacob Faibussowitsch { 18*a4af0ceeSJacob Faibussowitsch 19*a4af0ceeSJacob Faibussowitsch // for tag-based dispatch of handle retrieval 20*a4af0ceeSJacob Faibussowitsch template <typename HT> struct HandleTag { }; 21*a4af0ceeSJacob Faibussowitsch 22*a4af0ceeSJacob Faibussowitsch } // namespace detail 23030f984aSJacob Faibussowitsch 24030f984aSJacob Faibussowitsch // Forward declare 25*a4af0ceeSJacob Faibussowitsch template <CUPMDeviceType T> class CUPMContext; 26030f984aSJacob Faibussowitsch 27*a4af0ceeSJacob Faibussowitsch template <CUPMDeviceType T> 28030f984aSJacob Faibussowitsch class CUPMContext : CUPMInterface<T> 29030f984aSJacob Faibussowitsch { 30*a4af0ceeSJacob Faibussowitsch template <typename H> 31*a4af0ceeSJacob Faibussowitsch using HandleTag = typename detail::HandleTag<H>; 32*a4af0ceeSJacob Faibussowitsch 33030f984aSJacob Faibussowitsch public: 341b6e0089SPierre Jolivet PETSC_INHERIT_CUPM_INTERFACE_TYPEDEFS_USING(cupmInterface_t,T) 35030f984aSJacob Faibussowitsch 36030f984aSJacob Faibussowitsch // This is the canonical PETSc "impls" struct that normally resides in a standalone impls 37030f984aSJacob Faibussowitsch // header, but since we are using the power of templates it must be declared part of 38030f984aSJacob Faibussowitsch // this class to have easy access the same typedefs. Technically one can make a 39030f984aSJacob Faibussowitsch // templated struct outside the class but it's more code for the same result. 40030f984aSJacob Faibussowitsch struct PetscDeviceContext_IMPLS 41030f984aSJacob Faibussowitsch { 42030f984aSJacob Faibussowitsch cupmStream_t stream; 43030f984aSJacob Faibussowitsch cupmEvent_t event; 44*a4af0ceeSJacob Faibussowitsch cupmEvent_t begin; // timer-only 45*a4af0ceeSJacob Faibussowitsch cupmEvent_t end; // timer-only 46*a4af0ceeSJacob Faibussowitsch #if PetscDefined(USE_DEBUG) 47*a4af0ceeSJacob Faibussowitsch PetscBool timerInUse; 48*a4af0ceeSJacob Faibussowitsch #endif 49030f984aSJacob Faibussowitsch cupmBlasHandle_t blas; 50030f984aSJacob Faibussowitsch cupmSolverHandle_t solver; 51*a4af0ceeSJacob Faibussowitsch 52*a4af0ceeSJacob Faibussowitsch PETSC_NODISCARD cupmBlasHandle_t handle(HandleTag<cupmBlasHandle_t>) { return blas; } 53*a4af0ceeSJacob Faibussowitsch PETSC_NODISCARD cupmSolverHandle_t handle(HandleTag<cupmSolverHandle_t>) { return solver; } 54030f984aSJacob Faibussowitsch }; 55030f984aSJacob Faibussowitsch 56030f984aSJacob Faibussowitsch private: 57*a4af0ceeSJacob Faibussowitsch static bool _initialized; 58*a4af0ceeSJacob Faibussowitsch static std::array<cupmBlasHandle_t,PETSC_DEVICE_MAX_DEVICES> _blashandles; 59*a4af0ceeSJacob Faibussowitsch static std::array<cupmSolverHandle_t,PETSC_DEVICE_MAX_DEVICES> _solverhandles; 60030f984aSJacob Faibussowitsch 61*a4af0ceeSJacob Faibussowitsch PETSC_NODISCARD static constexpr PetscDeviceContext_IMPLS* __impls_cast(PetscDeviceContext ptr) noexcept 62*a4af0ceeSJacob Faibussowitsch { 63*a4af0ceeSJacob Faibussowitsch return static_cast<PetscDeviceContext_IMPLS*>(ptr->data); 64*a4af0ceeSJacob Faibussowitsch } 65*a4af0ceeSJacob Faibussowitsch 66*a4af0ceeSJacob Faibussowitsch PETSC_NODISCARD static PetscErrorCode __finalize() noexcept 67030f984aSJacob Faibussowitsch { 68030f984aSJacob Faibussowitsch PetscErrorCode ierr; 69030f984aSJacob Faibussowitsch 70030f984aSJacob Faibussowitsch PetscFunctionBegin; 71*a4af0ceeSJacob Faibussowitsch for (auto&& handle : _blashandles) { 72*a4af0ceeSJacob Faibussowitsch if (handle) {ierr = cupmInterface_t::DestroyHandle(handle);CHKERRQ(ierr);} 73*a4af0ceeSJacob Faibussowitsch } 74*a4af0ceeSJacob Faibussowitsch for (auto&& handle : _solverhandles) { 75*a4af0ceeSJacob Faibussowitsch if (handle) {ierr = cupmInterface_t::DestroyHandle(handle);CHKERRQ(ierr);} 76*a4af0ceeSJacob Faibussowitsch } 77*a4af0ceeSJacob Faibussowitsch _initialized = false; 78030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 79030f984aSJacob Faibussowitsch } 80030f984aSJacob Faibussowitsch 81*a4af0ceeSJacob Faibussowitsch PETSC_NODISCARD static PetscErrorCode __initialize(PetscInt id, PetscDeviceContext_IMPLS *dci) noexcept 82030f984aSJacob Faibussowitsch { 83030f984aSJacob Faibussowitsch PetscErrorCode ierr; 84030f984aSJacob Faibussowitsch 85030f984aSJacob Faibussowitsch PetscFunctionBegin; 86*a4af0ceeSJacob Faibussowitsch ierr = PetscDeviceCheckDeviceCount_Internal(id);CHKERRQ(ierr); 87*a4af0ceeSJacob Faibussowitsch if (!_initialized) { 88*a4af0ceeSJacob Faibussowitsch _initialized = true; 89*a4af0ceeSJacob Faibussowitsch ierr = PetscRegisterFinalize(__finalize);CHKERRQ(ierr); 90030f984aSJacob Faibussowitsch } 91*a4af0ceeSJacob Faibussowitsch // use the blashandle as a canary 92*a4af0ceeSJacob Faibussowitsch if (!_blashandles[id]) { 93*a4af0ceeSJacob Faibussowitsch ierr = cupmInterface_t::InitializeHandle(_blashandles[id]);CHKERRQ(ierr); 94*a4af0ceeSJacob Faibussowitsch ierr = cupmInterface_t::InitializeHandle(_solverhandles[id]);CHKERRQ(ierr); 95030f984aSJacob Faibussowitsch } 96*a4af0ceeSJacob Faibussowitsch ierr = cupmInterface_t::SetHandleStream(_blashandles[id],dci->stream);CHKERRQ(ierr); 97*a4af0ceeSJacob Faibussowitsch ierr = cupmInterface_t::SetHandleStream(_solverhandles[id],dci->stream);CHKERRQ(ierr); 98*a4af0ceeSJacob Faibussowitsch dci->blas = _blashandles[id]; 99*a4af0ceeSJacob Faibussowitsch dci->solver = _solverhandles[id]; 100030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 101030f984aSJacob Faibussowitsch } 102030f984aSJacob Faibussowitsch 103030f984aSJacob Faibussowitsch public: 104*a4af0ceeSJacob Faibussowitsch const struct _DeviceContextOps ops = { 105*a4af0ceeSJacob Faibussowitsch destroy, 106*a4af0ceeSJacob Faibussowitsch changeStreamType, 107*a4af0ceeSJacob Faibussowitsch setUp, 108*a4af0ceeSJacob Faibussowitsch query, 109*a4af0ceeSJacob Faibussowitsch waitForContext, 110*a4af0ceeSJacob Faibussowitsch synchronize, 111*a4af0ceeSJacob Faibussowitsch getHandle<cupmBlasHandle_t>, 112*a4af0ceeSJacob Faibussowitsch getHandle<cupmSolverHandle_t>, 113*a4af0ceeSJacob Faibussowitsch beginTimer, 114*a4af0ceeSJacob Faibussowitsch endTimer 115*a4af0ceeSJacob Faibussowitsch }; 116030f984aSJacob Faibussowitsch 117030f984aSJacob Faibussowitsch // default constructor 118030f984aSJacob Faibussowitsch constexpr CUPMContext() noexcept = default; 119030f984aSJacob Faibussowitsch 120030f984aSJacob Faibussowitsch // All of these functions MUST be static in order to be callable from C, otherwise they 121030f984aSJacob Faibussowitsch // get the implicit 'this' pointer tacked on 122030f984aSJacob Faibussowitsch PETSC_NODISCARD static PetscErrorCode destroy(PetscDeviceContext) noexcept; 123030f984aSJacob Faibussowitsch PETSC_NODISCARD static PetscErrorCode changeStreamType(PetscDeviceContext,PetscStreamType) noexcept; 124030f984aSJacob Faibussowitsch PETSC_NODISCARD static PetscErrorCode setUp(PetscDeviceContext) noexcept; 125030f984aSJacob Faibussowitsch PETSC_NODISCARD static PetscErrorCode query(PetscDeviceContext,PetscBool*) noexcept; 126030f984aSJacob Faibussowitsch PETSC_NODISCARD static PetscErrorCode waitForContext(PetscDeviceContext,PetscDeviceContext) noexcept; 127030f984aSJacob Faibussowitsch PETSC_NODISCARD static PetscErrorCode synchronize(PetscDeviceContext) noexcept; 128*a4af0ceeSJacob Faibussowitsch template <typename Handle_t> 129*a4af0ceeSJacob Faibussowitsch PETSC_NODISCARD static PetscErrorCode getHandle(PetscDeviceContext,void*) noexcept; 130*a4af0ceeSJacob Faibussowitsch PETSC_NODISCARD static PetscErrorCode beginTimer(PetscDeviceContext) noexcept; 131*a4af0ceeSJacob Faibussowitsch PETSC_NODISCARD static PetscErrorCode endTimer(PetscDeviceContext,PetscLogDouble*) noexcept; 132030f984aSJacob Faibussowitsch }; 133030f984aSJacob Faibussowitsch 134*a4af0ceeSJacob Faibussowitsch template <CUPMDeviceType T> 135030f984aSJacob Faibussowitsch inline PetscErrorCode CUPMContext<T>::destroy(PetscDeviceContext dctx) noexcept 136030f984aSJacob Faibussowitsch { 137030f984aSJacob Faibussowitsch cupmError_t cerr; 138030f984aSJacob Faibussowitsch PetscErrorCode ierr; 139*a4af0ceeSJacob Faibussowitsch auto dci = __impls_cast(dctx); 140030f984aSJacob Faibussowitsch 141030f984aSJacob Faibussowitsch PetscFunctionBegin; 142030f984aSJacob Faibussowitsch if (dci->stream) {cerr = cupmStreamDestroy(dci->stream);CHKERRCUPM(cerr);} 143*a4af0ceeSJacob Faibussowitsch if (dci->event) { 144*a4af0ceeSJacob Faibussowitsch cerr = cupmEventDestroy(dci->event);CHKERRCUPM(cerr); 145*a4af0ceeSJacob Faibussowitsch cerr = cupmEventDestroy(dci->begin);CHKERRCUPM(cerr); 146*a4af0ceeSJacob Faibussowitsch cerr = cupmEventDestroy(dci->end);CHKERRCUPM(cerr); 147*a4af0ceeSJacob Faibussowitsch } 148030f984aSJacob Faibussowitsch ierr = PetscFree(dctx->data);CHKERRQ(ierr); 149030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 150030f984aSJacob Faibussowitsch } 151030f984aSJacob Faibussowitsch 152*a4af0ceeSJacob Faibussowitsch template <CUPMDeviceType T> 153*a4af0ceeSJacob Faibussowitsch inline PetscErrorCode CUPMContext<T>::changeStreamType(PetscDeviceContext dctx, PETSC_UNUSED PetscStreamType stype) noexcept 154030f984aSJacob Faibussowitsch { 155*a4af0ceeSJacob Faibussowitsch auto dci = __impls_cast(dctx); 156030f984aSJacob Faibussowitsch 157030f984aSJacob Faibussowitsch PetscFunctionBegin; 158030f984aSJacob Faibussowitsch if (dci->stream) { 159030f984aSJacob Faibussowitsch cupmError_t cerr; 160030f984aSJacob Faibussowitsch 161030f984aSJacob Faibussowitsch cerr = cupmStreamDestroy(dci->stream);CHKERRCUPM(cerr); 162030f984aSJacob Faibussowitsch dci->stream = nullptr; 163030f984aSJacob Faibussowitsch } 164030f984aSJacob Faibussowitsch // set these to null so they aren't usable until setup is called again 165030f984aSJacob Faibussowitsch dci->blas = nullptr; 166030f984aSJacob Faibussowitsch dci->solver = nullptr; 167030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 168030f984aSJacob Faibussowitsch } 169030f984aSJacob Faibussowitsch 170*a4af0ceeSJacob Faibussowitsch template <CUPMDeviceType T> 171030f984aSJacob Faibussowitsch inline PetscErrorCode CUPMContext<T>::setUp(PetscDeviceContext dctx) noexcept 172030f984aSJacob Faibussowitsch { 173030f984aSJacob Faibussowitsch PetscErrorCode ierr; 174030f984aSJacob Faibussowitsch cupmError_t cerr; 175*a4af0ceeSJacob Faibussowitsch auto dci = __impls_cast(dctx); 176030f984aSJacob Faibussowitsch 177030f984aSJacob Faibussowitsch PetscFunctionBegin; 178030f984aSJacob Faibussowitsch if (dci->stream) {cerr = cupmStreamDestroy(dci->stream);CHKERRCUPM(cerr);} 179030f984aSJacob Faibussowitsch switch (dctx->streamType) { 180030f984aSJacob Faibussowitsch case PETSC_STREAM_GLOBAL_BLOCKING: 181030f984aSJacob Faibussowitsch // don't create a stream for global blocking 182030f984aSJacob Faibussowitsch dci->stream = nullptr; 183030f984aSJacob Faibussowitsch break; 184030f984aSJacob Faibussowitsch case PETSC_STREAM_DEFAULT_BLOCKING: 185030f984aSJacob Faibussowitsch cerr = cupmStreamCreate(&dci->stream);CHKERRCUPM(cerr); 186030f984aSJacob Faibussowitsch break; 187030f984aSJacob Faibussowitsch case PETSC_STREAM_GLOBAL_NONBLOCKING: 188030f984aSJacob Faibussowitsch cerr = cupmStreamCreateWithFlags(&dci->stream,cupmStreamNonBlocking);CHKERRCUPM(cerr); 189030f984aSJacob Faibussowitsch break; 190030f984aSJacob Faibussowitsch default: 191*a4af0ceeSJacob Faibussowitsch SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_CORRUPT,"Invalid PetscStreamType %s",PetscStreamTypes[static_cast<int>(dctx->streamType)]); 192030f984aSJacob Faibussowitsch break; 193030f984aSJacob Faibussowitsch } 194*a4af0ceeSJacob Faibussowitsch if (!dci->event) { 195*a4af0ceeSJacob Faibussowitsch cerr = cupmEventCreate(&dci->event);CHKERRCUPM(cerr); 196*a4af0ceeSJacob Faibussowitsch cerr = cupmEventCreate(&dci->begin);CHKERRCUPM(cerr); 197*a4af0ceeSJacob Faibussowitsch cerr = cupmEventCreate(&dci->end);CHKERRCUPM(cerr); 198*a4af0ceeSJacob Faibussowitsch } 199*a4af0ceeSJacob Faibussowitsch #if PetscDefined(USE_DEBUG) 200*a4af0ceeSJacob Faibussowitsch dci->timerInUse = PETSC_FALSE; 201*a4af0ceeSJacob Faibussowitsch #endif 202*a4af0ceeSJacob Faibussowitsch ierr = __initialize(dctx->device->deviceId,dci);CHKERRQ(ierr); 203030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 204030f984aSJacob Faibussowitsch } 205030f984aSJacob Faibussowitsch 206*a4af0ceeSJacob Faibussowitsch template <CUPMDeviceType T> 207030f984aSJacob Faibussowitsch inline PetscErrorCode CUPMContext<T>::query(PetscDeviceContext dctx, PetscBool *idle) noexcept 208030f984aSJacob Faibussowitsch { 209030f984aSJacob Faibussowitsch cupmError_t cerr; 210030f984aSJacob Faibussowitsch 211030f984aSJacob Faibussowitsch PetscFunctionBegin; 212*a4af0ceeSJacob Faibussowitsch cerr = cupmStreamQuery(__impls_cast(dctx)->stream); 213*a4af0ceeSJacob Faibussowitsch if (cerr == cupmSuccess) *idle = PETSC_TRUE; 214*a4af0ceeSJacob Faibussowitsch else { 215030f984aSJacob Faibussowitsch // somethings gone wrong 216*a4af0ceeSJacob Faibussowitsch if (PetscUnlikely(cerr != cupmErrorNotReady)) CHKERRCUPM(cerr); 217*a4af0ceeSJacob Faibussowitsch *idle = PETSC_FALSE; 218030f984aSJacob Faibussowitsch } 219030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 220030f984aSJacob Faibussowitsch } 221030f984aSJacob Faibussowitsch 222*a4af0ceeSJacob Faibussowitsch template <CUPMDeviceType T> 223030f984aSJacob Faibussowitsch inline PetscErrorCode CUPMContext<T>::waitForContext(PetscDeviceContext dctxa, PetscDeviceContext dctxb) noexcept 224030f984aSJacob Faibussowitsch { 225030f984aSJacob Faibussowitsch cupmError_t cerr; 226*a4af0ceeSJacob Faibussowitsch auto dcia = __impls_cast(dctxa),dcib = __impls_cast(dctxb); 227030f984aSJacob Faibussowitsch 228030f984aSJacob Faibussowitsch PetscFunctionBegin; 229030f984aSJacob Faibussowitsch cerr = cupmEventRecord(dcib->event,dcib->stream);CHKERRCUPM(cerr); 230030f984aSJacob Faibussowitsch cerr = cupmStreamWaitEvent(dcia->stream,dcib->event,0);CHKERRCUPM(cerr); 231030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 232030f984aSJacob Faibussowitsch } 233030f984aSJacob Faibussowitsch 234*a4af0ceeSJacob Faibussowitsch template <CUPMDeviceType T> 235030f984aSJacob Faibussowitsch inline PetscErrorCode CUPMContext<T>::synchronize(PetscDeviceContext dctx) noexcept 236030f984aSJacob Faibussowitsch { 237030f984aSJacob Faibussowitsch cupmError_t cerr; 238*a4af0ceeSJacob Faibussowitsch auto dci = __impls_cast(dctx); 239030f984aSJacob Faibussowitsch 240030f984aSJacob Faibussowitsch PetscFunctionBegin; 241030f984aSJacob Faibussowitsch // in case anything was queued on the event 242030f984aSJacob Faibussowitsch cerr = cupmStreamWaitEvent(dci->stream,dci->event,0);CHKERRCUPM(cerr); 243030f984aSJacob Faibussowitsch cerr = cupmStreamSynchronize(dci->stream);CHKERRCUPM(cerr); 244030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 245030f984aSJacob Faibussowitsch } 246030f984aSJacob Faibussowitsch 247*a4af0ceeSJacob Faibussowitsch template <CUPMDeviceType T> 248*a4af0ceeSJacob Faibussowitsch template <typename Handle_T> 249*a4af0ceeSJacob Faibussowitsch inline PetscErrorCode CUPMContext<T>::getHandle(PetscDeviceContext dctx, void *handle) noexcept 250*a4af0ceeSJacob Faibussowitsch { 251*a4af0ceeSJacob Faibussowitsch PetscFunctionBegin; 252*a4af0ceeSJacob Faibussowitsch *static_cast<Handle_T*>(handle) = __impls_cast(dctx)->handle(HandleTag<Handle_T>()); 253*a4af0ceeSJacob Faibussowitsch PetscFunctionReturn(0); 254*a4af0ceeSJacob Faibussowitsch } 255*a4af0ceeSJacob Faibussowitsch 256*a4af0ceeSJacob Faibussowitsch template <CUPMDeviceType T> 257*a4af0ceeSJacob Faibussowitsch inline PetscErrorCode CUPMContext<T>::beginTimer(PetscDeviceContext dctx) noexcept 258*a4af0ceeSJacob Faibussowitsch { 259*a4af0ceeSJacob Faibussowitsch auto dci = __impls_cast(dctx); 260*a4af0ceeSJacob Faibussowitsch cupmError_t cerr; 261*a4af0ceeSJacob Faibussowitsch 262*a4af0ceeSJacob Faibussowitsch PetscFunctionBegin; 263*a4af0ceeSJacob Faibussowitsch #if PetscDefined(USE_DEBUG) 264*a4af0ceeSJacob Faibussowitsch if (PetscUnlikely(dci->timerInUse)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Forgot to call PetscLogGpuTimeEnd()?"); 265*a4af0ceeSJacob Faibussowitsch dci->timerInUse = PETSC_TRUE; 266*a4af0ceeSJacob Faibussowitsch #endif 267*a4af0ceeSJacob Faibussowitsch cerr = cupmEventRecord(dci->begin,dci->stream);CHKERRCUPM(cerr); 268*a4af0ceeSJacob Faibussowitsch PetscFunctionReturn(0); 269*a4af0ceeSJacob Faibussowitsch } 270*a4af0ceeSJacob Faibussowitsch 271*a4af0ceeSJacob Faibussowitsch template <CUPMDeviceType T> 272*a4af0ceeSJacob Faibussowitsch inline PetscErrorCode CUPMContext<T>::endTimer(PetscDeviceContext dctx, PetscLogDouble *elapsed) noexcept 273*a4af0ceeSJacob Faibussowitsch { 274*a4af0ceeSJacob Faibussowitsch cupmError_t cerr; 275*a4af0ceeSJacob Faibussowitsch float gtime; 276*a4af0ceeSJacob Faibussowitsch auto dci = __impls_cast(dctx); 277*a4af0ceeSJacob Faibussowitsch 278*a4af0ceeSJacob Faibussowitsch PetscFunctionBegin; 279*a4af0ceeSJacob Faibussowitsch #if PetscDefined(USE_DEBUG) 280*a4af0ceeSJacob Faibussowitsch if (PetscUnlikely(!dci->timerInUse)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Forgot to call PetscLogGpuTimeBegin()?"); 281*a4af0ceeSJacob Faibussowitsch dci->timerInUse = PETSC_FALSE; 282*a4af0ceeSJacob Faibussowitsch #endif 283*a4af0ceeSJacob Faibussowitsch cerr = cupmEventRecord(dci->end,dci->stream);CHKERRCUPM(cerr); 284*a4af0ceeSJacob Faibussowitsch cerr = cupmEventSynchronize(dci->end);CHKERRCUPM(cerr); 285*a4af0ceeSJacob Faibussowitsch cerr = cupmEventElapsedTime(>ime,dci->begin,dci->end);CHKERRCUPM(cerr); 286*a4af0ceeSJacob Faibussowitsch *elapsed = static_cast<PetscLogDouble>(gtime); 287*a4af0ceeSJacob Faibussowitsch PetscFunctionReturn(0); 288*a4af0ceeSJacob Faibussowitsch } 289*a4af0ceeSJacob Faibussowitsch 290030f984aSJacob Faibussowitsch // initialize the static member variables 291*a4af0ceeSJacob Faibussowitsch template <CUPMDeviceType T> bool CUPMContext<T>::_initialized = false; 292030f984aSJacob Faibussowitsch 293*a4af0ceeSJacob Faibussowitsch template <CUPMDeviceType T> 294*a4af0ceeSJacob Faibussowitsch std::array<typename CUPMContext<T>::cupmBlasHandle_t,PETSC_DEVICE_MAX_DEVICES> CUPMContext<T>::_blashandles = {}; 295030f984aSJacob Faibussowitsch 296*a4af0ceeSJacob Faibussowitsch template <CUPMDeviceType T> 297*a4af0ceeSJacob Faibussowitsch std::array<typename CUPMContext<T>::cupmSolverHandle_t,PETSC_DEVICE_MAX_DEVICES> CUPMContext<T>::_solverhandles = {}; 298030f984aSJacob Faibussowitsch 299*a4af0ceeSJacob Faibussowitsch // shorten this one up a bit (and instantiate the templates) 300*a4af0ceeSJacob Faibussowitsch using CUPMContextCuda = CUPMContext<CUPMDeviceType::CUDA>; 301*a4af0ceeSJacob Faibussowitsch using CUPMContextHip = CUPMContext<CUPMDeviceType::HIP>; 302030f984aSJacob Faibussowitsch 303030f984aSJacob Faibussowitsch } // namespace Petsc 304030f984aSJacob Faibussowitsch 305030f984aSJacob Faibussowitsch // shorthand for what is an EXTREMELY long name 306*a4af0ceeSJacob Faibussowitsch #define PetscDeviceContext_(IMPLS) Petsc::CUPMContext<Petsc::CUPMDeviceType::IMPLS>::PetscDeviceContext_IMPLS 307030f984aSJacob Faibussowitsch 308030f984aSJacob Faibussowitsch // shorthand for casting dctx->data to the appropriate object to access the handles 309*a4af0ceeSJacob Faibussowitsch #define PDC_IMPLS_STATIC_CAST(IMPLS,obj) static_cast<PetscDeviceContext_(IMPLS) *>((obj)->data) 310030f984aSJacob Faibussowitsch 311*a4af0ceeSJacob Faibussowitsch #endif // PETSCDEVICECONTEXTCUDA_HPP 312