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> 67a101e5eSJacob Faibussowitsch #include <petsc/private/logimpl.h> 7030f984aSJacob Faibussowitsch 8a4af0ceeSJacob Faibussowitsch #include <array> 9a4af0ceeSJacob Faibussowitsch 10*9371c9d4SSatish Balay namespace Petsc { 11a4af0ceeSJacob Faibussowitsch 12*9371c9d4SSatish Balay namespace Device { 1317f48955SJacob Faibussowitsch 14*9371c9d4SSatish Balay namespace CUPM { 1517f48955SJacob Faibussowitsch 16*9371c9d4SSatish Balay namespace Impl { 1717f48955SJacob Faibussowitsch 18030f984aSJacob Faibussowitsch // Forward declare 19*9371c9d4SSatish Balay template <DeviceType T> 20*9371c9d4SSatish Balay class PETSC_VISIBILITY_INTERNAL DeviceContext; 21030f984aSJacob Faibussowitsch 2217f48955SJacob Faibussowitsch template <DeviceType T> 23*9371c9d4SSatish Balay class DeviceContext : Impl::BlasInterface<T> { 2417f48955SJacob Faibussowitsch public: 2517f48955SJacob Faibussowitsch PETSC_CUPMBLAS_INHERIT_INTERFACE_TYPEDEFS_USING(cupmBlasInterface_t, T); 2617f48955SJacob Faibussowitsch 2717f48955SJacob Faibussowitsch private: 287a101e5eSJacob Faibussowitsch // for tag-based dispatch of handle retrieval 29*9371c9d4SSatish Balay template <typename H, std::size_t> 30*9371c9d4SSatish Balay struct HandleTag { 31*9371c9d4SSatish Balay using type = H; 32*9371c9d4SSatish Balay }; 337a101e5eSJacob Faibussowitsch using stream_tag = HandleTag<cupmStream_t, 0>; 347a101e5eSJacob Faibussowitsch using blas_tag = HandleTag<cupmBlasHandle_t, 1>; 357a101e5eSJacob Faibussowitsch using solver_tag = HandleTag<cupmSolverHandle_t, 2>; 36a4af0ceeSJacob Faibussowitsch 37030f984aSJacob Faibussowitsch public: 38030f984aSJacob Faibussowitsch // This is the canonical PETSc "impls" struct that normally resides in a standalone impls 39030f984aSJacob Faibussowitsch // header, but since we are using the power of templates it must be declared part of 40030f984aSJacob Faibussowitsch // this class to have easy access the same typedefs. Technically one can make a 41030f984aSJacob Faibussowitsch // templated struct outside the class but it's more code for the same result. 42*9371c9d4SSatish Balay struct PetscDeviceContext_IMPLS { 43030f984aSJacob Faibussowitsch cupmStream_t stream; 44030f984aSJacob Faibussowitsch cupmEvent_t event; 45a4af0ceeSJacob Faibussowitsch cupmEvent_t begin; // timer-only 46a4af0ceeSJacob Faibussowitsch cupmEvent_t end; // timer-only 47a4af0ceeSJacob Faibussowitsch #if PetscDefined(USE_DEBUG) 48a4af0ceeSJacob Faibussowitsch PetscBool timerInUse; 49a4af0ceeSJacob Faibussowitsch #endif 50030f984aSJacob Faibussowitsch cupmBlasHandle_t blas; 51030f984aSJacob Faibussowitsch cupmSolverHandle_t solver; 52a4af0ceeSJacob Faibussowitsch 53*9371c9d4SSatish Balay PETSC_NODISCARD auto get(stream_tag) const -> decltype(this->stream) { 54*9371c9d4SSatish Balay return this->stream; 55*9371c9d4SSatish Balay } 56*9371c9d4SSatish Balay PETSC_NODISCARD auto get(blas_tag) const -> decltype(this->blas) { 57*9371c9d4SSatish Balay return this->blas; 58*9371c9d4SSatish Balay } 59*9371c9d4SSatish Balay PETSC_NODISCARD auto get(solver_tag) const -> decltype(this->solver) { 60*9371c9d4SSatish Balay return this->solver; 61*9371c9d4SSatish Balay } 62030f984aSJacob Faibussowitsch }; 63030f984aSJacob Faibussowitsch 64030f984aSJacob Faibussowitsch private: 6517f48955SJacob Faibussowitsch static bool initialized_; 6617f48955SJacob Faibussowitsch static std::array<cupmBlasHandle_t, PETSC_DEVICE_MAX_DEVICES> blashandles_; 6717f48955SJacob Faibussowitsch static std::array<cupmSolverHandle_t, PETSC_DEVICE_MAX_DEVICES> solverhandles_; 68030f984aSJacob Faibussowitsch 69*9371c9d4SSatish Balay PETSC_CXX_COMPAT_DECL(constexpr PetscDeviceContext_IMPLS *impls_cast_(PetscDeviceContext ptr)) { 70a4af0ceeSJacob Faibussowitsch return static_cast<PetscDeviceContext_IMPLS *>(ptr->data); 71a4af0ceeSJacob Faibussowitsch } 72a4af0ceeSJacob Faibussowitsch 73*9371c9d4SSatish Balay PETSC_CXX_COMPAT_DECL(constexpr PetscLogEvent CUPMBLAS_HANDLE_CREATE()) { 747a101e5eSJacob Faibussowitsch return T == DeviceType::CUDA ? CUBLAS_HANDLE_CREATE : HIPBLAS_HANDLE_CREATE; 757a101e5eSJacob Faibussowitsch } 767a101e5eSJacob Faibussowitsch 77*9371c9d4SSatish Balay PETSC_CXX_COMPAT_DECL(constexpr PetscLogEvent CUPMSOLVER_HANDLE_CREATE()) { 787a101e5eSJacob Faibussowitsch return T == DeviceType::CUDA ? CUSOLVER_HANDLE_CREATE : HIPSOLVER_HANDLE_CREATE; 797a101e5eSJacob Faibussowitsch } 807a101e5eSJacob Faibussowitsch 817a101e5eSJacob Faibussowitsch // this exists purely to satisfy the compiler so the tag-based dispatch works for the other 827a101e5eSJacob Faibussowitsch // handles 83*9371c9d4SSatish Balay PETSC_CXX_COMPAT_DECL(PetscErrorCode initialize_handle_(stream_tag, PetscDeviceContext)) { 84*9371c9d4SSatish Balay return 0; 85*9371c9d4SSatish Balay } 867a101e5eSJacob Faibussowitsch 87*9371c9d4SSatish Balay PETSC_CXX_COMPAT_DECL(PetscErrorCode create_handle_(cupmBlasHandle_t &handle)) { 887a101e5eSJacob Faibussowitsch PetscLogEvent event; 897a101e5eSJacob Faibussowitsch 90030f984aSJacob Faibussowitsch PetscFunctionBegin; 917a101e5eSJacob Faibussowitsch if (PetscLikely(handle)) PetscFunctionReturn(0); 927a101e5eSJacob Faibussowitsch PetscCall(PetscLogPauseCurrentEvent_Internal(&event)); 937a101e5eSJacob Faibussowitsch PetscCall(PetscLogEventBegin(CUPMBLAS_HANDLE_CREATE(), 0, 0, 0, 0)); 9417f48955SJacob Faibussowitsch for (auto i = 0; i < 3; ++i) { 9517f48955SJacob Faibussowitsch auto cberr = cupmBlasCreate(&handle); 9617f48955SJacob Faibussowitsch if (PetscLikely(cberr == CUPMBLAS_STATUS_SUCCESS)) break; 979566063dSJacob Faibussowitsch if (PetscUnlikely(cberr != CUPMBLAS_STATUS_ALLOC_FAILED) && (cberr != CUPMBLAS_STATUS_NOT_INITIALIZED)) PetscCallCUPMBLAS(cberr); 9817f48955SJacob Faibussowitsch if (i != 2) { 999566063dSJacob Faibussowitsch PetscCall(PetscSleep(3)); 10017f48955SJacob Faibussowitsch continue; 101a4af0ceeSJacob Faibussowitsch } 1025f80ce2aSJacob Faibussowitsch PetscCheck(cberr == CUPMBLAS_STATUS_SUCCESS, PETSC_COMM_SELF, PETSC_ERR_GPU_RESOURCE, "Unable to initialize %s", cupmBlasName()); 103a4af0ceeSJacob Faibussowitsch } 1047a101e5eSJacob Faibussowitsch PetscCall(PetscLogEventEnd(CUPMBLAS_HANDLE_CREATE(), 0, 0, 0, 0)); 1057a101e5eSJacob Faibussowitsch PetscCall(PetscLogEventResume_Internal(event)); 106030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 107030f984aSJacob Faibussowitsch } 108030f984aSJacob Faibussowitsch 109*9371c9d4SSatish Balay PETSC_CXX_COMPAT_DECL(PetscErrorCode initialize_handle_(blas_tag, PetscDeviceContext dctx)) { 1107a101e5eSJacob Faibussowitsch const auto dci = impls_cast_(dctx); 1117a101e5eSJacob Faibussowitsch auto &handle = blashandles_[dctx->device->deviceId]; 11217f48955SJacob Faibussowitsch 11317f48955SJacob Faibussowitsch PetscFunctionBegin; 1147a101e5eSJacob Faibussowitsch PetscCall(create_handle_(handle)); 1157a101e5eSJacob Faibussowitsch PetscCallCUPMBLAS(cupmBlasSetStream(handle, dci->stream)); 1167a101e5eSJacob Faibussowitsch dci->blas = handle; 1177a101e5eSJacob Faibussowitsch PetscFunctionReturn(0); 1187a101e5eSJacob Faibussowitsch } 1197a101e5eSJacob Faibussowitsch 120*9371c9d4SSatish Balay PETSC_CXX_COMPAT_DECL(PetscErrorCode create_handle_(cupmSolverHandle_t &handle)) { 1217a101e5eSJacob Faibussowitsch PetscLogEvent event; 1227a101e5eSJacob Faibussowitsch 1237a101e5eSJacob Faibussowitsch PetscFunctionBegin; 1247a101e5eSJacob Faibussowitsch PetscCall(PetscLogPauseCurrentEvent_Internal(&event)); 1257a101e5eSJacob Faibussowitsch PetscCall(PetscLogEventBegin(CUPMSOLVER_HANDLE_CREATE(), 0, 0, 0, 0)); 1267a101e5eSJacob Faibussowitsch PetscCall(cupmBlasInterface_t::InitializeHandle(handle)); 1277a101e5eSJacob Faibussowitsch PetscCall(PetscLogEventEnd(CUPMSOLVER_HANDLE_CREATE(), 0, 0, 0, 0)); 1287a101e5eSJacob Faibussowitsch PetscCall(PetscLogEventResume_Internal(event)); 1297a101e5eSJacob Faibussowitsch PetscFunctionReturn(0); 1307a101e5eSJacob Faibussowitsch } 1317a101e5eSJacob Faibussowitsch 132*9371c9d4SSatish Balay PETSC_CXX_COMPAT_DECL(PetscErrorCode initialize_handle_(solver_tag, PetscDeviceContext dctx)) { 1337a101e5eSJacob Faibussowitsch const auto dci = impls_cast_(dctx); 1347a101e5eSJacob Faibussowitsch auto &handle = solverhandles_[dctx->device->deviceId]; 1357a101e5eSJacob Faibussowitsch 1367a101e5eSJacob Faibussowitsch PetscFunctionBegin; 1377a101e5eSJacob Faibussowitsch PetscCall(create_handle_(handle)); 1387a101e5eSJacob Faibussowitsch PetscCall(cupmBlasInterface_t::SetHandleStream(handle, dci->stream)); 1397a101e5eSJacob Faibussowitsch dci->solver = handle; 14017f48955SJacob Faibussowitsch PetscFunctionReturn(0); 14117f48955SJacob Faibussowitsch } 14217f48955SJacob Faibussowitsch 143*9371c9d4SSatish Balay PETSC_CXX_COMPAT_DECL(PetscErrorCode finalize_()) { 14417f48955SJacob Faibussowitsch PetscFunctionBegin; 14517f48955SJacob Faibussowitsch for (auto &&handle : blashandles_) { 14617f48955SJacob Faibussowitsch if (handle) { 1479566063dSJacob Faibussowitsch PetscCallCUPMBLAS(cupmBlasDestroy(handle)); 14817f48955SJacob Faibussowitsch handle = nullptr; 14917f48955SJacob Faibussowitsch } 15017f48955SJacob Faibussowitsch } 15117f48955SJacob Faibussowitsch for (auto &&handle : solverhandles_) { 15217f48955SJacob Faibussowitsch if (handle) { 1539566063dSJacob Faibussowitsch PetscCall(cupmBlasInterface_t::DestroyHandle(handle)); 15417f48955SJacob Faibussowitsch handle = nullptr; 15517f48955SJacob Faibussowitsch } 15617f48955SJacob Faibussowitsch } 15717f48955SJacob Faibussowitsch initialized_ = false; 15817f48955SJacob Faibussowitsch PetscFunctionReturn(0); 15917f48955SJacob Faibussowitsch } 16017f48955SJacob Faibussowitsch 161030f984aSJacob Faibussowitsch public: 162a4af0ceeSJacob Faibussowitsch const struct _DeviceContextOps ops = { 163*9371c9d4SSatish Balay destroy, changeStreamType, setUp, query, waitForContext, synchronize, getHandle<blas_tag>, getHandle<solver_tag>, getHandle<stream_tag>, beginTimer, endTimer, 164a4af0ceeSJacob Faibussowitsch }; 165030f984aSJacob Faibussowitsch 166030f984aSJacob Faibussowitsch // All of these functions MUST be static in order to be callable from C, otherwise they 167030f984aSJacob Faibussowitsch // get the implicit 'this' pointer tacked on 16817f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DECL(PetscErrorCode destroy(PetscDeviceContext)); 16917f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DECL(PetscErrorCode changeStreamType(PetscDeviceContext, PetscStreamType)); 17017f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DECL(PetscErrorCode setUp(PetscDeviceContext)); 17117f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DECL(PetscErrorCode query(PetscDeviceContext, PetscBool *)); 17217f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DECL(PetscErrorCode waitForContext(PetscDeviceContext, PetscDeviceContext)); 17317f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DECL(PetscErrorCode synchronize(PetscDeviceContext)); 174a4af0ceeSJacob Faibussowitsch template <typename Handle_t> 17517f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DECL(PetscErrorCode getHandle(PetscDeviceContext, void *)); 17617f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DECL(PetscErrorCode beginTimer(PetscDeviceContext)); 17717f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DECL(PetscErrorCode endTimer(PetscDeviceContext, PetscLogDouble *)); 1787a101e5eSJacob Faibussowitsch 1797a101e5eSJacob Faibussowitsch // not a PetscDeviceContext method, this registers the class 1807a101e5eSJacob Faibussowitsch PETSC_CXX_COMPAT_DECL(PetscErrorCode initialize()); 181030f984aSJacob Faibussowitsch }; 182030f984aSJacob Faibussowitsch 18317f48955SJacob Faibussowitsch template <DeviceType T> 184*9371c9d4SSatish Balay PETSC_CXX_COMPAT_DEFN(PetscErrorCode DeviceContext<T>::initialize()) { 1857a101e5eSJacob Faibussowitsch PetscFunctionBegin; 1867a101e5eSJacob Faibussowitsch if (PetscUnlikely(!initialized_)) { 1877a101e5eSJacob Faibussowitsch initialized_ = true; 1887a101e5eSJacob Faibussowitsch PetscCall(PetscRegisterFinalize(finalize_)); 1897a101e5eSJacob Faibussowitsch } 1907a101e5eSJacob Faibussowitsch PetscFunctionReturn(0); 1917a101e5eSJacob Faibussowitsch } 1927a101e5eSJacob Faibussowitsch 1937a101e5eSJacob Faibussowitsch template <DeviceType T> 194*9371c9d4SSatish Balay PETSC_CXX_COMPAT_DEFN(PetscErrorCode DeviceContext<T>::destroy(PetscDeviceContext dctx)) { 1957a101e5eSJacob Faibussowitsch const auto dci = impls_cast_(dctx); 196030f984aSJacob Faibussowitsch 197030f984aSJacob Faibussowitsch PetscFunctionBegin; 1989566063dSJacob Faibussowitsch if (dci->stream) PetscCallCUPM(cupmStreamDestroy(dci->stream)); 1999566063dSJacob Faibussowitsch if (dci->event) PetscCallCUPM(cupmEventDestroy(dci->event)); 2009566063dSJacob Faibussowitsch if (dci->begin) PetscCallCUPM(cupmEventDestroy(dci->begin)); 2019566063dSJacob Faibussowitsch if (dci->end) PetscCallCUPM(cupmEventDestroy(dci->end)); 2029566063dSJacob Faibussowitsch PetscCall(PetscFree(dctx->data)); 203030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 204030f984aSJacob Faibussowitsch } 205030f984aSJacob Faibussowitsch 20617f48955SJacob Faibussowitsch template <DeviceType T> 207*9371c9d4SSatish Balay PETSC_CXX_COMPAT_DEFN(PetscErrorCode DeviceContext<T>::changeStreamType(PetscDeviceContext dctx, PETSC_UNUSED PetscStreamType stype)) { 2087a101e5eSJacob Faibussowitsch const auto dci = impls_cast_(dctx); 209030f984aSJacob Faibussowitsch 210030f984aSJacob Faibussowitsch PetscFunctionBegin; 2117a101e5eSJacob Faibussowitsch if (auto &stream = dci->stream) { 2127a101e5eSJacob Faibussowitsch PetscCallCUPM(cupmStreamDestroy(stream)); 2137a101e5eSJacob Faibussowitsch stream = nullptr; 214030f984aSJacob Faibussowitsch } 215030f984aSJacob Faibussowitsch // set these to null so they aren't usable until setup is called again 216030f984aSJacob Faibussowitsch dci->blas = nullptr; 217030f984aSJacob Faibussowitsch dci->solver = nullptr; 218030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 219030f984aSJacob Faibussowitsch } 220030f984aSJacob Faibussowitsch 22117f48955SJacob Faibussowitsch template <DeviceType T> 222*9371c9d4SSatish Balay PETSC_CXX_COMPAT_DEFN(PetscErrorCode DeviceContext<T>::setUp(PetscDeviceContext dctx)) { 2237a101e5eSJacob Faibussowitsch const auto dci = impls_cast_(dctx); 2247a101e5eSJacob Faibussowitsch auto &stream = dci->stream; 225030f984aSJacob Faibussowitsch 226030f984aSJacob Faibussowitsch PetscFunctionBegin; 2277a101e5eSJacob Faibussowitsch if (stream) { 2287a101e5eSJacob Faibussowitsch PetscCallCUPM(cupmStreamDestroy(stream)); 2297a101e5eSJacob Faibussowitsch stream = nullptr; 23017f48955SJacob Faibussowitsch } 2317a101e5eSJacob Faibussowitsch switch (const auto stype = dctx->streamType) { 232030f984aSJacob Faibussowitsch case PETSC_STREAM_GLOBAL_BLOCKING: 233030f984aSJacob Faibussowitsch // don't create a stream for global blocking 234030f984aSJacob Faibussowitsch break; 235*9371c9d4SSatish Balay case PETSC_STREAM_DEFAULT_BLOCKING: PetscCallCUPM(cupmStreamCreate(&stream)); break; 236*9371c9d4SSatish Balay case PETSC_STREAM_GLOBAL_NONBLOCKING: PetscCallCUPM(cupmStreamCreateWithFlags(&stream, cupmStreamNonBlocking)); break; 237*9371c9d4SSatish Balay default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_CORRUPT, "Invalid PetscStreamType %s", PetscStreamTypes[util::integral_value(stype)]); break; 238030f984aSJacob Faibussowitsch } 2399566063dSJacob Faibussowitsch if (!dci->event) PetscCallCUPM(cupmEventCreate(&dci->event)); 240a4af0ceeSJacob Faibussowitsch #if PetscDefined(USE_DEBUG) 241a4af0ceeSJacob Faibussowitsch dci->timerInUse = PETSC_FALSE; 242a4af0ceeSJacob Faibussowitsch #endif 243030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 244030f984aSJacob Faibussowitsch } 245030f984aSJacob Faibussowitsch 24617f48955SJacob Faibussowitsch template <DeviceType T> 247*9371c9d4SSatish Balay PETSC_CXX_COMPAT_DEFN(PetscErrorCode DeviceContext<T>::query(PetscDeviceContext dctx, PetscBool *idle)) { 248030f984aSJacob Faibussowitsch cupmError_t cerr; 249030f984aSJacob Faibussowitsch 250030f984aSJacob Faibussowitsch PetscFunctionBegin; 25117f48955SJacob Faibussowitsch cerr = cupmStreamQuery(impls_cast_(dctx)->stream); 252a4af0ceeSJacob Faibussowitsch if (cerr == cupmSuccess) *idle = PETSC_TRUE; 253a4af0ceeSJacob Faibussowitsch else { 254030f984aSJacob Faibussowitsch // somethings gone wrong 2559566063dSJacob Faibussowitsch if (PetscUnlikely(cerr != cupmErrorNotReady)) PetscCallCUPM(cerr); 256a4af0ceeSJacob Faibussowitsch *idle = PETSC_FALSE; 257030f984aSJacob Faibussowitsch } 258030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 259030f984aSJacob Faibussowitsch } 260030f984aSJacob Faibussowitsch 26117f48955SJacob Faibussowitsch template <DeviceType T> 262*9371c9d4SSatish Balay PETSC_CXX_COMPAT_DEFN(PetscErrorCode DeviceContext<T>::waitForContext(PetscDeviceContext dctxa, PetscDeviceContext dctxb)) { 26317f48955SJacob Faibussowitsch auto dcib = impls_cast_(dctxb); 264030f984aSJacob Faibussowitsch 265030f984aSJacob Faibussowitsch PetscFunctionBegin; 2669566063dSJacob Faibussowitsch PetscCallCUPM(cupmEventRecord(dcib->event, dcib->stream)); 2679566063dSJacob Faibussowitsch PetscCallCUPM(cupmStreamWaitEvent(impls_cast_(dctxa)->stream, dcib->event, 0)); 268030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 269030f984aSJacob Faibussowitsch } 270030f984aSJacob Faibussowitsch 27117f48955SJacob Faibussowitsch template <DeviceType T> 272*9371c9d4SSatish Balay PETSC_CXX_COMPAT_DEFN(PetscErrorCode DeviceContext<T>::synchronize(PetscDeviceContext dctx)) { 27317f48955SJacob Faibussowitsch auto dci = impls_cast_(dctx); 274030f984aSJacob Faibussowitsch 275030f984aSJacob Faibussowitsch PetscFunctionBegin; 276030f984aSJacob Faibussowitsch // in case anything was queued on the event 2779566063dSJacob Faibussowitsch PetscCallCUPM(cupmStreamWaitEvent(dci->stream, dci->event, 0)); 2789566063dSJacob Faibussowitsch PetscCallCUPM(cupmStreamSynchronize(dci->stream)); 279030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 280030f984aSJacob Faibussowitsch } 281030f984aSJacob Faibussowitsch 28217f48955SJacob Faibussowitsch template <DeviceType T> 28317f48955SJacob Faibussowitsch template <typename handle_t> 284*9371c9d4SSatish Balay PETSC_CXX_COMPAT_DEFN(PetscErrorCode DeviceContext<T>::getHandle(PetscDeviceContext dctx, void *handle)) { 285a4af0ceeSJacob Faibussowitsch PetscFunctionBegin; 2867a101e5eSJacob Faibussowitsch PetscCall(initialize_handle_(handle_t{}, dctx)); 2877a101e5eSJacob Faibussowitsch *static_cast<typename handle_t::type *>(handle) = impls_cast_(dctx)->get(handle_t{}); 288a4af0ceeSJacob Faibussowitsch PetscFunctionReturn(0); 289a4af0ceeSJacob Faibussowitsch } 290a4af0ceeSJacob Faibussowitsch 29117f48955SJacob Faibussowitsch template <DeviceType T> 292*9371c9d4SSatish Balay PETSC_CXX_COMPAT_DEFN(PetscErrorCode DeviceContext<T>::beginTimer(PetscDeviceContext dctx)) { 29317f48955SJacob Faibussowitsch auto dci = impls_cast_(dctx); 294a4af0ceeSJacob Faibussowitsch 295a4af0ceeSJacob Faibussowitsch PetscFunctionBegin; 296a4af0ceeSJacob Faibussowitsch #if PetscDefined(USE_DEBUG) 2975f80ce2aSJacob Faibussowitsch PetscCheck(!dci->timerInUse, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Forgot to call PetscLogGpuTimeEnd()?"); 298a4af0ceeSJacob Faibussowitsch dci->timerInUse = PETSC_TRUE; 299a4af0ceeSJacob Faibussowitsch #endif 30017f48955SJacob Faibussowitsch if (!dci->begin) { 3019566063dSJacob Faibussowitsch PetscCallCUPM(cupmEventCreate(&dci->begin)); 3029566063dSJacob Faibussowitsch PetscCallCUPM(cupmEventCreate(&dci->end)); 30317f48955SJacob Faibussowitsch } 3049566063dSJacob Faibussowitsch PetscCallCUPM(cupmEventRecord(dci->begin, dci->stream)); 305a4af0ceeSJacob Faibussowitsch PetscFunctionReturn(0); 306a4af0ceeSJacob Faibussowitsch } 307a4af0ceeSJacob Faibussowitsch 30817f48955SJacob Faibussowitsch template <DeviceType T> 309*9371c9d4SSatish Balay PETSC_CXX_COMPAT_DEFN(PetscErrorCode DeviceContext<T>::endTimer(PetscDeviceContext dctx, PetscLogDouble *elapsed)) { 310a4af0ceeSJacob Faibussowitsch float gtime; 31117f48955SJacob Faibussowitsch auto dci = impls_cast_(dctx); 312a4af0ceeSJacob Faibussowitsch 313a4af0ceeSJacob Faibussowitsch PetscFunctionBegin; 314a4af0ceeSJacob Faibussowitsch #if PetscDefined(USE_DEBUG) 3155f80ce2aSJacob Faibussowitsch PetscCheck(dci->timerInUse, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Forgot to call PetscLogGpuTimeBegin()?"); 316a4af0ceeSJacob Faibussowitsch dci->timerInUse = PETSC_FALSE; 317a4af0ceeSJacob Faibussowitsch #endif 3189566063dSJacob Faibussowitsch PetscCallCUPM(cupmEventRecord(dci->end, dci->stream)); 3199566063dSJacob Faibussowitsch PetscCallCUPM(cupmEventSynchronize(dci->end)); 3209566063dSJacob Faibussowitsch PetscCallCUPM(cupmEventElapsedTime(>ime, dci->begin, dci->end)); 32117f48955SJacob Faibussowitsch *elapsed = static_cast<util::remove_pointer_t<decltype(elapsed)>>(gtime); 322a4af0ceeSJacob Faibussowitsch PetscFunctionReturn(0); 323a4af0ceeSJacob Faibussowitsch } 324a4af0ceeSJacob Faibussowitsch 325030f984aSJacob Faibussowitsch // initialize the static member variables 326*9371c9d4SSatish Balay template <DeviceType T> 327*9371c9d4SSatish Balay bool DeviceContext<T>::initialized_ = false; 328030f984aSJacob Faibussowitsch 32917f48955SJacob Faibussowitsch template <DeviceType T> 33017f48955SJacob Faibussowitsch std::array<typename DeviceContext<T>::cupmBlasHandle_t, PETSC_DEVICE_MAX_DEVICES> DeviceContext<T>::blashandles_ = {}; 331030f984aSJacob Faibussowitsch 33217f48955SJacob Faibussowitsch template <DeviceType T> 33317f48955SJacob Faibussowitsch std::array<typename DeviceContext<T>::cupmSolverHandle_t, PETSC_DEVICE_MAX_DEVICES> DeviceContext<T>::solverhandles_ = {}; 33417f48955SJacob Faibussowitsch 33517f48955SJacob Faibussowitsch } // namespace Impl 336030f984aSJacob Faibussowitsch 337a4af0ceeSJacob Faibussowitsch // shorten this one up a bit (and instantiate the templates) 33817f48955SJacob Faibussowitsch using CUPMContextCuda = Impl::DeviceContext<DeviceType::CUDA>; 33917f48955SJacob Faibussowitsch using CUPMContextHip = Impl::DeviceContext<DeviceType::HIP>; 340030f984aSJacob Faibussowitsch 341030f984aSJacob Faibussowitsch // shorthand for what is an EXTREMELY long name 34217f48955SJacob Faibussowitsch #define PetscDeviceContext_(IMPLS) Petsc::Device::CUPM::Impl::DeviceContext<Petsc::Device::CUPM::DeviceType::IMPLS>::PetscDeviceContext_IMPLS 343030f984aSJacob Faibussowitsch 34417f48955SJacob Faibussowitsch } // namespace CUPM 34517f48955SJacob Faibussowitsch 34617f48955SJacob Faibussowitsch } // namespace Device 34717f48955SJacob Faibussowitsch 34817f48955SJacob Faibussowitsch } // namespace Petsc 349030f984aSJacob Faibussowitsch 350a4af0ceeSJacob Faibussowitsch #endif // PETSCDEVICECONTEXTCUDA_HPP 351