xref: /petsc/src/sys/objects/device/impls/cupm/cupmcontext.hpp (revision 9371c9d470a9602b6d10a8bf50c9b2280a79e45a)
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(&gtime, 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