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) { 8517f48955SJacob Faibussowitsch auto ierr = PetscSleep(3);CHKERRQ(ierr); 8617f48955SJacob Faibussowitsch continue; 87a4af0ceeSJacob Faibussowitsch } 88*98921bdaSJacob Faibussowitsch if (PetscUnlikely(cberr != CUPMBLAS_STATUS_SUCCESS)) SETERRQ(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 cupmBlasError_t cberr; 9717f48955SJacob Faibussowitsch 9817f48955SJacob Faibussowitsch PetscFunctionBegin; 9917f48955SJacob Faibussowitsch cberr = cupmBlasGetStream(handle,&cupmStream);CHKERRCUPMBLAS(cberr); 10017f48955SJacob Faibussowitsch if (cupmStream != stream) {cberr = cupmBlasSetStream(handle,stream);CHKERRCUPMBLAS(cberr);} 10117f48955SJacob Faibussowitsch PetscFunctionReturn(0); 10217f48955SJacob Faibussowitsch } 10317f48955SJacob Faibussowitsch 10417f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DECL(PetscErrorCode finalize_()) 10517f48955SJacob Faibussowitsch { 10617f48955SJacob Faibussowitsch PetscFunctionBegin; 10717f48955SJacob Faibussowitsch for (auto&& handle : blashandles_) { 10817f48955SJacob Faibussowitsch if (handle) { 10917f48955SJacob Faibussowitsch auto cberr = cupmBlasDestroy(handle);CHKERRCUPMBLAS(cberr); 11017f48955SJacob Faibussowitsch handle = nullptr; 11117f48955SJacob Faibussowitsch } 11217f48955SJacob Faibussowitsch } 11317f48955SJacob Faibussowitsch for (auto&& handle : solverhandles_) { 11417f48955SJacob Faibussowitsch if (handle) { 11517f48955SJacob Faibussowitsch auto ierr = cupmBlasInterface_t::DestroyHandle(handle);CHKERRQ(ierr); 11617f48955SJacob Faibussowitsch handle = nullptr; 11717f48955SJacob Faibussowitsch } 11817f48955SJacob Faibussowitsch } 11917f48955SJacob Faibussowitsch initialized_ = false; 12017f48955SJacob Faibussowitsch PetscFunctionReturn(0); 12117f48955SJacob Faibussowitsch } 12217f48955SJacob Faibussowitsch 12317f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DECL(PetscErrorCode initialize_(PetscInt id, PetscDeviceContext_IMPLS *dci)) 124030f984aSJacob Faibussowitsch { 125030f984aSJacob Faibussowitsch PetscErrorCode ierr; 126030f984aSJacob Faibussowitsch 127030f984aSJacob Faibussowitsch PetscFunctionBegin; 128a4af0ceeSJacob Faibussowitsch ierr = PetscDeviceCheckDeviceCount_Internal(id);CHKERRQ(ierr); 12917f48955SJacob Faibussowitsch if (!initialized_) { 13017f48955SJacob Faibussowitsch initialized_ = true; 13117f48955SJacob Faibussowitsch ierr = PetscRegisterFinalize(finalize_);CHKERRQ(ierr); 132030f984aSJacob Faibussowitsch } 133a4af0ceeSJacob Faibussowitsch // use the blashandle as a canary 13417f48955SJacob Faibussowitsch if (!blashandles_[id]) { 13517f48955SJacob Faibussowitsch ierr = initialize_handle_(blashandles_[id]);CHKERRQ(ierr); 13617f48955SJacob Faibussowitsch ierr = cupmBlasInterface_t::InitializeHandle(solverhandles_[id]);CHKERRQ(ierr); 137030f984aSJacob Faibussowitsch } 13817f48955SJacob Faibussowitsch ierr = set_handle_stream_(blashandles_[id],dci->stream);CHKERRQ(ierr); 13917f48955SJacob Faibussowitsch ierr = cupmBlasInterface_t::SetHandleStream(solverhandles_[id],dci->stream);CHKERRQ(ierr); 14017f48955SJacob Faibussowitsch dci->blas = blashandles_[id]; 14117f48955SJacob Faibussowitsch dci->solver = solverhandles_[id]; 142030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 143030f984aSJacob Faibussowitsch } 144030f984aSJacob Faibussowitsch 145030f984aSJacob Faibussowitsch public: 146a4af0ceeSJacob Faibussowitsch const struct _DeviceContextOps ops = { 147a4af0ceeSJacob Faibussowitsch destroy, 148a4af0ceeSJacob Faibussowitsch changeStreamType, 149a4af0ceeSJacob Faibussowitsch setUp, 150a4af0ceeSJacob Faibussowitsch query, 151a4af0ceeSJacob Faibussowitsch waitForContext, 152a4af0ceeSJacob Faibussowitsch synchronize, 15317f48955SJacob Faibussowitsch getHandle<blas_tag>, 15417f48955SJacob Faibussowitsch getHandle<solver_tag>, 15517f48955SJacob Faibussowitsch getHandle<stream_tag>, 156a4af0ceeSJacob Faibussowitsch beginTimer, 15717f48955SJacob Faibussowitsch endTimer, 158a4af0ceeSJacob Faibussowitsch }; 159030f984aSJacob Faibussowitsch 160030f984aSJacob Faibussowitsch // All of these functions MUST be static in order to be callable from C, otherwise they 161030f984aSJacob Faibussowitsch // get the implicit 'this' pointer tacked on 16217f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DECL(PetscErrorCode destroy(PetscDeviceContext)); 16317f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DECL(PetscErrorCode changeStreamType(PetscDeviceContext,PetscStreamType)); 16417f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DECL(PetscErrorCode setUp(PetscDeviceContext)); 16517f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DECL(PetscErrorCode query(PetscDeviceContext,PetscBool*)); 16617f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DECL(PetscErrorCode waitForContext(PetscDeviceContext,PetscDeviceContext)); 16717f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DECL(PetscErrorCode synchronize(PetscDeviceContext)); 168a4af0ceeSJacob Faibussowitsch template <typename Handle_t> 16917f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DECL(PetscErrorCode getHandle(PetscDeviceContext,void*)); 17017f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DECL(PetscErrorCode beginTimer(PetscDeviceContext)); 17117f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DECL(PetscErrorCode endTimer(PetscDeviceContext,PetscLogDouble*)); 172030f984aSJacob Faibussowitsch }; 173030f984aSJacob Faibussowitsch 17417f48955SJacob Faibussowitsch template <DeviceType T> 17517f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DEFN(PetscErrorCode DeviceContext<T>::destroy(PetscDeviceContext dctx)) 176030f984aSJacob Faibussowitsch { 177030f984aSJacob Faibussowitsch cupmError_t cerr; 178030f984aSJacob Faibussowitsch PetscErrorCode ierr; 17917f48955SJacob Faibussowitsch auto dci = impls_cast_(dctx); 180030f984aSJacob Faibussowitsch 181030f984aSJacob Faibussowitsch PetscFunctionBegin; 182030f984aSJacob Faibussowitsch if (dci->stream) {cerr = cupmStreamDestroy(dci->stream);CHKERRCUPM(cerr);} 18317f48955SJacob Faibussowitsch if (dci->event) {cerr = cupmEventDestroy(dci->event);CHKERRCUPM(cerr); } 18417f48955SJacob Faibussowitsch if (dci->begin) {cerr = cupmEventDestroy(dci->begin);CHKERRCUPM(cerr); } 18517f48955SJacob Faibussowitsch if (dci->end) {cerr = cupmEventDestroy(dci->end);CHKERRCUPM(cerr); } 186030f984aSJacob Faibussowitsch ierr = PetscFree(dctx->data);CHKERRQ(ierr); 187030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 188030f984aSJacob Faibussowitsch } 189030f984aSJacob Faibussowitsch 19017f48955SJacob Faibussowitsch template <DeviceType T> 19117f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DEFN(PetscErrorCode DeviceContext<T>::changeStreamType(PetscDeviceContext dctx, PETSC_UNUSED PetscStreamType stype)) 192030f984aSJacob Faibussowitsch { 19317f48955SJacob Faibussowitsch auto dci = impls_cast_(dctx); 194030f984aSJacob Faibussowitsch 195030f984aSJacob Faibussowitsch PetscFunctionBegin; 196030f984aSJacob Faibussowitsch if (dci->stream) { 19717f48955SJacob Faibussowitsch auto cerr = cupmStreamDestroy(dci->stream);CHKERRCUPM(cerr); 198030f984aSJacob Faibussowitsch dci->stream = nullptr; 199030f984aSJacob Faibussowitsch } 200030f984aSJacob Faibussowitsch // set these to null so they aren't usable until setup is called again 201030f984aSJacob Faibussowitsch dci->blas = nullptr; 202030f984aSJacob Faibussowitsch dci->solver = nullptr; 203030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 204030f984aSJacob Faibussowitsch } 205030f984aSJacob Faibussowitsch 20617f48955SJacob Faibussowitsch template <DeviceType T> 20717f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DEFN(PetscErrorCode DeviceContext<T>::setUp(PetscDeviceContext dctx)) 208030f984aSJacob Faibussowitsch { 209030f984aSJacob Faibussowitsch PetscErrorCode ierr; 210030f984aSJacob Faibussowitsch cupmError_t cerr; 21117f48955SJacob Faibussowitsch auto dci = impls_cast_(dctx); 212030f984aSJacob Faibussowitsch 213030f984aSJacob Faibussowitsch PetscFunctionBegin; 21417f48955SJacob Faibussowitsch if (dci->stream) { 21517f48955SJacob Faibussowitsch cerr = cupmStreamDestroy(dci->stream);CHKERRCUPM(cerr); 21617f48955SJacob Faibussowitsch dci->stream = nullptr; 21717f48955SJacob Faibussowitsch } 218030f984aSJacob Faibussowitsch switch (dctx->streamType) { 219030f984aSJacob Faibussowitsch case PETSC_STREAM_GLOBAL_BLOCKING: 220030f984aSJacob Faibussowitsch // don't create a stream for global blocking 221030f984aSJacob Faibussowitsch break; 222030f984aSJacob Faibussowitsch case PETSC_STREAM_DEFAULT_BLOCKING: 223030f984aSJacob Faibussowitsch cerr = cupmStreamCreate(&dci->stream);CHKERRCUPM(cerr); 224030f984aSJacob Faibussowitsch break; 225030f984aSJacob Faibussowitsch case PETSC_STREAM_GLOBAL_NONBLOCKING: 226030f984aSJacob Faibussowitsch cerr = cupmStreamCreateWithFlags(&dci->stream,cupmStreamNonBlocking);CHKERRCUPM(cerr); 227030f984aSJacob Faibussowitsch break; 228030f984aSJacob Faibussowitsch default: 229*98921bdaSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_CORRUPT,"Invalid PetscStreamType %s",PetscStreamTypes[util::integral_value(dctx->streamType)]); 230030f984aSJacob Faibussowitsch break; 231030f984aSJacob Faibussowitsch } 23217f48955SJacob Faibussowitsch if (!dci->event) {cerr = cupmEventCreate(&dci->event);CHKERRCUPM(cerr);} 233a4af0ceeSJacob Faibussowitsch #if PetscDefined(USE_DEBUG) 234a4af0ceeSJacob Faibussowitsch dci->timerInUse = PETSC_FALSE; 235a4af0ceeSJacob Faibussowitsch #endif 23617f48955SJacob Faibussowitsch ierr = initialize_(dctx->device->deviceId,dci);CHKERRQ(ierr); 237030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 238030f984aSJacob Faibussowitsch } 239030f984aSJacob Faibussowitsch 24017f48955SJacob Faibussowitsch template <DeviceType T> 24117f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DEFN(PetscErrorCode DeviceContext<T>::query(PetscDeviceContext dctx, PetscBool *idle)) 242030f984aSJacob Faibussowitsch { 243030f984aSJacob Faibussowitsch cupmError_t cerr; 244030f984aSJacob Faibussowitsch 245030f984aSJacob Faibussowitsch PetscFunctionBegin; 24617f48955SJacob Faibussowitsch cerr = cupmStreamQuery(impls_cast_(dctx)->stream); 247a4af0ceeSJacob Faibussowitsch if (cerr == cupmSuccess) *idle = PETSC_TRUE; 248a4af0ceeSJacob Faibussowitsch else { 249030f984aSJacob Faibussowitsch // somethings gone wrong 250a4af0ceeSJacob Faibussowitsch if (PetscUnlikely(cerr != cupmErrorNotReady)) CHKERRCUPM(cerr); 251a4af0ceeSJacob Faibussowitsch *idle = PETSC_FALSE; 252030f984aSJacob Faibussowitsch } 253030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 254030f984aSJacob Faibussowitsch } 255030f984aSJacob Faibussowitsch 25617f48955SJacob Faibussowitsch template <DeviceType T> 25717f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DEFN(PetscErrorCode DeviceContext<T>::waitForContext(PetscDeviceContext dctxa, PetscDeviceContext dctxb)) 258030f984aSJacob Faibussowitsch { 259030f984aSJacob Faibussowitsch cupmError_t cerr; 26017f48955SJacob Faibussowitsch auto dcib = impls_cast_(dctxb); 261030f984aSJacob Faibussowitsch 262030f984aSJacob Faibussowitsch PetscFunctionBegin; 263030f984aSJacob Faibussowitsch cerr = cupmEventRecord(dcib->event,dcib->stream);CHKERRCUPM(cerr); 26417f48955SJacob Faibussowitsch cerr = cupmStreamWaitEvent(impls_cast_(dctxa)->stream,dcib->event,0);CHKERRCUPM(cerr); 265030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 266030f984aSJacob Faibussowitsch } 267030f984aSJacob Faibussowitsch 26817f48955SJacob Faibussowitsch template <DeviceType T> 26917f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DEFN(PetscErrorCode DeviceContext<T>::synchronize(PetscDeviceContext dctx)) 270030f984aSJacob Faibussowitsch { 271030f984aSJacob Faibussowitsch cupmError_t cerr; 27217f48955SJacob Faibussowitsch auto dci = impls_cast_(dctx); 273030f984aSJacob Faibussowitsch 274030f984aSJacob Faibussowitsch PetscFunctionBegin; 275030f984aSJacob Faibussowitsch // in case anything was queued on the event 276030f984aSJacob Faibussowitsch cerr = cupmStreamWaitEvent(dci->stream,dci->event,0);CHKERRCUPM(cerr); 277030f984aSJacob Faibussowitsch cerr = cupmStreamSynchronize(dci->stream);CHKERRCUPM(cerr); 278030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 279030f984aSJacob Faibussowitsch } 280030f984aSJacob Faibussowitsch 28117f48955SJacob Faibussowitsch template <DeviceType T> 28217f48955SJacob Faibussowitsch template <typename handle_t> 28317f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DEFN(PetscErrorCode DeviceContext<T>::getHandle(PetscDeviceContext dctx, void *handle)) 284a4af0ceeSJacob Faibussowitsch { 285a4af0ceeSJacob Faibussowitsch PetscFunctionBegin; 28617f48955SJacob Faibussowitsch *static_cast<typename handle_t::type*>(handle) = impls_cast_(dctx)->get(handle_t()); 287a4af0ceeSJacob Faibussowitsch PetscFunctionReturn(0); 288a4af0ceeSJacob Faibussowitsch } 289a4af0ceeSJacob Faibussowitsch 29017f48955SJacob Faibussowitsch template <DeviceType T> 29117f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DEFN(PetscErrorCode DeviceContext<T>::beginTimer(PetscDeviceContext dctx)) 292a4af0ceeSJacob Faibussowitsch { 29317f48955SJacob Faibussowitsch auto dci = impls_cast_(dctx); 294a4af0ceeSJacob Faibussowitsch cupmError_t cerr; 295a4af0ceeSJacob Faibussowitsch 296a4af0ceeSJacob Faibussowitsch PetscFunctionBegin; 297a4af0ceeSJacob Faibussowitsch #if PetscDefined(USE_DEBUG) 298a4af0ceeSJacob Faibussowitsch if (PetscUnlikely(dci->timerInUse)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Forgot to call PetscLogGpuTimeEnd()?"); 299a4af0ceeSJacob Faibussowitsch dci->timerInUse = PETSC_TRUE; 300a4af0ceeSJacob Faibussowitsch #endif 30117f48955SJacob Faibussowitsch if (!dci->begin) { 30217f48955SJacob Faibussowitsch cerr = cupmEventCreate(&dci->begin);CHKERRCUPM(cerr); 30317f48955SJacob Faibussowitsch cerr = cupmEventCreate(&dci->end);CHKERRCUPM(cerr); 30417f48955SJacob Faibussowitsch } 305a4af0ceeSJacob Faibussowitsch cerr = cupmEventRecord(dci->begin,dci->stream);CHKERRCUPM(cerr); 306a4af0ceeSJacob Faibussowitsch PetscFunctionReturn(0); 307a4af0ceeSJacob Faibussowitsch } 308a4af0ceeSJacob Faibussowitsch 30917f48955SJacob Faibussowitsch template <DeviceType T> 31017f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DEFN(PetscErrorCode DeviceContext<T>::endTimer(PetscDeviceContext dctx, PetscLogDouble *elapsed)) 311a4af0ceeSJacob Faibussowitsch { 312a4af0ceeSJacob Faibussowitsch cupmError_t cerr; 313a4af0ceeSJacob Faibussowitsch float gtime; 31417f48955SJacob Faibussowitsch auto dci = impls_cast_(dctx); 315a4af0ceeSJacob Faibussowitsch 316a4af0ceeSJacob Faibussowitsch PetscFunctionBegin; 317a4af0ceeSJacob Faibussowitsch #if PetscDefined(USE_DEBUG) 318a4af0ceeSJacob Faibussowitsch if (PetscUnlikely(!dci->timerInUse)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Forgot to call PetscLogGpuTimeBegin()?"); 319a4af0ceeSJacob Faibussowitsch dci->timerInUse = PETSC_FALSE; 320a4af0ceeSJacob Faibussowitsch #endif 321a4af0ceeSJacob Faibussowitsch cerr = cupmEventRecord(dci->end,dci->stream);CHKERRCUPM(cerr); 322a4af0ceeSJacob Faibussowitsch cerr = cupmEventSynchronize(dci->end);CHKERRCUPM(cerr); 323a4af0ceeSJacob Faibussowitsch cerr = cupmEventElapsedTime(>ime,dci->begin,dci->end);CHKERRCUPM(cerr); 32417f48955SJacob Faibussowitsch *elapsed = static_cast<util::remove_pointer_t<decltype(elapsed)>>(gtime); 325a4af0ceeSJacob Faibussowitsch PetscFunctionReturn(0); 326a4af0ceeSJacob Faibussowitsch } 327a4af0ceeSJacob Faibussowitsch 328030f984aSJacob Faibussowitsch // initialize the static member variables 32917f48955SJacob Faibussowitsch template <DeviceType T> bool DeviceContext<T>::initialized_ = false; 330030f984aSJacob Faibussowitsch 33117f48955SJacob Faibussowitsch template <DeviceType T> 33217f48955SJacob Faibussowitsch std::array<typename DeviceContext<T>::cupmBlasHandle_t,PETSC_DEVICE_MAX_DEVICES> DeviceContext<T>::blashandles_ = {}; 333030f984aSJacob Faibussowitsch 33417f48955SJacob Faibussowitsch template <DeviceType T> 33517f48955SJacob Faibussowitsch std::array<typename DeviceContext<T>::cupmSolverHandle_t,PETSC_DEVICE_MAX_DEVICES> DeviceContext<T>::solverhandles_ = {}; 33617f48955SJacob Faibussowitsch 33717f48955SJacob Faibussowitsch } // namespace Impl 338030f984aSJacob Faibussowitsch 339a4af0ceeSJacob Faibussowitsch // shorten this one up a bit (and instantiate the templates) 34017f48955SJacob Faibussowitsch using CUPMContextCuda = Impl::DeviceContext<DeviceType::CUDA>; 34117f48955SJacob Faibussowitsch using CUPMContextHip = Impl::DeviceContext<DeviceType::HIP>; 342030f984aSJacob Faibussowitsch 343030f984aSJacob Faibussowitsch // shorthand for what is an EXTREMELY long name 34417f48955SJacob Faibussowitsch #define PetscDeviceContext_(IMPLS) Petsc::Device::CUPM::Impl::DeviceContext<Petsc::Device::CUPM::DeviceType::IMPLS>::PetscDeviceContext_IMPLS 345030f984aSJacob Faibussowitsch 34617f48955SJacob Faibussowitsch } // namespace CUPM 34717f48955SJacob Faibussowitsch 34817f48955SJacob Faibussowitsch } // namespace Device 34917f48955SJacob Faibussowitsch 35017f48955SJacob Faibussowitsch } // namespace Petsc 351030f984aSJacob Faibussowitsch 352a4af0ceeSJacob Faibussowitsch #endif // PETSCDEVICECONTEXTCUDA_HPP 353