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> 6030f984aSJacob Faibussowitsch 7a4af0ceeSJacob Faibussowitsch #include <array> 8a4af0ceeSJacob Faibussowitsch 9a4af0ceeSJacob Faibussowitsch namespace Petsc 10a4af0ceeSJacob Faibussowitsch { 11a4af0ceeSJacob Faibussowitsch 1217f48955SJacob Faibussowitsch namespace Device 1317f48955SJacob Faibussowitsch { 1417f48955SJacob Faibussowitsch 1517f48955SJacob Faibussowitsch namespace CUPM 1617f48955SJacob Faibussowitsch { 1717f48955SJacob Faibussowitsch 1817f48955SJacob Faibussowitsch namespace Impl 1917f48955SJacob Faibussowitsch { 2017f48955SJacob Faibussowitsch 21a4af0ceeSJacob Faibussowitsch namespace detail 22a4af0ceeSJacob Faibussowitsch { 23a4af0ceeSJacob Faibussowitsch 24a4af0ceeSJacob Faibussowitsch // for tag-based dispatch of handle retrieval 2517f48955SJacob Faibussowitsch template <typename T> struct HandleTag { using type = T; }; 26a4af0ceeSJacob Faibussowitsch 27a4af0ceeSJacob Faibussowitsch } // namespace detail 28030f984aSJacob Faibussowitsch 29030f984aSJacob Faibussowitsch // Forward declare 3017f48955SJacob Faibussowitsch template <DeviceType T> class PETSC_VISIBILITY_INTERNAL DeviceContext; 31030f984aSJacob Faibussowitsch 3217f48955SJacob Faibussowitsch template <DeviceType T> 3317f48955SJacob Faibussowitsch class DeviceContext : Impl::BlasInterface<T> 34030f984aSJacob Faibussowitsch { 3517f48955SJacob Faibussowitsch public: 3617f48955SJacob Faibussowitsch PETSC_CUPMBLAS_INHERIT_INTERFACE_TYPEDEFS_USING(cupmBlasInterface_t,T); 3717f48955SJacob Faibussowitsch 3817f48955SJacob Faibussowitsch private: 3917f48955SJacob Faibussowitsch template <typename H> using HandleTag = typename detail::HandleTag<H>; 4017f48955SJacob Faibussowitsch using stream_tag = HandleTag<cupmStream_t>; 4117f48955SJacob Faibussowitsch using blas_tag = HandleTag<cupmBlasHandle_t>; 4217f48955SJacob Faibussowitsch using solver_tag = HandleTag<cupmSolverHandle_t>; 43a4af0ceeSJacob Faibussowitsch 44030f984aSJacob Faibussowitsch public: 45030f984aSJacob Faibussowitsch // This is the canonical PETSc "impls" struct that normally resides in a standalone impls 46030f984aSJacob Faibussowitsch // header, but since we are using the power of templates it must be declared part of 47030f984aSJacob Faibussowitsch // this class to have easy access the same typedefs. Technically one can make a 48030f984aSJacob Faibussowitsch // templated struct outside the class but it's more code for the same result. 49030f984aSJacob Faibussowitsch struct PetscDeviceContext_IMPLS 50030f984aSJacob Faibussowitsch { 51030f984aSJacob Faibussowitsch cupmStream_t stream; 52030f984aSJacob Faibussowitsch cupmEvent_t event; 53a4af0ceeSJacob Faibussowitsch cupmEvent_t begin; // timer-only 54a4af0ceeSJacob Faibussowitsch cupmEvent_t end; // timer-only 55a4af0ceeSJacob Faibussowitsch #if PetscDefined(USE_DEBUG) 56a4af0ceeSJacob Faibussowitsch PetscBool timerInUse; 57a4af0ceeSJacob Faibussowitsch #endif 58030f984aSJacob Faibussowitsch cupmBlasHandle_t blas; 59030f984aSJacob Faibussowitsch cupmSolverHandle_t solver; 60a4af0ceeSJacob Faibussowitsch 6117f48955SJacob Faibussowitsch PETSC_NODISCARD auto get(stream_tag) const -> decltype(this->stream) { return this->stream; } 6217f48955SJacob Faibussowitsch PETSC_NODISCARD auto get(blas_tag) const -> decltype(this->blas) { return this->blas; } 6317f48955SJacob Faibussowitsch PETSC_NODISCARD auto get(solver_tag) const -> decltype(this->solver) { return this->solver; } 64030f984aSJacob Faibussowitsch }; 65030f984aSJacob Faibussowitsch 66030f984aSJacob Faibussowitsch private: 6717f48955SJacob Faibussowitsch static bool initialized_; 6817f48955SJacob Faibussowitsch static std::array<cupmBlasHandle_t,PETSC_DEVICE_MAX_DEVICES> blashandles_; 6917f48955SJacob Faibussowitsch static std::array<cupmSolverHandle_t,PETSC_DEVICE_MAX_DEVICES> solverhandles_; 70030f984aSJacob Faibussowitsch 7117f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DECL(constexpr PetscDeviceContext_IMPLS* impls_cast_(PetscDeviceContext ptr)) 72a4af0ceeSJacob Faibussowitsch { 73a4af0ceeSJacob Faibussowitsch return static_cast<PetscDeviceContext_IMPLS*>(ptr->data); 74a4af0ceeSJacob Faibussowitsch } 75a4af0ceeSJacob Faibussowitsch 7617f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DECL(PetscErrorCode initialize_handle_(cupmBlasHandle_t &handle)) 77030f984aSJacob Faibussowitsch { 78030f984aSJacob Faibussowitsch PetscFunctionBegin; 7917f48955SJacob Faibussowitsch if (handle) PetscFunctionReturn(0); 8017f48955SJacob Faibussowitsch for (auto i = 0; i < 3; ++i) { 8117f48955SJacob Faibussowitsch auto cberr = cupmBlasCreate(&handle); 8217f48955SJacob Faibussowitsch if (PetscLikely(cberr == CUPMBLAS_STATUS_SUCCESS)) break; 8317f48955SJacob Faibussowitsch if (PetscUnlikely(cberr != CUPMBLAS_STATUS_ALLOC_FAILED) && (cberr != CUPMBLAS_STATUS_NOT_INITIALIZED)) CHKERRCUPMBLAS(cberr); 8417f48955SJacob Faibussowitsch if (i != 2) { 85*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSleep(3)); 8617f48955SJacob Faibussowitsch continue; 87a4af0ceeSJacob Faibussowitsch } 88*5f80ce2aSJacob Faibussowitsch PetscCheck(cberr == CUPMBLAS_STATUS_SUCCESS,PETSC_COMM_SELF,PETSC_ERR_GPU_RESOURCE,"Unable to initialize %s",cupmBlasName()); 89a4af0ceeSJacob Faibussowitsch } 90030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 91030f984aSJacob Faibussowitsch } 92030f984aSJacob Faibussowitsch 9317f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DECL(PetscErrorCode set_handle_stream_(cupmBlasHandle_t &handle, cupmStream_t &stream)) 9417f48955SJacob Faibussowitsch { 9517f48955SJacob Faibussowitsch cupmStream_t cupmStream; 9617f48955SJacob Faibussowitsch 9717f48955SJacob Faibussowitsch PetscFunctionBegin; 98*5f80ce2aSJacob Faibussowitsch CHKERRCUPMBLAS(cupmBlasGetStream(handle,&cupmStream)); 99*5f80ce2aSJacob Faibussowitsch if (cupmStream != stream) CHKERRCUPMBLAS(cupmBlasSetStream(handle,stream)); 10017f48955SJacob Faibussowitsch PetscFunctionReturn(0); 10117f48955SJacob Faibussowitsch } 10217f48955SJacob Faibussowitsch 10317f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DECL(PetscErrorCode finalize_()) 10417f48955SJacob Faibussowitsch { 10517f48955SJacob Faibussowitsch PetscFunctionBegin; 10617f48955SJacob Faibussowitsch for (auto&& handle : blashandles_) { 10717f48955SJacob Faibussowitsch if (handle) { 108*5f80ce2aSJacob Faibussowitsch CHKERRCUPMBLAS(cupmBlasDestroy(handle)); 10917f48955SJacob Faibussowitsch handle = nullptr; 11017f48955SJacob Faibussowitsch } 11117f48955SJacob Faibussowitsch } 11217f48955SJacob Faibussowitsch for (auto&& handle : solverhandles_) { 11317f48955SJacob Faibussowitsch if (handle) { 114*5f80ce2aSJacob Faibussowitsch CHKERRQ(cupmBlasInterface_t::DestroyHandle(handle)); 11517f48955SJacob Faibussowitsch handle = nullptr; 11617f48955SJacob Faibussowitsch } 11717f48955SJacob Faibussowitsch } 11817f48955SJacob Faibussowitsch initialized_ = false; 11917f48955SJacob Faibussowitsch PetscFunctionReturn(0); 12017f48955SJacob Faibussowitsch } 12117f48955SJacob Faibussowitsch 12217f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DECL(PetscErrorCode initialize_(PetscInt id, PetscDeviceContext_IMPLS *dci)) 123030f984aSJacob Faibussowitsch { 124030f984aSJacob Faibussowitsch 125030f984aSJacob Faibussowitsch PetscFunctionBegin; 126*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDeviceCheckDeviceCount_Internal(id)); 12717f48955SJacob Faibussowitsch if (!initialized_) { 12817f48955SJacob Faibussowitsch initialized_ = true; 129*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscRegisterFinalize(finalize_)); 130030f984aSJacob Faibussowitsch } 131a4af0ceeSJacob Faibussowitsch // use the blashandle as a canary 13217f48955SJacob Faibussowitsch if (!blashandles_[id]) { 133*5f80ce2aSJacob Faibussowitsch CHKERRQ(initialize_handle_(blashandles_[id])); 134*5f80ce2aSJacob Faibussowitsch CHKERRQ(cupmBlasInterface_t::InitializeHandle(solverhandles_[id])); 135030f984aSJacob Faibussowitsch } 136*5f80ce2aSJacob Faibussowitsch CHKERRQ(set_handle_stream_(blashandles_[id],dci->stream)); 137*5f80ce2aSJacob Faibussowitsch CHKERRQ(cupmBlasInterface_t::SetHandleStream(solverhandles_[id],dci->stream)); 13817f48955SJacob Faibussowitsch dci->blas = blashandles_[id]; 13917f48955SJacob Faibussowitsch dci->solver = solverhandles_[id]; 140030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 141030f984aSJacob Faibussowitsch } 142030f984aSJacob Faibussowitsch 143030f984aSJacob Faibussowitsch public: 144a4af0ceeSJacob Faibussowitsch const struct _DeviceContextOps ops = { 145a4af0ceeSJacob Faibussowitsch destroy, 146a4af0ceeSJacob Faibussowitsch changeStreamType, 147a4af0ceeSJacob Faibussowitsch setUp, 148a4af0ceeSJacob Faibussowitsch query, 149a4af0ceeSJacob Faibussowitsch waitForContext, 150a4af0ceeSJacob Faibussowitsch synchronize, 15117f48955SJacob Faibussowitsch getHandle<blas_tag>, 15217f48955SJacob Faibussowitsch getHandle<solver_tag>, 15317f48955SJacob Faibussowitsch getHandle<stream_tag>, 154a4af0ceeSJacob Faibussowitsch beginTimer, 15517f48955SJacob Faibussowitsch endTimer, 156a4af0ceeSJacob Faibussowitsch }; 157030f984aSJacob Faibussowitsch 158030f984aSJacob Faibussowitsch // All of these functions MUST be static in order to be callable from C, otherwise they 159030f984aSJacob Faibussowitsch // get the implicit 'this' pointer tacked on 16017f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DECL(PetscErrorCode destroy(PetscDeviceContext)); 16117f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DECL(PetscErrorCode changeStreamType(PetscDeviceContext,PetscStreamType)); 16217f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DECL(PetscErrorCode setUp(PetscDeviceContext)); 16317f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DECL(PetscErrorCode query(PetscDeviceContext,PetscBool*)); 16417f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DECL(PetscErrorCode waitForContext(PetscDeviceContext,PetscDeviceContext)); 16517f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DECL(PetscErrorCode synchronize(PetscDeviceContext)); 166a4af0ceeSJacob Faibussowitsch template <typename Handle_t> 16717f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DECL(PetscErrorCode getHandle(PetscDeviceContext,void*)); 16817f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DECL(PetscErrorCode beginTimer(PetscDeviceContext)); 16917f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DECL(PetscErrorCode endTimer(PetscDeviceContext,PetscLogDouble*)); 170030f984aSJacob Faibussowitsch }; 171030f984aSJacob Faibussowitsch 17217f48955SJacob Faibussowitsch template <DeviceType T> 17317f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DEFN(PetscErrorCode DeviceContext<T>::destroy(PetscDeviceContext dctx)) 174030f984aSJacob Faibussowitsch { 17517f48955SJacob Faibussowitsch auto dci = impls_cast_(dctx); 176030f984aSJacob Faibussowitsch 177030f984aSJacob Faibussowitsch PetscFunctionBegin; 178*5f80ce2aSJacob Faibussowitsch if (dci->stream) CHKERRCUPM(cupmStreamDestroy(dci->stream)); 179*5f80ce2aSJacob Faibussowitsch if (dci->event) CHKERRCUPM(cupmEventDestroy(dci->event)); 180*5f80ce2aSJacob Faibussowitsch if (dci->begin) CHKERRCUPM(cupmEventDestroy(dci->begin)); 181*5f80ce2aSJacob Faibussowitsch if (dci->end) CHKERRCUPM(cupmEventDestroy(dci->end)); 182*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(dctx->data)); 183030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 184030f984aSJacob Faibussowitsch } 185030f984aSJacob Faibussowitsch 18617f48955SJacob Faibussowitsch template <DeviceType T> 18717f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DEFN(PetscErrorCode DeviceContext<T>::changeStreamType(PetscDeviceContext dctx, PETSC_UNUSED PetscStreamType stype)) 188030f984aSJacob Faibussowitsch { 18917f48955SJacob Faibussowitsch auto dci = impls_cast_(dctx); 190030f984aSJacob Faibussowitsch 191030f984aSJacob Faibussowitsch PetscFunctionBegin; 192030f984aSJacob Faibussowitsch if (dci->stream) { 193*5f80ce2aSJacob Faibussowitsch CHKERRCUPM(cupmStreamDestroy(dci->stream)); 194030f984aSJacob Faibussowitsch dci->stream = nullptr; 195030f984aSJacob Faibussowitsch } 196030f984aSJacob Faibussowitsch // set these to null so they aren't usable until setup is called again 197030f984aSJacob Faibussowitsch dci->blas = nullptr; 198030f984aSJacob Faibussowitsch dci->solver = nullptr; 199030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 200030f984aSJacob Faibussowitsch } 201030f984aSJacob Faibussowitsch 20217f48955SJacob Faibussowitsch template <DeviceType T> 20317f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DEFN(PetscErrorCode DeviceContext<T>::setUp(PetscDeviceContext dctx)) 204030f984aSJacob Faibussowitsch { 20517f48955SJacob Faibussowitsch auto dci = impls_cast_(dctx); 206030f984aSJacob Faibussowitsch 207030f984aSJacob Faibussowitsch PetscFunctionBegin; 20817f48955SJacob Faibussowitsch if (dci->stream) { 209*5f80ce2aSJacob Faibussowitsch CHKERRCUPM(cupmStreamDestroy(dci->stream)); 21017f48955SJacob Faibussowitsch dci->stream = nullptr; 21117f48955SJacob Faibussowitsch } 212030f984aSJacob Faibussowitsch switch (dctx->streamType) { 213030f984aSJacob Faibussowitsch case PETSC_STREAM_GLOBAL_BLOCKING: 214030f984aSJacob Faibussowitsch // don't create a stream for global blocking 215030f984aSJacob Faibussowitsch break; 216030f984aSJacob Faibussowitsch case PETSC_STREAM_DEFAULT_BLOCKING: 217*5f80ce2aSJacob Faibussowitsch CHKERRCUPM(cupmStreamCreate(&dci->stream)); 218030f984aSJacob Faibussowitsch break; 219030f984aSJacob Faibussowitsch case PETSC_STREAM_GLOBAL_NONBLOCKING: 220*5f80ce2aSJacob Faibussowitsch CHKERRCUPM(cupmStreamCreateWithFlags(&dci->stream,cupmStreamNonBlocking)); 221030f984aSJacob Faibussowitsch break; 222030f984aSJacob Faibussowitsch default: 22398921bdaSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_CORRUPT,"Invalid PetscStreamType %s",PetscStreamTypes[util::integral_value(dctx->streamType)]); 224030f984aSJacob Faibussowitsch break; 225030f984aSJacob Faibussowitsch } 226*5f80ce2aSJacob Faibussowitsch if (!dci->event) CHKERRCUPM(cupmEventCreate(&dci->event)); 227a4af0ceeSJacob Faibussowitsch #if PetscDefined(USE_DEBUG) 228a4af0ceeSJacob Faibussowitsch dci->timerInUse = PETSC_FALSE; 229a4af0ceeSJacob Faibussowitsch #endif 230*5f80ce2aSJacob Faibussowitsch CHKERRQ(initialize_(dctx->device->deviceId,dci)); 231030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 232030f984aSJacob Faibussowitsch } 233030f984aSJacob Faibussowitsch 23417f48955SJacob Faibussowitsch template <DeviceType T> 23517f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DEFN(PetscErrorCode DeviceContext<T>::query(PetscDeviceContext dctx, PetscBool *idle)) 236030f984aSJacob Faibussowitsch { 237030f984aSJacob Faibussowitsch cupmError_t cerr; 238030f984aSJacob Faibussowitsch 239030f984aSJacob Faibussowitsch PetscFunctionBegin; 24017f48955SJacob Faibussowitsch cerr = cupmStreamQuery(impls_cast_(dctx)->stream); 241a4af0ceeSJacob Faibussowitsch if (cerr == cupmSuccess) *idle = PETSC_TRUE; 242a4af0ceeSJacob Faibussowitsch else { 243030f984aSJacob Faibussowitsch // somethings gone wrong 244a4af0ceeSJacob Faibussowitsch if (PetscUnlikely(cerr != cupmErrorNotReady)) CHKERRCUPM(cerr); 245a4af0ceeSJacob Faibussowitsch *idle = PETSC_FALSE; 246030f984aSJacob Faibussowitsch } 247030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 248030f984aSJacob Faibussowitsch } 249030f984aSJacob Faibussowitsch 25017f48955SJacob Faibussowitsch template <DeviceType T> 25117f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DEFN(PetscErrorCode DeviceContext<T>::waitForContext(PetscDeviceContext dctxa, PetscDeviceContext dctxb)) 252030f984aSJacob Faibussowitsch { 25317f48955SJacob Faibussowitsch auto dcib = impls_cast_(dctxb); 254030f984aSJacob Faibussowitsch 255030f984aSJacob Faibussowitsch PetscFunctionBegin; 256*5f80ce2aSJacob Faibussowitsch CHKERRCUPM(cupmEventRecord(dcib->event,dcib->stream)); 257*5f80ce2aSJacob Faibussowitsch CHKERRCUPM(cupmStreamWaitEvent(impls_cast_(dctxa)->stream,dcib->event,0)); 258030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 259030f984aSJacob Faibussowitsch } 260030f984aSJacob Faibussowitsch 26117f48955SJacob Faibussowitsch template <DeviceType T> 26217f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DEFN(PetscErrorCode DeviceContext<T>::synchronize(PetscDeviceContext dctx)) 263030f984aSJacob Faibussowitsch { 26417f48955SJacob Faibussowitsch auto dci = impls_cast_(dctx); 265030f984aSJacob Faibussowitsch 266030f984aSJacob Faibussowitsch PetscFunctionBegin; 267030f984aSJacob Faibussowitsch // in case anything was queued on the event 268*5f80ce2aSJacob Faibussowitsch CHKERRCUPM(cupmStreamWaitEvent(dci->stream,dci->event,0)); 269*5f80ce2aSJacob Faibussowitsch CHKERRCUPM(cupmStreamSynchronize(dci->stream)); 270030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 271030f984aSJacob Faibussowitsch } 272030f984aSJacob Faibussowitsch 27317f48955SJacob Faibussowitsch template <DeviceType T> 27417f48955SJacob Faibussowitsch template <typename handle_t> 27517f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DEFN(PetscErrorCode DeviceContext<T>::getHandle(PetscDeviceContext dctx, void *handle)) 276a4af0ceeSJacob Faibussowitsch { 277a4af0ceeSJacob Faibussowitsch PetscFunctionBegin; 27817f48955SJacob Faibussowitsch *static_cast<typename handle_t::type*>(handle) = impls_cast_(dctx)->get(handle_t()); 279a4af0ceeSJacob Faibussowitsch PetscFunctionReturn(0); 280a4af0ceeSJacob Faibussowitsch } 281a4af0ceeSJacob Faibussowitsch 28217f48955SJacob Faibussowitsch template <DeviceType T> 28317f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DEFN(PetscErrorCode DeviceContext<T>::beginTimer(PetscDeviceContext dctx)) 284a4af0ceeSJacob Faibussowitsch { 28517f48955SJacob Faibussowitsch auto dci = impls_cast_(dctx); 286a4af0ceeSJacob Faibussowitsch 287a4af0ceeSJacob Faibussowitsch PetscFunctionBegin; 288a4af0ceeSJacob Faibussowitsch #if PetscDefined(USE_DEBUG) 289*5f80ce2aSJacob Faibussowitsch PetscCheck(!dci->timerInUse,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Forgot to call PetscLogGpuTimeEnd()?"); 290a4af0ceeSJacob Faibussowitsch dci->timerInUse = PETSC_TRUE; 291a4af0ceeSJacob Faibussowitsch #endif 29217f48955SJacob Faibussowitsch if (!dci->begin) { 293*5f80ce2aSJacob Faibussowitsch CHKERRCUPM(cupmEventCreate(&dci->begin)); 294*5f80ce2aSJacob Faibussowitsch CHKERRCUPM(cupmEventCreate(&dci->end)); 29517f48955SJacob Faibussowitsch } 296*5f80ce2aSJacob Faibussowitsch CHKERRCUPM(cupmEventRecord(dci->begin,dci->stream)); 297a4af0ceeSJacob Faibussowitsch PetscFunctionReturn(0); 298a4af0ceeSJacob Faibussowitsch } 299a4af0ceeSJacob Faibussowitsch 30017f48955SJacob Faibussowitsch template <DeviceType T> 30117f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DEFN(PetscErrorCode DeviceContext<T>::endTimer(PetscDeviceContext dctx, PetscLogDouble *elapsed)) 302a4af0ceeSJacob Faibussowitsch { 303a4af0ceeSJacob Faibussowitsch float gtime; 30417f48955SJacob Faibussowitsch auto dci = impls_cast_(dctx); 305a4af0ceeSJacob Faibussowitsch 306a4af0ceeSJacob Faibussowitsch PetscFunctionBegin; 307a4af0ceeSJacob Faibussowitsch #if PetscDefined(USE_DEBUG) 308*5f80ce2aSJacob Faibussowitsch PetscCheck(dci->timerInUse,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Forgot to call PetscLogGpuTimeBegin()?"); 309a4af0ceeSJacob Faibussowitsch dci->timerInUse = PETSC_FALSE; 310a4af0ceeSJacob Faibussowitsch #endif 311*5f80ce2aSJacob Faibussowitsch CHKERRCUPM(cupmEventRecord(dci->end,dci->stream)); 312*5f80ce2aSJacob Faibussowitsch CHKERRCUPM(cupmEventSynchronize(dci->end)); 313*5f80ce2aSJacob Faibussowitsch CHKERRCUPM(cupmEventElapsedTime(>ime,dci->begin,dci->end)); 31417f48955SJacob Faibussowitsch *elapsed = static_cast<util::remove_pointer_t<decltype(elapsed)>>(gtime); 315a4af0ceeSJacob Faibussowitsch PetscFunctionReturn(0); 316a4af0ceeSJacob Faibussowitsch } 317a4af0ceeSJacob Faibussowitsch 318030f984aSJacob Faibussowitsch // initialize the static member variables 31917f48955SJacob Faibussowitsch template <DeviceType T> bool DeviceContext<T>::initialized_ = false; 320030f984aSJacob Faibussowitsch 32117f48955SJacob Faibussowitsch template <DeviceType T> 32217f48955SJacob Faibussowitsch std::array<typename DeviceContext<T>::cupmBlasHandle_t,PETSC_DEVICE_MAX_DEVICES> DeviceContext<T>::blashandles_ = {}; 323030f984aSJacob Faibussowitsch 32417f48955SJacob Faibussowitsch template <DeviceType T> 32517f48955SJacob Faibussowitsch std::array<typename DeviceContext<T>::cupmSolverHandle_t,PETSC_DEVICE_MAX_DEVICES> DeviceContext<T>::solverhandles_ = {}; 32617f48955SJacob Faibussowitsch 32717f48955SJacob Faibussowitsch } // namespace Impl 328030f984aSJacob Faibussowitsch 329a4af0ceeSJacob Faibussowitsch // shorten this one up a bit (and instantiate the templates) 33017f48955SJacob Faibussowitsch using CUPMContextCuda = Impl::DeviceContext<DeviceType::CUDA>; 33117f48955SJacob Faibussowitsch using CUPMContextHip = Impl::DeviceContext<DeviceType::HIP>; 332030f984aSJacob Faibussowitsch 333030f984aSJacob Faibussowitsch // shorthand for what is an EXTREMELY long name 33417f48955SJacob Faibussowitsch #define PetscDeviceContext_(IMPLS) Petsc::Device::CUPM::Impl::DeviceContext<Petsc::Device::CUPM::DeviceType::IMPLS>::PetscDeviceContext_IMPLS 335030f984aSJacob Faibussowitsch 33617f48955SJacob Faibussowitsch } // namespace CUPM 33717f48955SJacob Faibussowitsch 33817f48955SJacob Faibussowitsch } // namespace Device 33917f48955SJacob Faibussowitsch 34017f48955SJacob Faibussowitsch } // namespace Petsc 341030f984aSJacob Faibussowitsch 342a4af0ceeSJacob Faibussowitsch #endif // PETSCDEVICECONTEXTCUDA_HPP 343