117f48955SJacob Faibussowitsch #ifndef PETSCDEVICECONTEXTCUPM_HPP 2030f984aSJacob Faibussowitsch #define PETSCDEVICECONTEXTCUPM_HPP 3030f984aSJacob Faibussowitsch 4a4af0ceeSJacob Faibussowitsch #include <petsc/private/deviceimpl.h> 517f48955SJacob Faibussowitsch #include <petsc/private/cupmblasinterface.hpp> 6*7a101e5eSJacob Faibussowitsch #include <petsc/private/logimpl.h> 7030f984aSJacob Faibussowitsch 8a4af0ceeSJacob Faibussowitsch #include <array> 9a4af0ceeSJacob Faibussowitsch 10a4af0ceeSJacob Faibussowitsch namespace Petsc 11a4af0ceeSJacob Faibussowitsch { 12a4af0ceeSJacob Faibussowitsch 1317f48955SJacob Faibussowitsch namespace Device 1417f48955SJacob Faibussowitsch { 1517f48955SJacob Faibussowitsch 1617f48955SJacob Faibussowitsch namespace CUPM 1717f48955SJacob Faibussowitsch { 1817f48955SJacob Faibussowitsch 1917f48955SJacob Faibussowitsch namespace Impl 2017f48955SJacob Faibussowitsch { 2117f48955SJacob Faibussowitsch 22030f984aSJacob Faibussowitsch // Forward declare 2317f48955SJacob Faibussowitsch template <DeviceType T> class PETSC_VISIBILITY_INTERNAL DeviceContext; 24030f984aSJacob Faibussowitsch 2517f48955SJacob Faibussowitsch template <DeviceType T> 2617f48955SJacob Faibussowitsch class DeviceContext : Impl::BlasInterface<T> 27030f984aSJacob Faibussowitsch { 2817f48955SJacob Faibussowitsch public: 2917f48955SJacob Faibussowitsch PETSC_CUPMBLAS_INHERIT_INTERFACE_TYPEDEFS_USING(cupmBlasInterface_t,T); 3017f48955SJacob Faibussowitsch 3117f48955SJacob Faibussowitsch private: 32*7a101e5eSJacob Faibussowitsch // for tag-based dispatch of handle retrieval 33*7a101e5eSJacob Faibussowitsch template <typename H,std::size_t> struct HandleTag { using type = H; }; 34*7a101e5eSJacob Faibussowitsch using stream_tag = HandleTag<cupmStream_t,0>; 35*7a101e5eSJacob Faibussowitsch using blas_tag = HandleTag<cupmBlasHandle_t,1>; 36*7a101e5eSJacob Faibussowitsch using solver_tag = HandleTag<cupmSolverHandle_t,2>; 37a4af0ceeSJacob Faibussowitsch 38030f984aSJacob Faibussowitsch public: 39030f984aSJacob Faibussowitsch // This is the canonical PETSc "impls" struct that normally resides in a standalone impls 40030f984aSJacob Faibussowitsch // header, but since we are using the power of templates it must be declared part of 41030f984aSJacob Faibussowitsch // this class to have easy access the same typedefs. Technically one can make a 42030f984aSJacob Faibussowitsch // templated struct outside the class but it's more code for the same result. 43030f984aSJacob Faibussowitsch struct PetscDeviceContext_IMPLS 44030f984aSJacob Faibussowitsch { 45030f984aSJacob Faibussowitsch cupmStream_t stream; 46030f984aSJacob Faibussowitsch cupmEvent_t event; 47a4af0ceeSJacob Faibussowitsch cupmEvent_t begin; // timer-only 48a4af0ceeSJacob Faibussowitsch cupmEvent_t end; // timer-only 49a4af0ceeSJacob Faibussowitsch #if PetscDefined(USE_DEBUG) 50a4af0ceeSJacob Faibussowitsch PetscBool timerInUse; 51a4af0ceeSJacob Faibussowitsch #endif 52030f984aSJacob Faibussowitsch cupmBlasHandle_t blas; 53030f984aSJacob Faibussowitsch cupmSolverHandle_t solver; 54a4af0ceeSJacob Faibussowitsch 5517f48955SJacob Faibussowitsch PETSC_NODISCARD auto get(stream_tag) const -> decltype(this->stream) { return this->stream; } 5617f48955SJacob Faibussowitsch PETSC_NODISCARD auto get(blas_tag) const -> decltype(this->blas) { return this->blas; } 5717f48955SJacob Faibussowitsch PETSC_NODISCARD auto get(solver_tag) const -> decltype(this->solver) { return this->solver; } 58030f984aSJacob Faibussowitsch }; 59030f984aSJacob Faibussowitsch 60030f984aSJacob Faibussowitsch private: 6117f48955SJacob Faibussowitsch static bool initialized_; 6217f48955SJacob Faibussowitsch static std::array<cupmBlasHandle_t,PETSC_DEVICE_MAX_DEVICES> blashandles_; 6317f48955SJacob Faibussowitsch static std::array<cupmSolverHandle_t,PETSC_DEVICE_MAX_DEVICES> solverhandles_; 64030f984aSJacob Faibussowitsch 6517f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DECL(constexpr PetscDeviceContext_IMPLS* impls_cast_(PetscDeviceContext ptr)) 66a4af0ceeSJacob Faibussowitsch { 67a4af0ceeSJacob Faibussowitsch return static_cast<PetscDeviceContext_IMPLS*>(ptr->data); 68a4af0ceeSJacob Faibussowitsch } 69a4af0ceeSJacob Faibussowitsch 70*7a101e5eSJacob Faibussowitsch PETSC_CXX_COMPAT_DECL(constexpr PetscLogEvent CUPMBLAS_HANDLE_CREATE()) 71030f984aSJacob Faibussowitsch { 72*7a101e5eSJacob Faibussowitsch return T == DeviceType::CUDA ? CUBLAS_HANDLE_CREATE : HIPBLAS_HANDLE_CREATE; 73*7a101e5eSJacob Faibussowitsch } 74*7a101e5eSJacob Faibussowitsch 75*7a101e5eSJacob Faibussowitsch PETSC_CXX_COMPAT_DECL(constexpr PetscLogEvent CUPMSOLVER_HANDLE_CREATE()) 76*7a101e5eSJacob Faibussowitsch { 77*7a101e5eSJacob Faibussowitsch return T == DeviceType::CUDA ? CUSOLVER_HANDLE_CREATE : HIPSOLVER_HANDLE_CREATE; 78*7a101e5eSJacob Faibussowitsch } 79*7a101e5eSJacob Faibussowitsch 80*7a101e5eSJacob Faibussowitsch // this exists purely to satisfy the compiler so the tag-based dispatch works for the other 81*7a101e5eSJacob Faibussowitsch // handles 82*7a101e5eSJacob Faibussowitsch PETSC_CXX_COMPAT_DECL(PetscErrorCode initialize_handle_(stream_tag,PetscDeviceContext)) { return 0; } 83*7a101e5eSJacob Faibussowitsch 84*7a101e5eSJacob Faibussowitsch PETSC_CXX_COMPAT_DECL(PetscErrorCode create_handle_(cupmBlasHandle_t &handle)) 85*7a101e5eSJacob Faibussowitsch { 86*7a101e5eSJacob Faibussowitsch PetscLogEvent event; 87*7a101e5eSJacob Faibussowitsch 88030f984aSJacob Faibussowitsch PetscFunctionBegin; 89*7a101e5eSJacob Faibussowitsch if (PetscLikely(handle)) PetscFunctionReturn(0); 90*7a101e5eSJacob Faibussowitsch PetscCall(PetscLogPauseCurrentEvent_Internal(&event)); 91*7a101e5eSJacob Faibussowitsch PetscCall(PetscLogEventBegin(CUPMBLAS_HANDLE_CREATE(),0,0,0,0)); 9217f48955SJacob Faibussowitsch for (auto i = 0; i < 3; ++i) { 9317f48955SJacob Faibussowitsch auto cberr = cupmBlasCreate(&handle); 9417f48955SJacob Faibussowitsch if (PetscLikely(cberr == CUPMBLAS_STATUS_SUCCESS)) break; 959566063dSJacob Faibussowitsch if (PetscUnlikely(cberr != CUPMBLAS_STATUS_ALLOC_FAILED) && (cberr != CUPMBLAS_STATUS_NOT_INITIALIZED)) PetscCallCUPMBLAS(cberr); 9617f48955SJacob Faibussowitsch if (i != 2) { 979566063dSJacob Faibussowitsch PetscCall(PetscSleep(3)); 9817f48955SJacob Faibussowitsch continue; 99a4af0ceeSJacob Faibussowitsch } 1005f80ce2aSJacob Faibussowitsch PetscCheck(cberr == CUPMBLAS_STATUS_SUCCESS,PETSC_COMM_SELF,PETSC_ERR_GPU_RESOURCE,"Unable to initialize %s",cupmBlasName()); 101a4af0ceeSJacob Faibussowitsch } 102*7a101e5eSJacob Faibussowitsch PetscCall(PetscLogEventEnd(CUPMBLAS_HANDLE_CREATE(),0,0,0,0)); 103*7a101e5eSJacob Faibussowitsch PetscCall(PetscLogEventResume_Internal(event)); 104030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 105030f984aSJacob Faibussowitsch } 106030f984aSJacob Faibussowitsch 107*7a101e5eSJacob Faibussowitsch PETSC_CXX_COMPAT_DECL(PetscErrorCode initialize_handle_(blas_tag, PetscDeviceContext dctx)) 10817f48955SJacob Faibussowitsch { 109*7a101e5eSJacob Faibussowitsch const auto dci = impls_cast_(dctx); 110*7a101e5eSJacob Faibussowitsch auto& handle = blashandles_[dctx->device->deviceId]; 11117f48955SJacob Faibussowitsch 11217f48955SJacob Faibussowitsch PetscFunctionBegin; 113*7a101e5eSJacob Faibussowitsch PetscCall(create_handle_(handle)); 114*7a101e5eSJacob Faibussowitsch PetscCallCUPMBLAS(cupmBlasSetStream(handle,dci->stream)); 115*7a101e5eSJacob Faibussowitsch dci->blas = handle; 116*7a101e5eSJacob Faibussowitsch PetscFunctionReturn(0); 117*7a101e5eSJacob Faibussowitsch } 118*7a101e5eSJacob Faibussowitsch 119*7a101e5eSJacob Faibussowitsch PETSC_CXX_COMPAT_DECL(PetscErrorCode create_handle_(cupmSolverHandle_t &handle)) 120*7a101e5eSJacob Faibussowitsch { 121*7a101e5eSJacob Faibussowitsch PetscLogEvent event; 122*7a101e5eSJacob Faibussowitsch 123*7a101e5eSJacob Faibussowitsch PetscFunctionBegin; 124*7a101e5eSJacob Faibussowitsch PetscCall(PetscLogPauseCurrentEvent_Internal(&event)); 125*7a101e5eSJacob Faibussowitsch PetscCall(PetscLogEventBegin(CUPMSOLVER_HANDLE_CREATE(),0,0,0,0)); 126*7a101e5eSJacob Faibussowitsch PetscCall(cupmBlasInterface_t::InitializeHandle(handle)); 127*7a101e5eSJacob Faibussowitsch PetscCall(PetscLogEventEnd(CUPMSOLVER_HANDLE_CREATE(),0,0,0,0)); 128*7a101e5eSJacob Faibussowitsch PetscCall(PetscLogEventResume_Internal(event)); 129*7a101e5eSJacob Faibussowitsch PetscFunctionReturn(0); 130*7a101e5eSJacob Faibussowitsch } 131*7a101e5eSJacob Faibussowitsch 132*7a101e5eSJacob Faibussowitsch PETSC_CXX_COMPAT_DECL(PetscErrorCode initialize_handle_(solver_tag, PetscDeviceContext dctx)) 133*7a101e5eSJacob Faibussowitsch { 134*7a101e5eSJacob Faibussowitsch const auto dci = impls_cast_(dctx); 135*7a101e5eSJacob Faibussowitsch auto& handle = solverhandles_[dctx->device->deviceId]; 136*7a101e5eSJacob Faibussowitsch 137*7a101e5eSJacob Faibussowitsch PetscFunctionBegin; 138*7a101e5eSJacob Faibussowitsch PetscCall(create_handle_(handle)); 139*7a101e5eSJacob Faibussowitsch PetscCall(cupmBlasInterface_t::SetHandleStream(handle,dci->stream)); 140*7a101e5eSJacob Faibussowitsch dci->solver = handle; 14117f48955SJacob Faibussowitsch PetscFunctionReturn(0); 14217f48955SJacob Faibussowitsch } 14317f48955SJacob Faibussowitsch 14417f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DECL(PetscErrorCode finalize_()) 14517f48955SJacob Faibussowitsch { 14617f48955SJacob Faibussowitsch PetscFunctionBegin; 14717f48955SJacob Faibussowitsch for (auto&& handle : blashandles_) { 14817f48955SJacob Faibussowitsch if (handle) { 1499566063dSJacob Faibussowitsch PetscCallCUPMBLAS(cupmBlasDestroy(handle)); 15017f48955SJacob Faibussowitsch handle = nullptr; 15117f48955SJacob Faibussowitsch } 15217f48955SJacob Faibussowitsch } 15317f48955SJacob Faibussowitsch for (auto&& handle : solverhandles_) { 15417f48955SJacob Faibussowitsch if (handle) { 1559566063dSJacob Faibussowitsch PetscCall(cupmBlasInterface_t::DestroyHandle(handle)); 15617f48955SJacob Faibussowitsch handle = nullptr; 15717f48955SJacob Faibussowitsch } 15817f48955SJacob Faibussowitsch } 15917f48955SJacob Faibussowitsch initialized_ = false; 16017f48955SJacob Faibussowitsch PetscFunctionReturn(0); 16117f48955SJacob Faibussowitsch } 16217f48955SJacob Faibussowitsch 163030f984aSJacob Faibussowitsch public: 164a4af0ceeSJacob Faibussowitsch const struct _DeviceContextOps ops = { 165a4af0ceeSJacob Faibussowitsch destroy, 166a4af0ceeSJacob Faibussowitsch changeStreamType, 167a4af0ceeSJacob Faibussowitsch setUp, 168a4af0ceeSJacob Faibussowitsch query, 169a4af0ceeSJacob Faibussowitsch waitForContext, 170a4af0ceeSJacob Faibussowitsch synchronize, 17117f48955SJacob Faibussowitsch getHandle<blas_tag>, 17217f48955SJacob Faibussowitsch getHandle<solver_tag>, 17317f48955SJacob Faibussowitsch getHandle<stream_tag>, 174a4af0ceeSJacob Faibussowitsch beginTimer, 17517f48955SJacob Faibussowitsch endTimer, 176a4af0ceeSJacob Faibussowitsch }; 177030f984aSJacob Faibussowitsch 178030f984aSJacob Faibussowitsch // All of these functions MUST be static in order to be callable from C, otherwise they 179030f984aSJacob Faibussowitsch // get the implicit 'this' pointer tacked on 18017f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DECL(PetscErrorCode destroy(PetscDeviceContext)); 18117f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DECL(PetscErrorCode changeStreamType(PetscDeviceContext,PetscStreamType)); 18217f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DECL(PetscErrorCode setUp(PetscDeviceContext)); 18317f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DECL(PetscErrorCode query(PetscDeviceContext,PetscBool*)); 18417f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DECL(PetscErrorCode waitForContext(PetscDeviceContext,PetscDeviceContext)); 18517f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DECL(PetscErrorCode synchronize(PetscDeviceContext)); 186a4af0ceeSJacob Faibussowitsch template <typename Handle_t> 18717f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DECL(PetscErrorCode getHandle(PetscDeviceContext,void*)); 18817f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DECL(PetscErrorCode beginTimer(PetscDeviceContext)); 18917f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DECL(PetscErrorCode endTimer(PetscDeviceContext,PetscLogDouble*)); 190*7a101e5eSJacob Faibussowitsch 191*7a101e5eSJacob Faibussowitsch // not a PetscDeviceContext method, this registers the class 192*7a101e5eSJacob Faibussowitsch PETSC_CXX_COMPAT_DECL(PetscErrorCode initialize()); 193030f984aSJacob Faibussowitsch }; 194030f984aSJacob Faibussowitsch 19517f48955SJacob Faibussowitsch template <DeviceType T> 196*7a101e5eSJacob Faibussowitsch PETSC_CXX_COMPAT_DEFN(PetscErrorCode DeviceContext<T>::initialize()) 197*7a101e5eSJacob Faibussowitsch { 198*7a101e5eSJacob Faibussowitsch PetscFunctionBegin; 199*7a101e5eSJacob Faibussowitsch if (PetscUnlikely(!initialized_)) { 200*7a101e5eSJacob Faibussowitsch initialized_ = true; 201*7a101e5eSJacob Faibussowitsch PetscCall(PetscRegisterFinalize(finalize_)); 202*7a101e5eSJacob Faibussowitsch } 203*7a101e5eSJacob Faibussowitsch PetscFunctionReturn(0); 204*7a101e5eSJacob Faibussowitsch } 205*7a101e5eSJacob Faibussowitsch 206*7a101e5eSJacob Faibussowitsch template <DeviceType T> 20717f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DEFN(PetscErrorCode DeviceContext<T>::destroy(PetscDeviceContext dctx)) 208030f984aSJacob Faibussowitsch { 209*7a101e5eSJacob Faibussowitsch const auto dci = impls_cast_(dctx); 210030f984aSJacob Faibussowitsch 211030f984aSJacob Faibussowitsch PetscFunctionBegin; 2129566063dSJacob Faibussowitsch if (dci->stream) PetscCallCUPM(cupmStreamDestroy(dci->stream)); 2139566063dSJacob Faibussowitsch if (dci->event) PetscCallCUPM(cupmEventDestroy(dci->event)); 2149566063dSJacob Faibussowitsch if (dci->begin) PetscCallCUPM(cupmEventDestroy(dci->begin)); 2159566063dSJacob Faibussowitsch if (dci->end) PetscCallCUPM(cupmEventDestroy(dci->end)); 2169566063dSJacob Faibussowitsch PetscCall(PetscFree(dctx->data)); 217030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 218030f984aSJacob Faibussowitsch } 219030f984aSJacob Faibussowitsch 22017f48955SJacob Faibussowitsch template <DeviceType T> 22117f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DEFN(PetscErrorCode DeviceContext<T>::changeStreamType(PetscDeviceContext dctx, PETSC_UNUSED PetscStreamType stype)) 222030f984aSJacob Faibussowitsch { 223*7a101e5eSJacob Faibussowitsch const auto dci = impls_cast_(dctx); 224030f984aSJacob Faibussowitsch 225030f984aSJacob Faibussowitsch PetscFunctionBegin; 226*7a101e5eSJacob Faibussowitsch if (auto& stream = dci->stream) { 227*7a101e5eSJacob Faibussowitsch PetscCallCUPM(cupmStreamDestroy(stream)); 228*7a101e5eSJacob Faibussowitsch stream = nullptr; 229030f984aSJacob Faibussowitsch } 230030f984aSJacob Faibussowitsch // set these to null so they aren't usable until setup is called again 231030f984aSJacob Faibussowitsch dci->blas = nullptr; 232030f984aSJacob Faibussowitsch dci->solver = nullptr; 233030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 234030f984aSJacob Faibussowitsch } 235030f984aSJacob Faibussowitsch 23617f48955SJacob Faibussowitsch template <DeviceType T> 23717f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DEFN(PetscErrorCode DeviceContext<T>::setUp(PetscDeviceContext dctx)) 238030f984aSJacob Faibussowitsch { 239*7a101e5eSJacob Faibussowitsch const auto dci = impls_cast_(dctx); 240*7a101e5eSJacob Faibussowitsch auto& stream = dci->stream; 241030f984aSJacob Faibussowitsch 242030f984aSJacob Faibussowitsch PetscFunctionBegin; 243*7a101e5eSJacob Faibussowitsch if (stream) { 244*7a101e5eSJacob Faibussowitsch PetscCallCUPM(cupmStreamDestroy(stream)); 245*7a101e5eSJacob Faibussowitsch stream = nullptr; 24617f48955SJacob Faibussowitsch } 247*7a101e5eSJacob Faibussowitsch switch (const auto stype = dctx->streamType) { 248030f984aSJacob Faibussowitsch case PETSC_STREAM_GLOBAL_BLOCKING: 249030f984aSJacob Faibussowitsch // don't create a stream for global blocking 250030f984aSJacob Faibussowitsch break; 251030f984aSJacob Faibussowitsch case PETSC_STREAM_DEFAULT_BLOCKING: 252*7a101e5eSJacob Faibussowitsch PetscCallCUPM(cupmStreamCreate(&stream)); 253030f984aSJacob Faibussowitsch break; 254030f984aSJacob Faibussowitsch case PETSC_STREAM_GLOBAL_NONBLOCKING: 255*7a101e5eSJacob Faibussowitsch PetscCallCUPM(cupmStreamCreateWithFlags(&stream,cupmStreamNonBlocking)); 256030f984aSJacob Faibussowitsch break; 257030f984aSJacob Faibussowitsch default: 258*7a101e5eSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_CORRUPT,"Invalid PetscStreamType %s",PetscStreamTypes[util::integral_value(stype)]); 259030f984aSJacob Faibussowitsch break; 260030f984aSJacob Faibussowitsch } 2619566063dSJacob Faibussowitsch if (!dci->event) PetscCallCUPM(cupmEventCreate(&dci->event)); 262a4af0ceeSJacob Faibussowitsch #if PetscDefined(USE_DEBUG) 263a4af0ceeSJacob Faibussowitsch dci->timerInUse = PETSC_FALSE; 264a4af0ceeSJacob Faibussowitsch #endif 265030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 266030f984aSJacob Faibussowitsch } 267030f984aSJacob Faibussowitsch 26817f48955SJacob Faibussowitsch template <DeviceType T> 26917f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DEFN(PetscErrorCode DeviceContext<T>::query(PetscDeviceContext dctx, PetscBool *idle)) 270030f984aSJacob Faibussowitsch { 271030f984aSJacob Faibussowitsch cupmError_t cerr; 272030f984aSJacob Faibussowitsch 273030f984aSJacob Faibussowitsch PetscFunctionBegin; 27417f48955SJacob Faibussowitsch cerr = cupmStreamQuery(impls_cast_(dctx)->stream); 275a4af0ceeSJacob Faibussowitsch if (cerr == cupmSuccess) *idle = PETSC_TRUE; 276a4af0ceeSJacob Faibussowitsch else { 277030f984aSJacob Faibussowitsch // somethings gone wrong 2789566063dSJacob Faibussowitsch if (PetscUnlikely(cerr != cupmErrorNotReady)) PetscCallCUPM(cerr); 279a4af0ceeSJacob Faibussowitsch *idle = PETSC_FALSE; 280030f984aSJacob Faibussowitsch } 281030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 282030f984aSJacob Faibussowitsch } 283030f984aSJacob Faibussowitsch 28417f48955SJacob Faibussowitsch template <DeviceType T> 28517f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DEFN(PetscErrorCode DeviceContext<T>::waitForContext(PetscDeviceContext dctxa, PetscDeviceContext dctxb)) 286030f984aSJacob Faibussowitsch { 28717f48955SJacob Faibussowitsch auto dcib = impls_cast_(dctxb); 288030f984aSJacob Faibussowitsch 289030f984aSJacob Faibussowitsch PetscFunctionBegin; 2909566063dSJacob Faibussowitsch PetscCallCUPM(cupmEventRecord(dcib->event,dcib->stream)); 2919566063dSJacob Faibussowitsch PetscCallCUPM(cupmStreamWaitEvent(impls_cast_(dctxa)->stream,dcib->event,0)); 292030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 293030f984aSJacob Faibussowitsch } 294030f984aSJacob Faibussowitsch 29517f48955SJacob Faibussowitsch template <DeviceType T> 29617f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DEFN(PetscErrorCode DeviceContext<T>::synchronize(PetscDeviceContext dctx)) 297030f984aSJacob Faibussowitsch { 29817f48955SJacob Faibussowitsch auto dci = impls_cast_(dctx); 299030f984aSJacob Faibussowitsch 300030f984aSJacob Faibussowitsch PetscFunctionBegin; 301030f984aSJacob Faibussowitsch // in case anything was queued on the event 3029566063dSJacob Faibussowitsch PetscCallCUPM(cupmStreamWaitEvent(dci->stream,dci->event,0)); 3039566063dSJacob Faibussowitsch PetscCallCUPM(cupmStreamSynchronize(dci->stream)); 304030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 305030f984aSJacob Faibussowitsch } 306030f984aSJacob Faibussowitsch 30717f48955SJacob Faibussowitsch template <DeviceType T> 30817f48955SJacob Faibussowitsch template <typename handle_t> 30917f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DEFN(PetscErrorCode DeviceContext<T>::getHandle(PetscDeviceContext dctx, void *handle)) 310a4af0ceeSJacob Faibussowitsch { 311a4af0ceeSJacob Faibussowitsch PetscFunctionBegin; 312*7a101e5eSJacob Faibussowitsch PetscCall(initialize_handle_(handle_t{},dctx)); 313*7a101e5eSJacob Faibussowitsch *static_cast<typename handle_t::type*>(handle) = impls_cast_(dctx)->get(handle_t{}); 314a4af0ceeSJacob Faibussowitsch PetscFunctionReturn(0); 315a4af0ceeSJacob Faibussowitsch } 316a4af0ceeSJacob Faibussowitsch 31717f48955SJacob Faibussowitsch template <DeviceType T> 31817f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DEFN(PetscErrorCode DeviceContext<T>::beginTimer(PetscDeviceContext dctx)) 319a4af0ceeSJacob Faibussowitsch { 32017f48955SJacob Faibussowitsch auto dci = impls_cast_(dctx); 321a4af0ceeSJacob Faibussowitsch 322a4af0ceeSJacob Faibussowitsch PetscFunctionBegin; 323a4af0ceeSJacob Faibussowitsch #if PetscDefined(USE_DEBUG) 3245f80ce2aSJacob Faibussowitsch PetscCheck(!dci->timerInUse,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Forgot to call PetscLogGpuTimeEnd()?"); 325a4af0ceeSJacob Faibussowitsch dci->timerInUse = PETSC_TRUE; 326a4af0ceeSJacob Faibussowitsch #endif 32717f48955SJacob Faibussowitsch if (!dci->begin) { 3289566063dSJacob Faibussowitsch PetscCallCUPM(cupmEventCreate(&dci->begin)); 3299566063dSJacob Faibussowitsch PetscCallCUPM(cupmEventCreate(&dci->end)); 33017f48955SJacob Faibussowitsch } 3319566063dSJacob Faibussowitsch PetscCallCUPM(cupmEventRecord(dci->begin,dci->stream)); 332a4af0ceeSJacob Faibussowitsch PetscFunctionReturn(0); 333a4af0ceeSJacob Faibussowitsch } 334a4af0ceeSJacob Faibussowitsch 33517f48955SJacob Faibussowitsch template <DeviceType T> 33617f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DEFN(PetscErrorCode DeviceContext<T>::endTimer(PetscDeviceContext dctx, PetscLogDouble *elapsed)) 337a4af0ceeSJacob Faibussowitsch { 338a4af0ceeSJacob Faibussowitsch float gtime; 33917f48955SJacob Faibussowitsch auto dci = impls_cast_(dctx); 340a4af0ceeSJacob Faibussowitsch 341a4af0ceeSJacob Faibussowitsch PetscFunctionBegin; 342a4af0ceeSJacob Faibussowitsch #if PetscDefined(USE_DEBUG) 3435f80ce2aSJacob Faibussowitsch PetscCheck(dci->timerInUse,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Forgot to call PetscLogGpuTimeBegin()?"); 344a4af0ceeSJacob Faibussowitsch dci->timerInUse = PETSC_FALSE; 345a4af0ceeSJacob Faibussowitsch #endif 3469566063dSJacob Faibussowitsch PetscCallCUPM(cupmEventRecord(dci->end,dci->stream)); 3479566063dSJacob Faibussowitsch PetscCallCUPM(cupmEventSynchronize(dci->end)); 3489566063dSJacob Faibussowitsch PetscCallCUPM(cupmEventElapsedTime(>ime,dci->begin,dci->end)); 34917f48955SJacob Faibussowitsch *elapsed = static_cast<util::remove_pointer_t<decltype(elapsed)>>(gtime); 350a4af0ceeSJacob Faibussowitsch PetscFunctionReturn(0); 351a4af0ceeSJacob Faibussowitsch } 352a4af0ceeSJacob Faibussowitsch 353030f984aSJacob Faibussowitsch // initialize the static member variables 35417f48955SJacob Faibussowitsch template <DeviceType T> bool DeviceContext<T>::initialized_ = false; 355030f984aSJacob Faibussowitsch 35617f48955SJacob Faibussowitsch template <DeviceType T> 35717f48955SJacob Faibussowitsch std::array<typename DeviceContext<T>::cupmBlasHandle_t,PETSC_DEVICE_MAX_DEVICES> DeviceContext<T>::blashandles_ = {}; 358030f984aSJacob Faibussowitsch 35917f48955SJacob Faibussowitsch template <DeviceType T> 36017f48955SJacob Faibussowitsch std::array<typename DeviceContext<T>::cupmSolverHandle_t,PETSC_DEVICE_MAX_DEVICES> DeviceContext<T>::solverhandles_ = {}; 36117f48955SJacob Faibussowitsch 36217f48955SJacob Faibussowitsch } // namespace Impl 363030f984aSJacob Faibussowitsch 364a4af0ceeSJacob Faibussowitsch // shorten this one up a bit (and instantiate the templates) 36517f48955SJacob Faibussowitsch using CUPMContextCuda = Impl::DeviceContext<DeviceType::CUDA>; 36617f48955SJacob Faibussowitsch using CUPMContextHip = Impl::DeviceContext<DeviceType::HIP>; 367030f984aSJacob Faibussowitsch 368030f984aSJacob Faibussowitsch // shorthand for what is an EXTREMELY long name 36917f48955SJacob Faibussowitsch #define PetscDeviceContext_(IMPLS) Petsc::Device::CUPM::Impl::DeviceContext<Petsc::Device::CUPM::DeviceType::IMPLS>::PetscDeviceContext_IMPLS 370030f984aSJacob Faibussowitsch 37117f48955SJacob Faibussowitsch } // namespace CUPM 37217f48955SJacob Faibussowitsch 37317f48955SJacob Faibussowitsch } // namespace Device 37417f48955SJacob Faibussowitsch 37517f48955SJacob Faibussowitsch } // namespace Petsc 376030f984aSJacob Faibussowitsch 377a4af0ceeSJacob Faibussowitsch #endif // PETSCDEVICECONTEXTCUDA_HPP 378