1*17f48955SJacob Faibussowitsch #ifndef PETSCDEVICECONTEXTCUPM_HPP 2030f984aSJacob Faibussowitsch #define PETSCDEVICECONTEXTCUPM_HPP 3030f984aSJacob Faibussowitsch 4a4af0ceeSJacob Faibussowitsch #include <petsc/private/deviceimpl.h> 5*17f48955SJacob Faibussowitsch #include <petsc/private/cupmblasinterface.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 11a4af0ceeSJacob Faibussowitsch #include <array> 12a4af0ceeSJacob Faibussowitsch 13a4af0ceeSJacob Faibussowitsch namespace Petsc 14a4af0ceeSJacob Faibussowitsch { 15a4af0ceeSJacob Faibussowitsch 16*17f48955SJacob Faibussowitsch namespace Device 17*17f48955SJacob Faibussowitsch { 18*17f48955SJacob Faibussowitsch 19*17f48955SJacob Faibussowitsch namespace CUPM 20*17f48955SJacob Faibussowitsch { 21*17f48955SJacob Faibussowitsch 22*17f48955SJacob Faibussowitsch namespace Impl 23*17f48955SJacob Faibussowitsch { 24*17f48955SJacob Faibussowitsch 25a4af0ceeSJacob Faibussowitsch namespace detail 26a4af0ceeSJacob Faibussowitsch { 27a4af0ceeSJacob Faibussowitsch 28a4af0ceeSJacob Faibussowitsch // for tag-based dispatch of handle retrieval 29*17f48955SJacob Faibussowitsch template <typename T> struct HandleTag { using type = T; }; 30a4af0ceeSJacob Faibussowitsch 31a4af0ceeSJacob Faibussowitsch } // namespace detail 32030f984aSJacob Faibussowitsch 33030f984aSJacob Faibussowitsch // Forward declare 34*17f48955SJacob Faibussowitsch template <DeviceType T> class PETSC_VISIBILITY_INTERNAL DeviceContext; 35030f984aSJacob Faibussowitsch 36*17f48955SJacob Faibussowitsch template <DeviceType T> 37*17f48955SJacob Faibussowitsch class DeviceContext : Impl::BlasInterface<T> 38030f984aSJacob Faibussowitsch { 39*17f48955SJacob Faibussowitsch public: 40*17f48955SJacob Faibussowitsch PETSC_CUPMBLAS_INHERIT_INTERFACE_TYPEDEFS_USING(cupmBlasInterface_t,T); 41*17f48955SJacob Faibussowitsch 42*17f48955SJacob Faibussowitsch private: 43*17f48955SJacob Faibussowitsch template <typename H> using HandleTag = typename detail::HandleTag<H>; 44*17f48955SJacob Faibussowitsch using stream_tag = HandleTag<cupmStream_t>; 45*17f48955SJacob Faibussowitsch using blas_tag = HandleTag<cupmBlasHandle_t>; 46*17f48955SJacob Faibussowitsch using solver_tag = HandleTag<cupmSolverHandle_t>; 47a4af0ceeSJacob Faibussowitsch 48030f984aSJacob Faibussowitsch public: 49030f984aSJacob Faibussowitsch // This is the canonical PETSc "impls" struct that normally resides in a standalone impls 50030f984aSJacob Faibussowitsch // header, but since we are using the power of templates it must be declared part of 51030f984aSJacob Faibussowitsch // this class to have easy access the same typedefs. Technically one can make a 52030f984aSJacob Faibussowitsch // templated struct outside the class but it's more code for the same result. 53030f984aSJacob Faibussowitsch struct PetscDeviceContext_IMPLS 54030f984aSJacob Faibussowitsch { 55030f984aSJacob Faibussowitsch cupmStream_t stream; 56030f984aSJacob Faibussowitsch cupmEvent_t event; 57a4af0ceeSJacob Faibussowitsch cupmEvent_t begin; // timer-only 58a4af0ceeSJacob Faibussowitsch cupmEvent_t end; // timer-only 59a4af0ceeSJacob Faibussowitsch #if PetscDefined(USE_DEBUG) 60a4af0ceeSJacob Faibussowitsch PetscBool timerInUse; 61a4af0ceeSJacob Faibussowitsch #endif 62030f984aSJacob Faibussowitsch cupmBlasHandle_t blas; 63030f984aSJacob Faibussowitsch cupmSolverHandle_t solver; 64a4af0ceeSJacob Faibussowitsch 65*17f48955SJacob Faibussowitsch PETSC_NODISCARD auto get(stream_tag) const -> decltype(this->stream) { return this->stream; } 66*17f48955SJacob Faibussowitsch PETSC_NODISCARD auto get(blas_tag) const -> decltype(this->blas) { return this->blas; } 67*17f48955SJacob Faibussowitsch PETSC_NODISCARD auto get(solver_tag) const -> decltype(this->solver) { return this->solver; } 68030f984aSJacob Faibussowitsch }; 69030f984aSJacob Faibussowitsch 70030f984aSJacob Faibussowitsch private: 71*17f48955SJacob Faibussowitsch static bool initialized_; 72*17f48955SJacob Faibussowitsch static std::array<cupmBlasHandle_t,PETSC_DEVICE_MAX_DEVICES> blashandles_; 73*17f48955SJacob Faibussowitsch static std::array<cupmSolverHandle_t,PETSC_DEVICE_MAX_DEVICES> solverhandles_; 74030f984aSJacob Faibussowitsch 75*17f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DECL(constexpr PetscDeviceContext_IMPLS* impls_cast_(PetscDeviceContext ptr)) 76a4af0ceeSJacob Faibussowitsch { 77a4af0ceeSJacob Faibussowitsch return static_cast<PetscDeviceContext_IMPLS*>(ptr->data); 78a4af0ceeSJacob Faibussowitsch } 79a4af0ceeSJacob Faibussowitsch 80*17f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DECL(PetscErrorCode initialize_handle_(cupmBlasHandle_t &handle)) 81030f984aSJacob Faibussowitsch { 82030f984aSJacob Faibussowitsch PetscFunctionBegin; 83*17f48955SJacob Faibussowitsch if (handle) PetscFunctionReturn(0); 84*17f48955SJacob Faibussowitsch for (auto i = 0; i < 3; ++i) { 85*17f48955SJacob Faibussowitsch auto cberr = cupmBlasCreate(&handle); 86*17f48955SJacob Faibussowitsch if (PetscLikely(cberr == CUPMBLAS_STATUS_SUCCESS)) break; 87*17f48955SJacob Faibussowitsch if (PetscUnlikely(cberr != CUPMBLAS_STATUS_ALLOC_FAILED) && (cberr != CUPMBLAS_STATUS_NOT_INITIALIZED)) CHKERRCUPMBLAS(cberr); 88*17f48955SJacob Faibussowitsch if (i != 2) { 89*17f48955SJacob Faibussowitsch auto ierr = PetscSleep(3);CHKERRQ(ierr); 90*17f48955SJacob Faibussowitsch continue; 91a4af0ceeSJacob Faibussowitsch } 92*17f48955SJacob Faibussowitsch if (PetscUnlikely(cberr != CUPMBLAS_STATUS_SUCCESS)) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_GPU_RESOURCE,"Unable to initialize %s",cupmBlasName()); 93a4af0ceeSJacob Faibussowitsch } 94030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 95030f984aSJacob Faibussowitsch } 96030f984aSJacob Faibussowitsch 97*17f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DECL(PetscErrorCode set_handle_stream_(cupmBlasHandle_t &handle, cupmStream_t &stream)) 98*17f48955SJacob Faibussowitsch { 99*17f48955SJacob Faibussowitsch cupmStream_t cupmStream; 100*17f48955SJacob Faibussowitsch cupmBlasError_t cberr; 101*17f48955SJacob Faibussowitsch 102*17f48955SJacob Faibussowitsch PetscFunctionBegin; 103*17f48955SJacob Faibussowitsch cberr = cupmBlasGetStream(handle,&cupmStream);CHKERRCUPMBLAS(cberr); 104*17f48955SJacob Faibussowitsch if (cupmStream != stream) {cberr = cupmBlasSetStream(handle,stream);CHKERRCUPMBLAS(cberr);} 105*17f48955SJacob Faibussowitsch PetscFunctionReturn(0); 106*17f48955SJacob Faibussowitsch } 107*17f48955SJacob Faibussowitsch 108*17f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DECL(PetscErrorCode finalize_()) 109*17f48955SJacob Faibussowitsch { 110*17f48955SJacob Faibussowitsch PetscFunctionBegin; 111*17f48955SJacob Faibussowitsch for (auto&& handle : blashandles_) { 112*17f48955SJacob Faibussowitsch if (handle) { 113*17f48955SJacob Faibussowitsch auto cberr = cupmBlasDestroy(handle);CHKERRCUPMBLAS(cberr); 114*17f48955SJacob Faibussowitsch handle = nullptr; 115*17f48955SJacob Faibussowitsch } 116*17f48955SJacob Faibussowitsch } 117*17f48955SJacob Faibussowitsch for (auto&& handle : solverhandles_) { 118*17f48955SJacob Faibussowitsch if (handle) { 119*17f48955SJacob Faibussowitsch auto ierr = cupmBlasInterface_t::DestroyHandle(handle);CHKERRQ(ierr); 120*17f48955SJacob Faibussowitsch handle = nullptr; 121*17f48955SJacob Faibussowitsch } 122*17f48955SJacob Faibussowitsch } 123*17f48955SJacob Faibussowitsch initialized_ = false; 124*17f48955SJacob Faibussowitsch PetscFunctionReturn(0); 125*17f48955SJacob Faibussowitsch } 126*17f48955SJacob Faibussowitsch 127*17f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DECL(PetscErrorCode initialize_(PetscInt id, PetscDeviceContext_IMPLS *dci)) 128030f984aSJacob Faibussowitsch { 129030f984aSJacob Faibussowitsch PetscErrorCode ierr; 130030f984aSJacob Faibussowitsch 131030f984aSJacob Faibussowitsch PetscFunctionBegin; 132a4af0ceeSJacob Faibussowitsch ierr = PetscDeviceCheckDeviceCount_Internal(id);CHKERRQ(ierr); 133*17f48955SJacob Faibussowitsch if (!initialized_) { 134*17f48955SJacob Faibussowitsch initialized_ = true; 135*17f48955SJacob Faibussowitsch ierr = PetscRegisterFinalize(finalize_);CHKERRQ(ierr); 136030f984aSJacob Faibussowitsch } 137a4af0ceeSJacob Faibussowitsch // use the blashandle as a canary 138*17f48955SJacob Faibussowitsch if (!blashandles_[id]) { 139*17f48955SJacob Faibussowitsch ierr = initialize_handle_(blashandles_[id]);CHKERRQ(ierr); 140*17f48955SJacob Faibussowitsch ierr = cupmBlasInterface_t::InitializeHandle(solverhandles_[id]);CHKERRQ(ierr); 141030f984aSJacob Faibussowitsch } 142*17f48955SJacob Faibussowitsch ierr = set_handle_stream_(blashandles_[id],dci->stream);CHKERRQ(ierr); 143*17f48955SJacob Faibussowitsch ierr = cupmBlasInterface_t::SetHandleStream(solverhandles_[id],dci->stream);CHKERRQ(ierr); 144*17f48955SJacob Faibussowitsch dci->blas = blashandles_[id]; 145*17f48955SJacob Faibussowitsch dci->solver = solverhandles_[id]; 146030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 147030f984aSJacob Faibussowitsch } 148030f984aSJacob Faibussowitsch 149030f984aSJacob Faibussowitsch public: 150a4af0ceeSJacob Faibussowitsch const struct _DeviceContextOps ops = { 151a4af0ceeSJacob Faibussowitsch destroy, 152a4af0ceeSJacob Faibussowitsch changeStreamType, 153a4af0ceeSJacob Faibussowitsch setUp, 154a4af0ceeSJacob Faibussowitsch query, 155a4af0ceeSJacob Faibussowitsch waitForContext, 156a4af0ceeSJacob Faibussowitsch synchronize, 157*17f48955SJacob Faibussowitsch getHandle<blas_tag>, 158*17f48955SJacob Faibussowitsch getHandle<solver_tag>, 159*17f48955SJacob Faibussowitsch getHandle<stream_tag>, 160a4af0ceeSJacob Faibussowitsch beginTimer, 161*17f48955SJacob Faibussowitsch endTimer, 162a4af0ceeSJacob Faibussowitsch }; 163030f984aSJacob Faibussowitsch 164030f984aSJacob Faibussowitsch // All of these functions MUST be static in order to be callable from C, otherwise they 165030f984aSJacob Faibussowitsch // get the implicit 'this' pointer tacked on 166*17f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DECL(PetscErrorCode destroy(PetscDeviceContext)); 167*17f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DECL(PetscErrorCode changeStreamType(PetscDeviceContext,PetscStreamType)); 168*17f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DECL(PetscErrorCode setUp(PetscDeviceContext)); 169*17f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DECL(PetscErrorCode query(PetscDeviceContext,PetscBool*)); 170*17f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DECL(PetscErrorCode waitForContext(PetscDeviceContext,PetscDeviceContext)); 171*17f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DECL(PetscErrorCode synchronize(PetscDeviceContext)); 172a4af0ceeSJacob Faibussowitsch template <typename Handle_t> 173*17f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DECL(PetscErrorCode getHandle(PetscDeviceContext,void*)); 174*17f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DECL(PetscErrorCode beginTimer(PetscDeviceContext)); 175*17f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DECL(PetscErrorCode endTimer(PetscDeviceContext,PetscLogDouble*)); 176030f984aSJacob Faibussowitsch }; 177030f984aSJacob Faibussowitsch 178*17f48955SJacob Faibussowitsch template <DeviceType T> 179*17f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DEFN(PetscErrorCode DeviceContext<T>::destroy(PetscDeviceContext dctx)) 180030f984aSJacob Faibussowitsch { 181030f984aSJacob Faibussowitsch cupmError_t cerr; 182030f984aSJacob Faibussowitsch PetscErrorCode ierr; 183*17f48955SJacob Faibussowitsch auto dci = impls_cast_(dctx); 184030f984aSJacob Faibussowitsch 185030f984aSJacob Faibussowitsch PetscFunctionBegin; 186030f984aSJacob Faibussowitsch if (dci->stream) {cerr = cupmStreamDestroy(dci->stream);CHKERRCUPM(cerr);} 187*17f48955SJacob Faibussowitsch if (dci->event) {cerr = cupmEventDestroy(dci->event);CHKERRCUPM(cerr); } 188*17f48955SJacob Faibussowitsch if (dci->begin) {cerr = cupmEventDestroy(dci->begin);CHKERRCUPM(cerr); } 189*17f48955SJacob Faibussowitsch if (dci->end) {cerr = cupmEventDestroy(dci->end);CHKERRCUPM(cerr); } 190030f984aSJacob Faibussowitsch ierr = PetscFree(dctx->data);CHKERRQ(ierr); 191030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 192030f984aSJacob Faibussowitsch } 193030f984aSJacob Faibussowitsch 194*17f48955SJacob Faibussowitsch template <DeviceType T> 195*17f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DEFN(PetscErrorCode DeviceContext<T>::changeStreamType(PetscDeviceContext dctx, PETSC_UNUSED PetscStreamType stype)) 196030f984aSJacob Faibussowitsch { 197*17f48955SJacob Faibussowitsch auto dci = impls_cast_(dctx); 198030f984aSJacob Faibussowitsch 199030f984aSJacob Faibussowitsch PetscFunctionBegin; 200030f984aSJacob Faibussowitsch if (dci->stream) { 201*17f48955SJacob Faibussowitsch auto cerr = cupmStreamDestroy(dci->stream);CHKERRCUPM(cerr); 202030f984aSJacob Faibussowitsch dci->stream = nullptr; 203030f984aSJacob Faibussowitsch } 204030f984aSJacob Faibussowitsch // set these to null so they aren't usable until setup is called again 205030f984aSJacob Faibussowitsch dci->blas = nullptr; 206030f984aSJacob Faibussowitsch dci->solver = nullptr; 207030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 208030f984aSJacob Faibussowitsch } 209030f984aSJacob Faibussowitsch 210*17f48955SJacob Faibussowitsch template <DeviceType T> 211*17f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DEFN(PetscErrorCode DeviceContext<T>::setUp(PetscDeviceContext dctx)) 212030f984aSJacob Faibussowitsch { 213030f984aSJacob Faibussowitsch PetscErrorCode ierr; 214030f984aSJacob Faibussowitsch cupmError_t cerr; 215*17f48955SJacob Faibussowitsch auto dci = impls_cast_(dctx); 216030f984aSJacob Faibussowitsch 217030f984aSJacob Faibussowitsch PetscFunctionBegin; 218*17f48955SJacob Faibussowitsch if (dci->stream) { 219*17f48955SJacob Faibussowitsch cerr = cupmStreamDestroy(dci->stream);CHKERRCUPM(cerr); 220*17f48955SJacob Faibussowitsch dci->stream = nullptr; 221*17f48955SJacob Faibussowitsch } 222030f984aSJacob Faibussowitsch switch (dctx->streamType) { 223030f984aSJacob Faibussowitsch case PETSC_STREAM_GLOBAL_BLOCKING: 224030f984aSJacob Faibussowitsch // don't create a stream for global blocking 225030f984aSJacob Faibussowitsch break; 226030f984aSJacob Faibussowitsch case PETSC_STREAM_DEFAULT_BLOCKING: 227030f984aSJacob Faibussowitsch cerr = cupmStreamCreate(&dci->stream);CHKERRCUPM(cerr); 228030f984aSJacob Faibussowitsch break; 229030f984aSJacob Faibussowitsch case PETSC_STREAM_GLOBAL_NONBLOCKING: 230030f984aSJacob Faibussowitsch cerr = cupmStreamCreateWithFlags(&dci->stream,cupmStreamNonBlocking);CHKERRCUPM(cerr); 231030f984aSJacob Faibussowitsch break; 232030f984aSJacob Faibussowitsch default: 233*17f48955SJacob Faibussowitsch SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_CORRUPT,"Invalid PetscStreamType %s",PetscStreamTypes[util::integral_value(dctx->streamType)]); 234030f984aSJacob Faibussowitsch break; 235030f984aSJacob Faibussowitsch } 236*17f48955SJacob Faibussowitsch if (!dci->event) {cerr = cupmEventCreate(&dci->event);CHKERRCUPM(cerr);} 237a4af0ceeSJacob Faibussowitsch #if PetscDefined(USE_DEBUG) 238a4af0ceeSJacob Faibussowitsch dci->timerInUse = PETSC_FALSE; 239a4af0ceeSJacob Faibussowitsch #endif 240*17f48955SJacob Faibussowitsch ierr = initialize_(dctx->device->deviceId,dci);CHKERRQ(ierr); 241030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 242030f984aSJacob Faibussowitsch } 243030f984aSJacob Faibussowitsch 244*17f48955SJacob Faibussowitsch template <DeviceType T> 245*17f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DEFN(PetscErrorCode DeviceContext<T>::query(PetscDeviceContext dctx, PetscBool *idle)) 246030f984aSJacob Faibussowitsch { 247030f984aSJacob Faibussowitsch cupmError_t cerr; 248030f984aSJacob Faibussowitsch 249030f984aSJacob Faibussowitsch PetscFunctionBegin; 250*17f48955SJacob Faibussowitsch cerr = cupmStreamQuery(impls_cast_(dctx)->stream); 251a4af0ceeSJacob Faibussowitsch if (cerr == cupmSuccess) *idle = PETSC_TRUE; 252a4af0ceeSJacob Faibussowitsch else { 253030f984aSJacob Faibussowitsch // somethings gone wrong 254a4af0ceeSJacob Faibussowitsch if (PetscUnlikely(cerr != cupmErrorNotReady)) CHKERRCUPM(cerr); 255a4af0ceeSJacob Faibussowitsch *idle = PETSC_FALSE; 256030f984aSJacob Faibussowitsch } 257030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 258030f984aSJacob Faibussowitsch } 259030f984aSJacob Faibussowitsch 260*17f48955SJacob Faibussowitsch template <DeviceType T> 261*17f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DEFN(PetscErrorCode DeviceContext<T>::waitForContext(PetscDeviceContext dctxa, PetscDeviceContext dctxb)) 262030f984aSJacob Faibussowitsch { 263030f984aSJacob Faibussowitsch cupmError_t cerr; 264*17f48955SJacob Faibussowitsch auto dcib = impls_cast_(dctxb); 265030f984aSJacob Faibussowitsch 266030f984aSJacob Faibussowitsch PetscFunctionBegin; 267030f984aSJacob Faibussowitsch cerr = cupmEventRecord(dcib->event,dcib->stream);CHKERRCUPM(cerr); 268*17f48955SJacob Faibussowitsch cerr = cupmStreamWaitEvent(impls_cast_(dctxa)->stream,dcib->event,0);CHKERRCUPM(cerr); 269030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 270030f984aSJacob Faibussowitsch } 271030f984aSJacob Faibussowitsch 272*17f48955SJacob Faibussowitsch template <DeviceType T> 273*17f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DEFN(PetscErrorCode DeviceContext<T>::synchronize(PetscDeviceContext dctx)) 274030f984aSJacob Faibussowitsch { 275030f984aSJacob Faibussowitsch cupmError_t cerr; 276*17f48955SJacob Faibussowitsch auto dci = impls_cast_(dctx); 277030f984aSJacob Faibussowitsch 278030f984aSJacob Faibussowitsch PetscFunctionBegin; 279030f984aSJacob Faibussowitsch // in case anything was queued on the event 280030f984aSJacob Faibussowitsch cerr = cupmStreamWaitEvent(dci->stream,dci->event,0);CHKERRCUPM(cerr); 281030f984aSJacob Faibussowitsch cerr = cupmStreamSynchronize(dci->stream);CHKERRCUPM(cerr); 282030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 283030f984aSJacob Faibussowitsch } 284030f984aSJacob Faibussowitsch 285*17f48955SJacob Faibussowitsch template <DeviceType T> 286*17f48955SJacob Faibussowitsch template <typename handle_t> 287*17f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DEFN(PetscErrorCode DeviceContext<T>::getHandle(PetscDeviceContext dctx, void *handle)) 288a4af0ceeSJacob Faibussowitsch { 289a4af0ceeSJacob Faibussowitsch PetscFunctionBegin; 290*17f48955SJacob Faibussowitsch *static_cast<typename handle_t::type*>(handle) = impls_cast_(dctx)->get(handle_t()); 291a4af0ceeSJacob Faibussowitsch PetscFunctionReturn(0); 292a4af0ceeSJacob Faibussowitsch } 293a4af0ceeSJacob Faibussowitsch 294*17f48955SJacob Faibussowitsch template <DeviceType T> 295*17f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DEFN(PetscErrorCode DeviceContext<T>::beginTimer(PetscDeviceContext dctx)) 296a4af0ceeSJacob Faibussowitsch { 297*17f48955SJacob Faibussowitsch auto dci = impls_cast_(dctx); 298a4af0ceeSJacob Faibussowitsch cupmError_t cerr; 299a4af0ceeSJacob Faibussowitsch 300a4af0ceeSJacob Faibussowitsch PetscFunctionBegin; 301a4af0ceeSJacob Faibussowitsch #if PetscDefined(USE_DEBUG) 302a4af0ceeSJacob Faibussowitsch if (PetscUnlikely(dci->timerInUse)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Forgot to call PetscLogGpuTimeEnd()?"); 303a4af0ceeSJacob Faibussowitsch dci->timerInUse = PETSC_TRUE; 304a4af0ceeSJacob Faibussowitsch #endif 305*17f48955SJacob Faibussowitsch if (!dci->begin) { 306*17f48955SJacob Faibussowitsch cerr = cupmEventCreate(&dci->begin);CHKERRCUPM(cerr); 307*17f48955SJacob Faibussowitsch cerr = cupmEventCreate(&dci->end);CHKERRCUPM(cerr); 308*17f48955SJacob Faibussowitsch } 309a4af0ceeSJacob Faibussowitsch cerr = cupmEventRecord(dci->begin,dci->stream);CHKERRCUPM(cerr); 310a4af0ceeSJacob Faibussowitsch PetscFunctionReturn(0); 311a4af0ceeSJacob Faibussowitsch } 312a4af0ceeSJacob Faibussowitsch 313*17f48955SJacob Faibussowitsch template <DeviceType T> 314*17f48955SJacob Faibussowitsch PETSC_CXX_COMPAT_DEFN(PetscErrorCode DeviceContext<T>::endTimer(PetscDeviceContext dctx, PetscLogDouble *elapsed)) 315a4af0ceeSJacob Faibussowitsch { 316a4af0ceeSJacob Faibussowitsch cupmError_t cerr; 317a4af0ceeSJacob Faibussowitsch float gtime; 318*17f48955SJacob Faibussowitsch auto dci = impls_cast_(dctx); 319a4af0ceeSJacob Faibussowitsch 320a4af0ceeSJacob Faibussowitsch PetscFunctionBegin; 321a4af0ceeSJacob Faibussowitsch #if PetscDefined(USE_DEBUG) 322a4af0ceeSJacob Faibussowitsch if (PetscUnlikely(!dci->timerInUse)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Forgot to call PetscLogGpuTimeBegin()?"); 323a4af0ceeSJacob Faibussowitsch dci->timerInUse = PETSC_FALSE; 324a4af0ceeSJacob Faibussowitsch #endif 325a4af0ceeSJacob Faibussowitsch cerr = cupmEventRecord(dci->end,dci->stream);CHKERRCUPM(cerr); 326a4af0ceeSJacob Faibussowitsch cerr = cupmEventSynchronize(dci->end);CHKERRCUPM(cerr); 327a4af0ceeSJacob Faibussowitsch cerr = cupmEventElapsedTime(>ime,dci->begin,dci->end);CHKERRCUPM(cerr); 328*17f48955SJacob Faibussowitsch *elapsed = static_cast<util::remove_pointer_t<decltype(elapsed)>>(gtime); 329a4af0ceeSJacob Faibussowitsch PetscFunctionReturn(0); 330a4af0ceeSJacob Faibussowitsch } 331a4af0ceeSJacob Faibussowitsch 332030f984aSJacob Faibussowitsch // initialize the static member variables 333*17f48955SJacob Faibussowitsch template <DeviceType T> bool DeviceContext<T>::initialized_ = false; 334030f984aSJacob Faibussowitsch 335*17f48955SJacob Faibussowitsch template <DeviceType T> 336*17f48955SJacob Faibussowitsch std::array<typename DeviceContext<T>::cupmBlasHandle_t,PETSC_DEVICE_MAX_DEVICES> DeviceContext<T>::blashandles_ = {}; 337030f984aSJacob Faibussowitsch 338*17f48955SJacob Faibussowitsch template <DeviceType T> 339*17f48955SJacob Faibussowitsch std::array<typename DeviceContext<T>::cupmSolverHandle_t,PETSC_DEVICE_MAX_DEVICES> DeviceContext<T>::solverhandles_ = {}; 340*17f48955SJacob Faibussowitsch 341*17f48955SJacob Faibussowitsch } // namespace Impl 342030f984aSJacob Faibussowitsch 343a4af0ceeSJacob Faibussowitsch // shorten this one up a bit (and instantiate the templates) 344*17f48955SJacob Faibussowitsch using CUPMContextCuda = Impl::DeviceContext<DeviceType::CUDA>; 345*17f48955SJacob Faibussowitsch using CUPMContextHip = Impl::DeviceContext<DeviceType::HIP>; 346030f984aSJacob Faibussowitsch 347030f984aSJacob Faibussowitsch // shorthand for what is an EXTREMELY long name 348*17f48955SJacob Faibussowitsch #define PetscDeviceContext_(IMPLS) Petsc::Device::CUPM::Impl::DeviceContext<Petsc::Device::CUPM::DeviceType::IMPLS>::PetscDeviceContext_IMPLS 349030f984aSJacob Faibussowitsch 350*17f48955SJacob Faibussowitsch } // namespace CUPM 351*17f48955SJacob Faibussowitsch 352*17f48955SJacob Faibussowitsch } // namespace Device 353*17f48955SJacob Faibussowitsch 354*17f48955SJacob Faibussowitsch } // namespace Petsc 355030f984aSJacob Faibussowitsch 356a4af0ceeSJacob Faibussowitsch #endif // PETSCDEVICECONTEXTCUDA_HPP 357