117f48955SJacob Faibussowitsch #ifndef PETSCDEVICECONTEXTCUPM_HPP 2030f984aSJacob Faibussowitsch #define PETSCDEVICECONTEXTCUPM_HPP 3030f984aSJacob Faibussowitsch 4a4af0ceeSJacob Faibussowitsch #include <petsc/private/deviceimpl.h> 596a4b4d9SJacob Faibussowitsch #include <petsc/private/cupmsolverinterface.hpp> 67a101e5eSJacob Faibussowitsch #include <petsc/private/logimpl.h> 7030f984aSJacob Faibussowitsch 80e6b6b59SJacob Faibussowitsch #include <petsc/private/cpp/array.hpp> 9a4af0ceeSJacob Faibussowitsch 100e6b6b59SJacob Faibussowitsch #include "../segmentedmempool.hpp" 110e6b6b59SJacob Faibussowitsch #include "cupmallocator.hpp" 120e6b6b59SJacob Faibussowitsch #include "cupmstream.hpp" 130e6b6b59SJacob Faibussowitsch #include "cupmevent.hpp" 140e6b6b59SJacob Faibussowitsch 150e6b6b59SJacob Faibussowitsch #if defined(__cplusplus) 166797ed33SJacob Faibussowitsch 17d71ae5a4SJacob Faibussowitsch namespace Petsc 18d71ae5a4SJacob Faibussowitsch { 19a4af0ceeSJacob Faibussowitsch 20d71ae5a4SJacob Faibussowitsch namespace device 21d71ae5a4SJacob Faibussowitsch { 2217f48955SJacob Faibussowitsch 23d71ae5a4SJacob Faibussowitsch namespace cupm 24d71ae5a4SJacob Faibussowitsch { 2517f48955SJacob Faibussowitsch 26d71ae5a4SJacob Faibussowitsch namespace impl 27d71ae5a4SJacob Faibussowitsch { 28030f984aSJacob Faibussowitsch 2917f48955SJacob Faibussowitsch template <DeviceType T> 3096a4b4d9SJacob Faibussowitsch class DeviceContext : SolverInterface<T> { 3117f48955SJacob Faibussowitsch public: 3296a4b4d9SJacob Faibussowitsch PETSC_CUPMSOLVER_INHERIT_INTERFACE_TYPEDEFS_USING(T); 3317f48955SJacob Faibussowitsch 3417f48955SJacob Faibussowitsch private: 359371c9d4SSatish Balay template <typename H, std::size_t> 369371c9d4SSatish Balay struct HandleTag { 379371c9d4SSatish Balay using type = H; 389371c9d4SSatish Balay }; 390e6b6b59SJacob Faibussowitsch 407a101e5eSJacob Faibussowitsch using stream_tag = HandleTag<cupmStream_t, 0>; 417a101e5eSJacob Faibussowitsch using blas_tag = HandleTag<cupmBlasHandle_t, 1>; 427a101e5eSJacob Faibussowitsch using solver_tag = HandleTag<cupmSolverHandle_t, 2>; 43a4af0ceeSJacob Faibussowitsch 440e6b6b59SJacob Faibussowitsch using stream_type = CUPMStream<T>; 450e6b6b59SJacob Faibussowitsch using event_type = CUPMEvent<T>; 460e6b6b59SJacob Faibussowitsch 47030f984aSJacob Faibussowitsch public: 48030f984aSJacob Faibussowitsch // This is the canonical PETSc "impls" struct that normally resides in a standalone impls 49030f984aSJacob Faibussowitsch // header, but since we are using the power of templates it must be declared part of 50030f984aSJacob Faibussowitsch // this class to have easy access the same typedefs. Technically one can make a 51030f984aSJacob Faibussowitsch // templated struct outside the class but it's more code for the same result. 520e6b6b59SJacob Faibussowitsch struct PetscDeviceContext_IMPLS : memory::PoolAllocated<PetscDeviceContext_IMPLS> { 530e6b6b59SJacob Faibussowitsch stream_type stream{}; 540e6b6b59SJacob Faibussowitsch cupmEvent_t event{}; 550e6b6b59SJacob Faibussowitsch cupmEvent_t begin{}; // timer-only 560e6b6b59SJacob Faibussowitsch cupmEvent_t end{}; // timer-only 57a4af0ceeSJacob Faibussowitsch #if PetscDefined(USE_DEBUG) 580e6b6b59SJacob Faibussowitsch PetscBool timerInUse{}; 59a4af0ceeSJacob Faibussowitsch #endif 600e6b6b59SJacob Faibussowitsch cupmBlasHandle_t blas{}; 610e6b6b59SJacob Faibussowitsch cupmSolverHandle_t solver{}; 62a4af0ceeSJacob Faibussowitsch 630e6b6b59SJacob Faibussowitsch constexpr PetscDeviceContext_IMPLS() noexcept = default; 640e6b6b59SJacob Faibussowitsch 65*31d47070SJunchao Zhang PETSC_NODISCARD const cupmStream_t &get(stream_tag) const noexcept { return this->stream.get_stream(); } 660e6b6b59SJacob Faibussowitsch 67*31d47070SJunchao Zhang PETSC_NODISCARD const cupmBlasHandle_t &get(blas_tag) const noexcept { return this->blas; } 680e6b6b59SJacob Faibussowitsch 69*31d47070SJunchao Zhang PETSC_NODISCARD const cupmSolverHandle_t &get(solver_tag) const noexcept { return this->solver; } 70030f984aSJacob Faibussowitsch }; 71030f984aSJacob Faibussowitsch 72030f984aSJacob Faibussowitsch private: 7317f48955SJacob Faibussowitsch static bool initialized_; 746d54fb17SJacob Faibussowitsch 7517f48955SJacob Faibussowitsch static std::array<cupmBlasHandle_t, PETSC_DEVICE_MAX_DEVICES> blashandles_; 7617f48955SJacob Faibussowitsch static std::array<cupmSolverHandle_t, PETSC_DEVICE_MAX_DEVICES> solverhandles_; 77030f984aSJacob Faibussowitsch 78d71ae5a4SJacob Faibussowitsch PETSC_NODISCARD static constexpr PetscDeviceContext_IMPLS *impls_cast_(PetscDeviceContext ptr) noexcept { return static_cast<PetscDeviceContext_IMPLS *>(ptr->data); } 79a4af0ceeSJacob Faibussowitsch 80d71ae5a4SJacob Faibussowitsch PETSC_NODISCARD static constexpr CUPMEvent<T> *event_cast_(PetscEvent event) noexcept { return static_cast<CUPMEvent<T> *>(event->data); } 810e6b6b59SJacob Faibussowitsch 82d71ae5a4SJacob Faibussowitsch PETSC_NODISCARD static PetscLogEvent CUPMBLAS_HANDLE_CREATE() noexcept { return T == DeviceType::CUDA ? CUBLAS_HANDLE_CREATE : HIPBLAS_HANDLE_CREATE; } 837a101e5eSJacob Faibussowitsch 84d71ae5a4SJacob Faibussowitsch PETSC_NODISCARD static PetscLogEvent CUPMSOLVER_HANDLE_CREATE() noexcept { return T == DeviceType::CUDA ? CUSOLVER_HANDLE_CREATE : HIPSOLVER_HANDLE_CREATE; } 857a101e5eSJacob Faibussowitsch 867a101e5eSJacob Faibussowitsch // this exists purely to satisfy the compiler so the tag-based dispatch works for the other 877a101e5eSJacob Faibussowitsch // handles 88089fb57cSJacob Faibussowitsch static PetscErrorCode initialize_handle_(stream_tag, PetscDeviceContext) noexcept { return PETSC_SUCCESS; } 897a101e5eSJacob Faibussowitsch 9096a4b4d9SJacob Faibussowitsch static PetscErrorCode initialize_handle_(blas_tag, PetscDeviceContext dctx) noexcept 91d71ae5a4SJacob Faibussowitsch { 9296a4b4d9SJacob Faibussowitsch const auto dci = impls_cast_(dctx); 9396a4b4d9SJacob Faibussowitsch auto &handle = blashandles_[dctx->device->deviceId]; 947a101e5eSJacob Faibussowitsch 95030f984aSJacob Faibussowitsch PetscFunctionBegin; 9696a4b4d9SJacob Faibussowitsch if (!handle) { 9796a4b4d9SJacob Faibussowitsch PetscLogEvent event; 9896a4b4d9SJacob Faibussowitsch 997a101e5eSJacob Faibussowitsch PetscCall(PetscLogPauseCurrentEvent_Internal(&event)); 1007a101e5eSJacob Faibussowitsch PetscCall(PetscLogEventBegin(CUPMBLAS_HANDLE_CREATE(), 0, 0, 0, 0)); 10117f48955SJacob Faibussowitsch for (auto i = 0; i < 3; ++i) { 10296a4b4d9SJacob Faibussowitsch const auto cberr = cupmBlasCreate(handle.ptr_to()); 10317f48955SJacob Faibussowitsch if (PetscLikely(cberr == CUPMBLAS_STATUS_SUCCESS)) break; 1049566063dSJacob Faibussowitsch if (PetscUnlikely(cberr != CUPMBLAS_STATUS_ALLOC_FAILED) && (cberr != CUPMBLAS_STATUS_NOT_INITIALIZED)) PetscCallCUPMBLAS(cberr); 10517f48955SJacob Faibussowitsch if (i != 2) { 1069566063dSJacob Faibussowitsch PetscCall(PetscSleep(3)); 10717f48955SJacob Faibussowitsch continue; 108a4af0ceeSJacob Faibussowitsch } 1095f80ce2aSJacob Faibussowitsch PetscCheck(cberr == CUPMBLAS_STATUS_SUCCESS, PETSC_COMM_SELF, PETSC_ERR_GPU_RESOURCE, "Unable to initialize %s", cupmBlasName()); 110a4af0ceeSJacob Faibussowitsch } 1117a101e5eSJacob Faibussowitsch PetscCall(PetscLogEventEnd(CUPMBLAS_HANDLE_CREATE(), 0, 0, 0, 0)); 1127a101e5eSJacob Faibussowitsch PetscCall(PetscLogEventResume_Internal(event)); 113030f984aSJacob Faibussowitsch } 1140e6b6b59SJacob Faibussowitsch PetscCallCUPMBLAS(cupmBlasSetStream(handle, dci->stream.get_stream())); 1157a101e5eSJacob Faibussowitsch dci->blas = handle; 1163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1177a101e5eSJacob Faibussowitsch } 1187a101e5eSJacob Faibussowitsch 119089fb57cSJacob Faibussowitsch static PetscErrorCode initialize_handle_(solver_tag, PetscDeviceContext dctx) noexcept 120d71ae5a4SJacob Faibussowitsch { 1216d54fb17SJacob Faibussowitsch const auto dci = impls_cast_(dctx); 1226d54fb17SJacob Faibussowitsch auto &handle = solverhandles_[dctx->device->deviceId]; 1237a101e5eSJacob Faibussowitsch 1247a101e5eSJacob Faibussowitsch PetscFunctionBegin; 12596a4b4d9SJacob Faibussowitsch if (!handle) { 12696a4b4d9SJacob Faibussowitsch PetscLogEvent event; 12796a4b4d9SJacob Faibussowitsch 1287a101e5eSJacob Faibussowitsch PetscCall(PetscLogPauseCurrentEvent_Internal(&event)); 1297a101e5eSJacob Faibussowitsch PetscCall(PetscLogEventBegin(CUPMSOLVER_HANDLE_CREATE(), 0, 0, 0, 0)); 13096a4b4d9SJacob Faibussowitsch for (auto i = 0; i < 3; ++i) { 13196a4b4d9SJacob Faibussowitsch const auto cerr = cupmSolverCreate(&handle); 13296a4b4d9SJacob Faibussowitsch if (PetscLikely(cerr == CUPMSOLVER_STATUS_SUCCESS)) break; 13396a4b4d9SJacob Faibussowitsch if ((cerr != CUPMSOLVER_STATUS_NOT_INITIALIZED) && (cerr != CUPMSOLVER_STATUS_ALLOC_FAILED)) PetscCallCUPMSOLVER(cerr); 13496a4b4d9SJacob Faibussowitsch if (i < 2) { 13596a4b4d9SJacob Faibussowitsch PetscCall(PetscSleep(3)); 13696a4b4d9SJacob Faibussowitsch continue; 13796a4b4d9SJacob Faibussowitsch } 13896a4b4d9SJacob Faibussowitsch PetscCheck(cerr == CUPMSOLVER_STATUS_SUCCESS, PETSC_COMM_SELF, PETSC_ERR_GPU_RESOURCE, "Unable to initialize %s", cupmSolverName()); 13996a4b4d9SJacob Faibussowitsch } 1407a101e5eSJacob Faibussowitsch PetscCall(PetscLogEventEnd(CUPMSOLVER_HANDLE_CREATE(), 0, 0, 0, 0)); 1417a101e5eSJacob Faibussowitsch PetscCall(PetscLogEventResume_Internal(event)); 14296a4b4d9SJacob Faibussowitsch } 14396a4b4d9SJacob Faibussowitsch PetscCallCUPMSOLVER(cupmSolverSetStream(handle, dci->stream.get_stream())); 1447a101e5eSJacob Faibussowitsch dci->solver = handle; 1453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 14617f48955SJacob Faibussowitsch } 14717f48955SJacob Faibussowitsch 148089fb57cSJacob Faibussowitsch static PetscErrorCode check_current_device_(PetscDeviceContext dctxl, PetscDeviceContext dctxr) noexcept 149d71ae5a4SJacob Faibussowitsch { 1500e6b6b59SJacob Faibussowitsch const auto devidl = dctxl->device->deviceId, devidr = dctxr->device->deviceId; 1510e6b6b59SJacob Faibussowitsch 1520e6b6b59SJacob Faibussowitsch PetscFunctionBegin; 1530e6b6b59SJacob Faibussowitsch PetscCheck(devidl == devidr, PETSC_COMM_SELF, PETSC_ERR_GPU, "Device contexts must be on the same device; dctx A (id %" PetscInt64_FMT " device id %" PetscInt_FMT ") dctx B (id %" PetscInt64_FMT " device id %" PetscInt_FMT ")", 1540e6b6b59SJacob Faibussowitsch PetscObjectCast(dctxl)->id, devidl, PetscObjectCast(dctxr)->id, devidr); 1550e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceCheckDeviceCount_Internal(devidl)); 1560e6b6b59SJacob Faibussowitsch PetscCall(PetscDeviceCheckDeviceCount_Internal(devidr)); 1570e6b6b59SJacob Faibussowitsch PetscCallCUPM(cupmSetDevice(static_cast<int>(devidl))); 1583ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1590e6b6b59SJacob Faibussowitsch } 1600e6b6b59SJacob Faibussowitsch 161089fb57cSJacob Faibussowitsch static PetscErrorCode check_current_device_(PetscDeviceContext dctx) noexcept { return check_current_device_(dctx, dctx); } 1620e6b6b59SJacob Faibussowitsch 163089fb57cSJacob Faibussowitsch static PetscErrorCode finalize_() noexcept 164d71ae5a4SJacob Faibussowitsch { 16517f48955SJacob Faibussowitsch PetscFunctionBegin; 16617f48955SJacob Faibussowitsch for (auto &&handle : blashandles_) { 16717f48955SJacob Faibussowitsch if (handle) { 1689566063dSJacob Faibussowitsch PetscCallCUPMBLAS(cupmBlasDestroy(handle)); 16917f48955SJacob Faibussowitsch handle = nullptr; 17017f48955SJacob Faibussowitsch } 17117f48955SJacob Faibussowitsch } 1726d54fb17SJacob Faibussowitsch 17317f48955SJacob Faibussowitsch for (auto &&handle : solverhandles_) { 17417f48955SJacob Faibussowitsch if (handle) { 17596a4b4d9SJacob Faibussowitsch PetscCallCUPMSOLVER(cupmSolverDestroy(handle)); 17617f48955SJacob Faibussowitsch handle = nullptr; 17717f48955SJacob Faibussowitsch } 17817f48955SJacob Faibussowitsch } 17917f48955SJacob Faibussowitsch initialized_ = false; 1803ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 18117f48955SJacob Faibussowitsch } 18217f48955SJacob Faibussowitsch 1830e6b6b59SJacob Faibussowitsch template <typename Allocator, typename PoolType = ::Petsc::memory::SegmentedMemoryPool<typename Allocator::value_type, stream_type, Allocator, 256 * sizeof(PetscScalar)>> 184d71ae5a4SJacob Faibussowitsch PETSC_NODISCARD static PoolType &default_pool_() noexcept 185d71ae5a4SJacob Faibussowitsch { 1860e6b6b59SJacob Faibussowitsch static PoolType pool; 1870e6b6b59SJacob Faibussowitsch return pool; 1880e6b6b59SJacob Faibussowitsch } 189030f984aSJacob Faibussowitsch 190089fb57cSJacob Faibussowitsch static PetscErrorCode check_memtype_(PetscMemType mtype, const char mess[]) noexcept 191d71ae5a4SJacob Faibussowitsch { 1920e6b6b59SJacob Faibussowitsch PetscFunctionBegin; 1930e6b6b59SJacob Faibussowitsch PetscCheck(PetscMemTypeHost(mtype) || (mtype == PETSC_MEMTYPE_DEVICE) || (mtype == PETSC_MEMTYPE_CUPM()), PETSC_COMM_SELF, PETSC_ERR_SUP, "%s device context can only handle %s (pinned) host or device memory", cupmName(), mess); 1943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1950e6b6b59SJacob Faibussowitsch } 1960e6b6b59SJacob Faibussowitsch 1970e6b6b59SJacob Faibussowitsch public: 198030f984aSJacob Faibussowitsch // All of these functions MUST be static in order to be callable from C, otherwise they 199030f984aSJacob Faibussowitsch // get the implicit 'this' pointer tacked on 200089fb57cSJacob Faibussowitsch static PetscErrorCode destroy(PetscDeviceContext) noexcept; 201089fb57cSJacob Faibussowitsch static PetscErrorCode changeStreamType(PetscDeviceContext, PetscStreamType) noexcept; 202089fb57cSJacob Faibussowitsch static PetscErrorCode setUp(PetscDeviceContext) noexcept; 203089fb57cSJacob Faibussowitsch static PetscErrorCode query(PetscDeviceContext, PetscBool *) noexcept; 204089fb57cSJacob Faibussowitsch static PetscErrorCode waitForContext(PetscDeviceContext, PetscDeviceContext) noexcept; 205089fb57cSJacob Faibussowitsch static PetscErrorCode synchronize(PetscDeviceContext) noexcept; 206a4af0ceeSJacob Faibussowitsch template <typename Handle_t> 207089fb57cSJacob Faibussowitsch static PetscErrorCode getHandle(PetscDeviceContext, void *) noexcept; 208*31d47070SJunchao Zhang template <typename Handle_t> 209*31d47070SJunchao Zhang static PetscErrorCode getHandlePtr(PetscDeviceContext, void *) noexcept; 210089fb57cSJacob Faibussowitsch static PetscErrorCode beginTimer(PetscDeviceContext) noexcept; 211089fb57cSJacob Faibussowitsch static PetscErrorCode endTimer(PetscDeviceContext, PetscLogDouble *) noexcept; 212089fb57cSJacob Faibussowitsch static PetscErrorCode memAlloc(PetscDeviceContext, PetscBool, PetscMemType, std::size_t, std::size_t, void **) noexcept; 213089fb57cSJacob Faibussowitsch static PetscErrorCode memFree(PetscDeviceContext, PetscMemType, void **) noexcept; 214089fb57cSJacob Faibussowitsch static PetscErrorCode memCopy(PetscDeviceContext, void *PETSC_RESTRICT, const void *PETSC_RESTRICT, std::size_t, PetscDeviceCopyMode) noexcept; 215089fb57cSJacob Faibussowitsch static PetscErrorCode memSet(PetscDeviceContext, PetscMemType, void *, PetscInt, std::size_t) noexcept; 216089fb57cSJacob Faibussowitsch static PetscErrorCode createEvent(PetscDeviceContext, PetscEvent) noexcept; 217089fb57cSJacob Faibussowitsch static PetscErrorCode recordEvent(PetscDeviceContext, PetscEvent) noexcept; 218089fb57cSJacob Faibussowitsch static PetscErrorCode waitForEvent(PetscDeviceContext, PetscEvent) noexcept; 2197a101e5eSJacob Faibussowitsch 2207a101e5eSJacob Faibussowitsch // not a PetscDeviceContext method, this registers the class 221089fb57cSJacob Faibussowitsch static PetscErrorCode initialize(PetscDevice) noexcept; 2220e6b6b59SJacob Faibussowitsch 2230e6b6b59SJacob Faibussowitsch // clang-format off 2246ff55be4SJacob Faibussowitsch static constexpr _DeviceContextOps ops = { 2256ff55be4SJacob Faibussowitsch PetscDesignatedInitializer(destroy, destroy), 2266ff55be4SJacob Faibussowitsch PetscDesignatedInitializer(changestreamtype, changeStreamType), 2276ff55be4SJacob Faibussowitsch PetscDesignatedInitializer(setup, setUp), 2286ff55be4SJacob Faibussowitsch PetscDesignatedInitializer(query, query), 2296ff55be4SJacob Faibussowitsch PetscDesignatedInitializer(waitforcontext, waitForContext), 2306ff55be4SJacob Faibussowitsch PetscDesignatedInitializer(synchronize, synchronize), 2316ff55be4SJacob Faibussowitsch PetscDesignatedInitializer(getblashandle, getHandle<blas_tag>), 2326ff55be4SJacob Faibussowitsch PetscDesignatedInitializer(getsolverhandle, getHandle<solver_tag>), 233*31d47070SJunchao Zhang PetscDesignatedInitializer(getstreamhandle, getHandlePtr<stream_tag>), 2346ff55be4SJacob Faibussowitsch PetscDesignatedInitializer(begintimer, beginTimer), 2356ff55be4SJacob Faibussowitsch PetscDesignatedInitializer(endtimer, endTimer), 2366ff55be4SJacob Faibussowitsch PetscDesignatedInitializer(memalloc, memAlloc), 2376ff55be4SJacob Faibussowitsch PetscDesignatedInitializer(memfree, memFree), 2386ff55be4SJacob Faibussowitsch PetscDesignatedInitializer(memcopy, memCopy), 2396ff55be4SJacob Faibussowitsch PetscDesignatedInitializer(memset, memSet), 2406ff55be4SJacob Faibussowitsch PetscDesignatedInitializer(createevent, createEvent), 2416ff55be4SJacob Faibussowitsch PetscDesignatedInitializer(recordevent, recordEvent), 2426ff55be4SJacob Faibussowitsch PetscDesignatedInitializer(waitforevent, waitForEvent) 2430e6b6b59SJacob Faibussowitsch }; 2440e6b6b59SJacob Faibussowitsch // clang-format on 245030f984aSJacob Faibussowitsch }; 246030f984aSJacob Faibussowitsch 2470e6b6b59SJacob Faibussowitsch // not a PetscDeviceContext method, this initializes the CLASS 24817f48955SJacob Faibussowitsch template <DeviceType T> 2496d54fb17SJacob Faibussowitsch inline PetscErrorCode DeviceContext<T>::initialize(PetscDevice device) noexcept 250d71ae5a4SJacob Faibussowitsch { 2517a101e5eSJacob Faibussowitsch PetscFunctionBegin; 2527a101e5eSJacob Faibussowitsch if (PetscUnlikely(!initialized_)) { 2530e6b6b59SJacob Faibussowitsch uint64_t threshold = UINT64_MAX; 2546d54fb17SJacob Faibussowitsch cupmMemPool_t mempool; 2550e6b6b59SJacob Faibussowitsch 2567a101e5eSJacob Faibussowitsch initialized_ = true; 2576d54fb17SJacob Faibussowitsch PetscCallCUPM(cupmDeviceGetMemPool(&mempool, static_cast<int>(device->deviceId))); 2580e6b6b59SJacob Faibussowitsch PetscCallCUPM(cupmMemPoolSetAttribute(mempool, cupmMemPoolAttrReleaseThreshold, &threshold)); 2590e6b6b59SJacob Faibussowitsch blashandles_.fill(nullptr); 2600e6b6b59SJacob Faibussowitsch solverhandles_.fill(nullptr); 2617a101e5eSJacob Faibussowitsch PetscCall(PetscRegisterFinalize(finalize_)); 2627a101e5eSJacob Faibussowitsch } 2633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2647a101e5eSJacob Faibussowitsch } 2657a101e5eSJacob Faibussowitsch 2667a101e5eSJacob Faibussowitsch template <DeviceType T> 2676d54fb17SJacob Faibussowitsch inline PetscErrorCode DeviceContext<T>::destroy(PetscDeviceContext dctx) noexcept 268d71ae5a4SJacob Faibussowitsch { 269030f984aSJacob Faibussowitsch PetscFunctionBegin; 2700e6b6b59SJacob Faibussowitsch if (const auto dci = impls_cast_(dctx)) { 2710e6b6b59SJacob Faibussowitsch PetscCall(dci->stream.destroy()); 272146a86ebSJacob Faibussowitsch if (dci->event) PetscCall(cupm_fast_event_pool<T>().deallocate(&dci->event)); 2739566063dSJacob Faibussowitsch if (dci->begin) PetscCallCUPM(cupmEventDestroy(dci->begin)); 2749566063dSJacob Faibussowitsch if (dci->end) PetscCallCUPM(cupmEventDestroy(dci->end)); 2750e6b6b59SJacob Faibussowitsch delete dci; 2760e6b6b59SJacob Faibussowitsch dctx->data = nullptr; 2770e6b6b59SJacob Faibussowitsch } 2783ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 279030f984aSJacob Faibussowitsch } 280030f984aSJacob Faibussowitsch 28117f48955SJacob Faibussowitsch template <DeviceType T> 2826d54fb17SJacob Faibussowitsch inline PetscErrorCode DeviceContext<T>::changeStreamType(PetscDeviceContext dctx, PETSC_UNUSED PetscStreamType stype) noexcept 283d71ae5a4SJacob Faibussowitsch { 2847a101e5eSJacob Faibussowitsch const auto dci = impls_cast_(dctx); 285030f984aSJacob Faibussowitsch 286030f984aSJacob Faibussowitsch PetscFunctionBegin; 2870e6b6b59SJacob Faibussowitsch PetscCall(dci->stream.destroy()); 288030f984aSJacob Faibussowitsch // set these to null so they aren't usable until setup is called again 289030f984aSJacob Faibussowitsch dci->blas = nullptr; 290030f984aSJacob Faibussowitsch dci->solver = nullptr; 2913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 292030f984aSJacob Faibussowitsch } 293030f984aSJacob Faibussowitsch 29417f48955SJacob Faibussowitsch template <DeviceType T> 2956d54fb17SJacob Faibussowitsch inline PetscErrorCode DeviceContext<T>::setUp(PetscDeviceContext dctx) noexcept 296d71ae5a4SJacob Faibussowitsch { 2977a101e5eSJacob Faibussowitsch const auto dci = impls_cast_(dctx); 2980e6b6b59SJacob Faibussowitsch auto &event = dci->event; 299030f984aSJacob Faibussowitsch 300030f984aSJacob Faibussowitsch PetscFunctionBegin; 3010e6b6b59SJacob Faibussowitsch PetscCall(check_current_device_(dctx)); 3020e6b6b59SJacob Faibussowitsch PetscCall(dci->stream.change_type(dctx->streamType)); 3030e6b6b59SJacob Faibussowitsch if (!event) PetscCall(cupm_fast_event_pool<T>().allocate(&event)); 304a4af0ceeSJacob Faibussowitsch #if PetscDefined(USE_DEBUG) 305a4af0ceeSJacob Faibussowitsch dci->timerInUse = PETSC_FALSE; 306a4af0ceeSJacob Faibussowitsch #endif 3073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 308030f984aSJacob Faibussowitsch } 309030f984aSJacob Faibussowitsch 31017f48955SJacob Faibussowitsch template <DeviceType T> 3116d54fb17SJacob Faibussowitsch inline PetscErrorCode DeviceContext<T>::query(PetscDeviceContext dctx, PetscBool *idle) noexcept 312d71ae5a4SJacob Faibussowitsch { 313030f984aSJacob Faibussowitsch PetscFunctionBegin; 3140e6b6b59SJacob Faibussowitsch PetscCall(check_current_device_(dctx)); 3154b955ea4SJacob Faibussowitsch switch (auto cerr = cupmStreamQuery(impls_cast_(dctx)->stream.get_stream())) { 316d71ae5a4SJacob Faibussowitsch case cupmSuccess: 317d71ae5a4SJacob Faibussowitsch *idle = PETSC_TRUE; 318d71ae5a4SJacob Faibussowitsch break; 319d71ae5a4SJacob Faibussowitsch case cupmErrorNotReady: 320d71ae5a4SJacob Faibussowitsch *idle = PETSC_FALSE; 3214b955ea4SJacob Faibussowitsch // reset the error 3224b955ea4SJacob Faibussowitsch cerr = cupmGetLastError(); 3234b955ea4SJacob Faibussowitsch static_cast<void>(cerr); 324d71ae5a4SJacob Faibussowitsch break; 325d71ae5a4SJacob Faibussowitsch default: 326d71ae5a4SJacob Faibussowitsch PetscCallCUPM(cerr); 327d71ae5a4SJacob Faibussowitsch PetscUnreachable(); 328030f984aSJacob Faibussowitsch } 3293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 330030f984aSJacob Faibussowitsch } 331030f984aSJacob Faibussowitsch 33217f48955SJacob Faibussowitsch template <DeviceType T> 3336d54fb17SJacob Faibussowitsch inline PetscErrorCode DeviceContext<T>::waitForContext(PetscDeviceContext dctxa, PetscDeviceContext dctxb) noexcept 334d71ae5a4SJacob Faibussowitsch { 3350e6b6b59SJacob Faibussowitsch const auto dcib = impls_cast_(dctxb); 3360e6b6b59SJacob Faibussowitsch const auto event = dcib->event; 337030f984aSJacob Faibussowitsch 338030f984aSJacob Faibussowitsch PetscFunctionBegin; 3390e6b6b59SJacob Faibussowitsch PetscCall(check_current_device_(dctxa, dctxb)); 3400e6b6b59SJacob Faibussowitsch PetscCallCUPM(cupmEventRecord(event, dcib->stream.get_stream())); 3410e6b6b59SJacob Faibussowitsch PetscCallCUPM(cupmStreamWaitEvent(impls_cast_(dctxa)->stream.get_stream(), event, 0)); 3423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 343030f984aSJacob Faibussowitsch } 344030f984aSJacob Faibussowitsch 34517f48955SJacob Faibussowitsch template <DeviceType T> 3466d54fb17SJacob Faibussowitsch inline PetscErrorCode DeviceContext<T>::synchronize(PetscDeviceContext dctx) noexcept 347d71ae5a4SJacob Faibussowitsch { 3480e6b6b59SJacob Faibussowitsch auto idle = PETSC_TRUE; 349030f984aSJacob Faibussowitsch 350030f984aSJacob Faibussowitsch PetscFunctionBegin; 3510e6b6b59SJacob Faibussowitsch PetscCall(query(dctx, &idle)); 3520e6b6b59SJacob Faibussowitsch if (!idle) PetscCallCUPM(cupmStreamSynchronize(impls_cast_(dctx)->stream.get_stream())); 3533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 354030f984aSJacob Faibussowitsch } 355030f984aSJacob Faibussowitsch 35617f48955SJacob Faibussowitsch template <DeviceType T> 35717f48955SJacob Faibussowitsch template <typename handle_t> 3586d54fb17SJacob Faibussowitsch inline PetscErrorCode DeviceContext<T>::getHandle(PetscDeviceContext dctx, void *handle) noexcept 359d71ae5a4SJacob Faibussowitsch { 360a4af0ceeSJacob Faibussowitsch PetscFunctionBegin; 3617a101e5eSJacob Faibussowitsch PetscCall(initialize_handle_(handle_t{}, dctx)); 3627a101e5eSJacob Faibussowitsch *static_cast<typename handle_t::type *>(handle) = impls_cast_(dctx)->get(handle_t{}); 3633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 364a4af0ceeSJacob Faibussowitsch } 365a4af0ceeSJacob Faibussowitsch 36617f48955SJacob Faibussowitsch template <DeviceType T> 367*31d47070SJunchao Zhang template <typename handle_t> 368*31d47070SJunchao Zhang inline PetscErrorCode DeviceContext<T>::getHandlePtr(PetscDeviceContext dctx, void *handle) noexcept 369*31d47070SJunchao Zhang { 370*31d47070SJunchao Zhang using handle_type = typename handle_t::type; 371*31d47070SJunchao Zhang 372*31d47070SJunchao Zhang PetscFunctionBegin; 373*31d47070SJunchao Zhang PetscCall(initialize_handle_(handle_t{}, dctx)); 374*31d47070SJunchao Zhang *static_cast<handle_type **>(handle) = const_cast<handle_type *>(std::addressof(impls_cast_(dctx)->get(handle_t{}))); 375*31d47070SJunchao Zhang PetscFunctionReturn(PETSC_SUCCESS); 376*31d47070SJunchao Zhang } 377*31d47070SJunchao Zhang 378*31d47070SJunchao Zhang template <DeviceType T> 3796d54fb17SJacob Faibussowitsch inline PetscErrorCode DeviceContext<T>::beginTimer(PetscDeviceContext dctx) noexcept 380d71ae5a4SJacob Faibussowitsch { 3810e6b6b59SJacob Faibussowitsch const auto dci = impls_cast_(dctx); 382a4af0ceeSJacob Faibussowitsch 383a4af0ceeSJacob Faibussowitsch PetscFunctionBegin; 3840e6b6b59SJacob Faibussowitsch PetscCall(check_current_device_(dctx)); 385a4af0ceeSJacob Faibussowitsch #if PetscDefined(USE_DEBUG) 3865f80ce2aSJacob Faibussowitsch PetscCheck(!dci->timerInUse, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Forgot to call PetscLogGpuTimeEnd()?"); 387a4af0ceeSJacob Faibussowitsch dci->timerInUse = PETSC_TRUE; 388a4af0ceeSJacob Faibussowitsch #endif 38917f48955SJacob Faibussowitsch if (!dci->begin) { 3900e6b6b59SJacob Faibussowitsch PetscAssert(!dci->end, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Don't have a 'begin' event, but somehow have an end event"); 3919566063dSJacob Faibussowitsch PetscCallCUPM(cupmEventCreate(&dci->begin)); 3929566063dSJacob Faibussowitsch PetscCallCUPM(cupmEventCreate(&dci->end)); 39317f48955SJacob Faibussowitsch } 3940e6b6b59SJacob Faibussowitsch PetscCallCUPM(cupmEventRecord(dci->begin, dci->stream.get_stream())); 3953ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 396a4af0ceeSJacob Faibussowitsch } 397a4af0ceeSJacob Faibussowitsch 39817f48955SJacob Faibussowitsch template <DeviceType T> 3996d54fb17SJacob Faibussowitsch inline PetscErrorCode DeviceContext<T>::endTimer(PetscDeviceContext dctx, PetscLogDouble *elapsed) noexcept 400d71ae5a4SJacob Faibussowitsch { 401a4af0ceeSJacob Faibussowitsch float gtime; 4020e6b6b59SJacob Faibussowitsch const auto dci = impls_cast_(dctx); 4030e6b6b59SJacob Faibussowitsch const auto end = dci->end; 404a4af0ceeSJacob Faibussowitsch 405a4af0ceeSJacob Faibussowitsch PetscFunctionBegin; 4060e6b6b59SJacob Faibussowitsch PetscCall(check_current_device_(dctx)); 407a4af0ceeSJacob Faibussowitsch #if PetscDefined(USE_DEBUG) 4085f80ce2aSJacob Faibussowitsch PetscCheck(dci->timerInUse, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Forgot to call PetscLogGpuTimeBegin()?"); 409a4af0ceeSJacob Faibussowitsch dci->timerInUse = PETSC_FALSE; 410a4af0ceeSJacob Faibussowitsch #endif 4110e6b6b59SJacob Faibussowitsch PetscCallCUPM(cupmEventRecord(end, dci->stream.get_stream())); 4120e6b6b59SJacob Faibussowitsch PetscCallCUPM(cupmEventSynchronize(end)); 4130e6b6b59SJacob Faibussowitsch PetscCallCUPM(cupmEventElapsedTime(>ime, dci->begin, end)); 41417f48955SJacob Faibussowitsch *elapsed = static_cast<util::remove_pointer_t<decltype(elapsed)>>(gtime); 4153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 416a4af0ceeSJacob Faibussowitsch } 417a4af0ceeSJacob Faibussowitsch 4180e6b6b59SJacob Faibussowitsch template <DeviceType T> 4196d54fb17SJacob Faibussowitsch inline PetscErrorCode DeviceContext<T>::memAlloc(PetscDeviceContext dctx, PetscBool clear, PetscMemType mtype, std::size_t n, std::size_t alignment, void **dest) noexcept 420d71ae5a4SJacob Faibussowitsch { 4210e6b6b59SJacob Faibussowitsch const auto &stream = impls_cast_(dctx)->stream; 4220e6b6b59SJacob Faibussowitsch 4230e6b6b59SJacob Faibussowitsch PetscFunctionBegin; 4240e6b6b59SJacob Faibussowitsch PetscCall(check_current_device_(dctx)); 4250e6b6b59SJacob Faibussowitsch PetscCall(check_memtype_(mtype, "allocating")); 4260e6b6b59SJacob Faibussowitsch if (PetscMemTypeHost(mtype)) { 4276797ed33SJacob Faibussowitsch PetscCall(default_pool_<HostAllocator<T>>().allocate(n, reinterpret_cast<char **>(dest), &stream, alignment)); 4280e6b6b59SJacob Faibussowitsch } else { 4296797ed33SJacob Faibussowitsch PetscCall(default_pool_<DeviceAllocator<T>>().allocate(n, reinterpret_cast<char **>(dest), &stream, alignment)); 4300e6b6b59SJacob Faibussowitsch } 4316797ed33SJacob Faibussowitsch if (clear) PetscCallCUPM(cupmMemsetAsync(*dest, 0, n, stream.get_stream())); 4323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4330e6b6b59SJacob Faibussowitsch } 4340e6b6b59SJacob Faibussowitsch 4350e6b6b59SJacob Faibussowitsch template <DeviceType T> 4366d54fb17SJacob Faibussowitsch inline PetscErrorCode DeviceContext<T>::memFree(PetscDeviceContext dctx, PetscMemType mtype, void **ptr) noexcept 437d71ae5a4SJacob Faibussowitsch { 4380e6b6b59SJacob Faibussowitsch const auto &stream = impls_cast_(dctx)->stream; 4390e6b6b59SJacob Faibussowitsch 4400e6b6b59SJacob Faibussowitsch PetscFunctionBegin; 4410e6b6b59SJacob Faibussowitsch PetscCall(check_current_device_(dctx)); 4420e6b6b59SJacob Faibussowitsch PetscCall(check_memtype_(mtype, "freeing")); 4433ba16761SJacob Faibussowitsch if (!*ptr) PetscFunctionReturn(PETSC_SUCCESS); 4440e6b6b59SJacob Faibussowitsch if (PetscMemTypeHost(mtype)) { 4450e6b6b59SJacob Faibussowitsch PetscCall(default_pool_<HostAllocator<T>>().deallocate(reinterpret_cast<char **>(ptr), &stream)); 4460e6b6b59SJacob Faibussowitsch // if ptr exists still exists the pool didn't own it 4470e6b6b59SJacob Faibussowitsch if (*ptr) { 4480e6b6b59SJacob Faibussowitsch auto registered = PETSC_FALSE, managed = PETSC_FALSE; 4490e6b6b59SJacob Faibussowitsch 4500e6b6b59SJacob Faibussowitsch PetscCall(PetscCUPMGetMemType(*ptr, nullptr, ®istered, &managed)); 4510e6b6b59SJacob Faibussowitsch if (registered) { 4520e6b6b59SJacob Faibussowitsch PetscCallCUPM(cupmFreeHost(*ptr)); 4530e6b6b59SJacob Faibussowitsch } else if (managed) { 4540e6b6b59SJacob Faibussowitsch PetscCallCUPM(cupmFreeAsync(*ptr, stream.get_stream())); 4550e6b6b59SJacob Faibussowitsch } 4560e6b6b59SJacob Faibussowitsch } 4570e6b6b59SJacob Faibussowitsch } else { 4580e6b6b59SJacob Faibussowitsch PetscCall(default_pool_<DeviceAllocator<T>>().deallocate(reinterpret_cast<char **>(ptr), &stream)); 4596d54fb17SJacob Faibussowitsch // if ptr still exists the pool didn't own it 4600e6b6b59SJacob Faibussowitsch if (*ptr) PetscCallCUPM(cupmFreeAsync(*ptr, stream.get_stream())); 4610e6b6b59SJacob Faibussowitsch } 4623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4630e6b6b59SJacob Faibussowitsch } 4640e6b6b59SJacob Faibussowitsch 4650e6b6b59SJacob Faibussowitsch template <DeviceType T> 4666d54fb17SJacob Faibussowitsch inline PetscErrorCode DeviceContext<T>::memCopy(PetscDeviceContext dctx, void *PETSC_RESTRICT dest, const void *PETSC_RESTRICT src, std::size_t n, PetscDeviceCopyMode mode) noexcept 467d71ae5a4SJacob Faibussowitsch { 4680e6b6b59SJacob Faibussowitsch const auto stream = impls_cast_(dctx)->stream.get_stream(); 4690e6b6b59SJacob Faibussowitsch 4700e6b6b59SJacob Faibussowitsch PetscFunctionBegin; 4710e6b6b59SJacob Faibussowitsch // can't use PetscCUPMMemcpyAsync here since we don't know sizeof(*src)... 4720e6b6b59SJacob Faibussowitsch if (mode == PETSC_DEVICE_COPY_HTOH) { 4736d54fb17SJacob Faibussowitsch const auto cerr = cupmStreamQuery(stream); 4746d54fb17SJacob Faibussowitsch 4750e6b6b59SJacob Faibussowitsch // yes this is faster 4766d54fb17SJacob Faibussowitsch if (cerr == cupmSuccess) { 4770e6b6b59SJacob Faibussowitsch PetscCall(PetscMemcpy(dest, src, n)); 4783ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4796d54fb17SJacob Faibussowitsch } else if (cerr == cupmErrorNotReady) { 4806d54fb17SJacob Faibussowitsch auto PETSC_UNUSED unused = cupmGetLastError(); 4816d54fb17SJacob Faibussowitsch 4826d54fb17SJacob Faibussowitsch static_cast<void>(unused); 4836d54fb17SJacob Faibussowitsch } else { 4846d54fb17SJacob Faibussowitsch PetscCallCUPM(cerr); 4850e6b6b59SJacob Faibussowitsch } 4860e6b6b59SJacob Faibussowitsch } 4873ba16761SJacob Faibussowitsch PetscCallCUPM(cupmMemcpyAsync(dest, src, n, PetscDeviceCopyModeToCUPMMemcpyKind(mode), stream)); 4883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4890e6b6b59SJacob Faibussowitsch } 4900e6b6b59SJacob Faibussowitsch 4910e6b6b59SJacob Faibussowitsch template <DeviceType T> 4926d54fb17SJacob Faibussowitsch inline PetscErrorCode DeviceContext<T>::memSet(PetscDeviceContext dctx, PetscMemType mtype, void *ptr, PetscInt v, std::size_t n) noexcept 493d71ae5a4SJacob Faibussowitsch { 4940e6b6b59SJacob Faibussowitsch PetscFunctionBegin; 4950e6b6b59SJacob Faibussowitsch PetscCall(check_current_device_(dctx)); 4960e6b6b59SJacob Faibussowitsch PetscCall(check_memtype_(mtype, "zeroing")); 4976797ed33SJacob Faibussowitsch PetscCallCUPM(cupmMemsetAsync(ptr, static_cast<int>(v), n, impls_cast_(dctx)->stream.get_stream())); 4983ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4990e6b6b59SJacob Faibussowitsch } 5000e6b6b59SJacob Faibussowitsch 5010e6b6b59SJacob Faibussowitsch template <DeviceType T> 5028eb1d50fSPierre Jolivet inline PetscErrorCode DeviceContext<T>::createEvent(PetscDeviceContext, PetscEvent event) noexcept 503d71ae5a4SJacob Faibussowitsch { 5040e6b6b59SJacob Faibussowitsch PetscFunctionBegin; 5050e6b6b59SJacob Faibussowitsch PetscCallCXX(event->data = new event_type()); 5060e6b6b59SJacob Faibussowitsch event->destroy = [](PetscEvent event) { 5070e6b6b59SJacob Faibussowitsch PetscFunctionBegin; 5080e6b6b59SJacob Faibussowitsch delete event_cast_(event); 5090e6b6b59SJacob Faibussowitsch event->data = nullptr; 5103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5110e6b6b59SJacob Faibussowitsch }; 5123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5130e6b6b59SJacob Faibussowitsch } 5140e6b6b59SJacob Faibussowitsch 5150e6b6b59SJacob Faibussowitsch template <DeviceType T> 5166d54fb17SJacob Faibussowitsch inline PetscErrorCode DeviceContext<T>::recordEvent(PetscDeviceContext dctx, PetscEvent event) noexcept 517d71ae5a4SJacob Faibussowitsch { 5180e6b6b59SJacob Faibussowitsch PetscFunctionBegin; 5190e6b6b59SJacob Faibussowitsch PetscCall(impls_cast_(dctx)->stream.record_event(*event_cast_(event))); 5203ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5210e6b6b59SJacob Faibussowitsch } 5220e6b6b59SJacob Faibussowitsch 5230e6b6b59SJacob Faibussowitsch template <DeviceType T> 5246d54fb17SJacob Faibussowitsch inline PetscErrorCode DeviceContext<T>::waitForEvent(PetscDeviceContext dctx, PetscEvent event) noexcept 525d71ae5a4SJacob Faibussowitsch { 5260e6b6b59SJacob Faibussowitsch PetscFunctionBegin; 5270e6b6b59SJacob Faibussowitsch PetscCall(impls_cast_(dctx)->stream.wait_for_event(*event_cast_(event))); 5283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5290e6b6b59SJacob Faibussowitsch } 5300e6b6b59SJacob Faibussowitsch 531030f984aSJacob Faibussowitsch // initialize the static member variables 5329371c9d4SSatish Balay template <DeviceType T> 5339371c9d4SSatish Balay bool DeviceContext<T>::initialized_ = false; 534030f984aSJacob Faibussowitsch 53517f48955SJacob Faibussowitsch template <DeviceType T> 53617f48955SJacob Faibussowitsch std::array<typename DeviceContext<T>::cupmBlasHandle_t, PETSC_DEVICE_MAX_DEVICES> DeviceContext<T>::blashandles_ = {}; 537030f984aSJacob Faibussowitsch 53817f48955SJacob Faibussowitsch template <DeviceType T> 53917f48955SJacob Faibussowitsch std::array<typename DeviceContext<T>::cupmSolverHandle_t, PETSC_DEVICE_MAX_DEVICES> DeviceContext<T>::solverhandles_ = {}; 54017f48955SJacob Faibussowitsch 5416ff55be4SJacob Faibussowitsch template <DeviceType T> 5426ff55be4SJacob Faibussowitsch constexpr _DeviceContextOps DeviceContext<T>::ops; 5436ff55be4SJacob Faibussowitsch 5440e6b6b59SJacob Faibussowitsch } // namespace impl 545030f984aSJacob Faibussowitsch 546a4af0ceeSJacob Faibussowitsch // shorten this one up a bit (and instantiate the templates) 5470e6b6b59SJacob Faibussowitsch using CUPMContextCuda = impl::DeviceContext<DeviceType::CUDA>; 5480e6b6b59SJacob Faibussowitsch using CUPMContextHip = impl::DeviceContext<DeviceType::HIP>; 549030f984aSJacob Faibussowitsch 550030f984aSJacob Faibussowitsch // shorthand for what is an EXTREMELY long name 5510e6b6b59SJacob Faibussowitsch #define PetscDeviceContext_(IMPLS) ::Petsc::device::cupm::impl::DeviceContext<::Petsc::device::cupm::DeviceType::IMPLS>::PetscDeviceContext_IMPLS 552030f984aSJacob Faibussowitsch 5530e6b6b59SJacob Faibussowitsch } // namespace cupm 55417f48955SJacob Faibussowitsch 5550e6b6b59SJacob Faibussowitsch } // namespace device 55617f48955SJacob Faibussowitsch 55717f48955SJacob Faibussowitsch } // namespace Petsc 558030f984aSJacob Faibussowitsch 5590e6b6b59SJacob Faibussowitsch #endif // __cplusplus 5600e6b6b59SJacob Faibussowitsch 561a4af0ceeSJacob Faibussowitsch #endif // PETSCDEVICECONTEXTCUDA_HPP 562