10e6b6b59SJacob Faibussowitsch #ifndef PETSCDEVICE_INTERFACE_INTERNAL_HPP 20e6b6b59SJacob Faibussowitsch #define PETSCDEVICE_INTERFACE_INTERNAL_HPP 30e6b6b59SJacob Faibussowitsch 40e6b6b59SJacob Faibussowitsch #include <petsc/private/deviceimpl.h> 50e6b6b59SJacob Faibussowitsch 60e6b6b59SJacob Faibussowitsch #include <petsc/private/cpp/utility.hpp> // std::pair 70e6b6b59SJacob Faibussowitsch #include <petsc/private/cpp/functional.hpp> //std::equal_to 80e6b6b59SJacob Faibussowitsch 90e6b6b59SJacob Faibussowitsch #include <unordered_map> 100e6b6b59SJacob Faibussowitsch #include <unordered_set> 110e6b6b59SJacob Faibussowitsch 120e6b6b59SJacob Faibussowitsch #if PetscDefined(USE_DEBUG) && PetscDefined(USE_INFO) 130e6b6b59SJacob Faibussowitsch #define PETSC_USE_DEBUG_AND_INFO 1 140e6b6b59SJacob Faibussowitsch #define PetscDebugInfo(dctx, ...) PetscInfo(dctx, __VA_ARGS__) 150e6b6b59SJacob Faibussowitsch #else 160e6b6b59SJacob Faibussowitsch #define PetscDebugInfo(dctx, ...) 0 170e6b6b59SJacob Faibussowitsch #endif 180e6b6b59SJacob Faibussowitsch 190e6b6b59SJacob Faibussowitsch // this file contains functions needed to bridge the gap between dcontext.cxx and device.cxx 200e6b6b59SJacob Faibussowitsch // but are not useful enough to put in the impl header 210e6b6b59SJacob Faibussowitsch PETSC_INTERN PetscErrorCode PetscDeviceContextSetDefaultDeviceForType_Internal(PetscDeviceContext, PetscDeviceType); 220e6b6b59SJacob Faibussowitsch PETSC_INTERN PetscErrorCode PetscDeviceContextSetRootDeviceType_Internal(PetscDeviceType); 230e6b6b59SJacob Faibussowitsch PETSC_INTERN PetscErrorCode PetscDeviceContextSetRootStreamType_Internal(PetscStreamType); 240e6b6b59SJacob Faibussowitsch PETSC_INTERN PetscErrorCode PetscDeviceContextSyncClearMap_Internal(PetscDeviceContext); 250e6b6b59SJacob Faibussowitsch PETSC_INTERN PetscErrorCode PetscDeviceContextCheckNotOrphaned_Internal(PetscDeviceContext); 260e6b6b59SJacob Faibussowitsch 270e6b6b59SJacob Faibussowitsch // open up namespace std to specialize equal_to for unordered_map 28*d71ae5a4SJacob Faibussowitsch namespace std 29*d71ae5a4SJacob Faibussowitsch { 300e6b6b59SJacob Faibussowitsch 310e6b6b59SJacob Faibussowitsch template <> 320e6b6b59SJacob Faibussowitsch struct equal_to<PetscDeviceContext> { 330e6b6b59SJacob Faibussowitsch #if PETSC_CPP_VERSION <= 17 340e6b6b59SJacob Faibussowitsch using result_type = bool; 350e6b6b59SJacob Faibussowitsch using first_argument_type = PetscDeviceContext; 360e6b6b59SJacob Faibussowitsch using second_argument_type = PetscDeviceContext; 370e6b6b59SJacob Faibussowitsch #endif 380e6b6b59SJacob Faibussowitsch 39*d71ae5a4SJacob Faibussowitsch constexpr bool operator()(const PetscDeviceContext &x, const PetscDeviceContext &y) const noexcept { return PetscObjectCast(x)->id == PetscObjectCast(y)->id; } 400e6b6b59SJacob Faibussowitsch }; 410e6b6b59SJacob Faibussowitsch 420e6b6b59SJacob Faibussowitsch } // namespace std 430e6b6b59SJacob Faibussowitsch 44*d71ae5a4SJacob Faibussowitsch namespace 45*d71ae5a4SJacob Faibussowitsch { 460e6b6b59SJacob Faibussowitsch 470e6b6b59SJacob Faibussowitsch struct CxxData { 480e6b6b59SJacob Faibussowitsch struct parent_type { 490e6b6b59SJacob Faibussowitsch PetscObjectId id = 0; 500e6b6b59SJacob Faibussowitsch PetscObjectState state = 0; 510e6b6b59SJacob Faibussowitsch 520e6b6b59SJacob Faibussowitsch constexpr parent_type() noexcept = default; 530e6b6b59SJacob Faibussowitsch 540e6b6b59SJacob Faibussowitsch constexpr explicit parent_type(PetscDeviceContext dctx) noexcept : parent_type(PetscObjectCast(dctx)->id, PetscObjectCast(dctx)->state) { } 550e6b6b59SJacob Faibussowitsch 560e6b6b59SJacob Faibussowitsch constexpr parent_type(const parent_type &) noexcept = default; 570e6b6b59SJacob Faibussowitsch PETSC_CONSTEXPR_14 parent_type &operator=(const parent_type &) noexcept = default; 580e6b6b59SJacob Faibussowitsch constexpr parent_type(parent_type &&) noexcept = default; 590e6b6b59SJacob Faibussowitsch PETSC_CONSTEXPR_14 parent_type &operator=(parent_type &&) noexcept = default; 600e6b6b59SJacob Faibussowitsch 610e6b6b59SJacob Faibussowitsch private: 620e6b6b59SJacob Faibussowitsch // make this private, we do not want to accept any old id and state pairing 630e6b6b59SJacob Faibussowitsch constexpr parent_type(PetscObjectId id_, PetscObjectState state_) noexcept : id(id_), state(state_) { } 640e6b6b59SJacob Faibussowitsch }; 650e6b6b59SJacob Faibussowitsch 660e6b6b59SJacob Faibussowitsch using upstream_type = std::unordered_map<PetscDeviceContext, parent_type>; 670e6b6b59SJacob Faibussowitsch using dep_type = std::unordered_set<PetscObjectId>; 680e6b6b59SJacob Faibussowitsch 690e6b6b59SJacob Faibussowitsch // double check we didn't specialize for no reason 700e6b6b59SJacob Faibussowitsch static_assert(std::is_same<typename upstream_type::key_equal, std::equal_to<PetscDeviceContext>>::value, ""); 710e6b6b59SJacob Faibussowitsch 720e6b6b59SJacob Faibussowitsch upstream_type upstream{}; 730e6b6b59SJacob Faibussowitsch dep_type deps{}; 740e6b6b59SJacob Faibussowitsch 750e6b6b59SJacob Faibussowitsch PETSC_NODISCARD PetscErrorCode clear() noexcept; 760e6b6b59SJacob Faibussowitsch }; 770e6b6b59SJacob Faibussowitsch 78*d71ae5a4SJacob Faibussowitsch inline PetscErrorCode CxxData::clear() noexcept 79*d71ae5a4SJacob Faibussowitsch { 800e6b6b59SJacob Faibussowitsch PetscFunctionBegin; 810e6b6b59SJacob Faibussowitsch PetscCallCXX(this->upstream.clear()); 820e6b6b59SJacob Faibussowitsch PetscCallCXX(this->deps.clear()); 830e6b6b59SJacob Faibussowitsch PetscFunctionReturn(0); 840e6b6b59SJacob Faibussowitsch } 850e6b6b59SJacob Faibussowitsch 86*d71ae5a4SJacob Faibussowitsch PETSC_NODISCARD inline CxxData *CxxDataCast(PetscDeviceContext dctx) noexcept 87*d71ae5a4SJacob Faibussowitsch { 880e6b6b59SJacob Faibussowitsch return static_cast<CxxData *>(PetscObjectCast(dctx)->cpp); 890e6b6b59SJacob Faibussowitsch } 900e6b6b59SJacob Faibussowitsch 910e6b6b59SJacob Faibussowitsch /* 920e6b6b59SJacob Faibussowitsch needed because PetscInitialize() needs to also query these options to set the defaults. Since 930e6b6b59SJacob Faibussowitsch it does not yet have a PetscDeviceContext to call this with, the actual options queries are 940e6b6b59SJacob Faibussowitsch abstracted out, so you can call this without one. 950e6b6b59SJacob Faibussowitsch */ 96*d71ae5a4SJacob Faibussowitsch inline PetscErrorCode PetscDeviceContextQueryOptions_Internal(PetscOptionItems *PetscOptionsObject, std::pair<PetscDeviceType, PetscBool> &deviceType, std::pair<PetscStreamType, PetscBool> &streamType) 97*d71ae5a4SJacob Faibussowitsch { 980e6b6b59SJacob Faibussowitsch auto dtype = static_cast<PetscInt>(deviceType.first); 990e6b6b59SJacob Faibussowitsch auto stype = static_cast<PetscInt>(streamType.first); 1000e6b6b59SJacob Faibussowitsch 1010e6b6b59SJacob Faibussowitsch PetscFunctionBegin; 1020e6b6b59SJacob Faibussowitsch /* set the device type first */ 1030e6b6b59SJacob Faibussowitsch PetscCall(PetscOptionsEList("-device_context_device_type", "Underlying PetscDevice", "PetscDeviceContextSetDevice", PetscDeviceTypes, PETSC_DEVICE_MAX, PetscDeviceTypes[dtype], &dtype, &deviceType.second)); 1040e6b6b59SJacob Faibussowitsch PetscCall(PetscOptionsEList("-device_context_stream_type", "PetscDeviceContext PetscStreamType", "PetscDeviceContextSetStreamType", PetscStreamTypes, PETSC_STREAM_MAX, PetscStreamTypes[stype], &stype, &streamType.second)); 1050e6b6b59SJacob Faibussowitsch deviceType.first = PetscDeviceTypeCast(dtype); 1060e6b6b59SJacob Faibussowitsch streamType.first = PetscStreamTypeCast(stype); 1070e6b6b59SJacob Faibussowitsch PetscFunctionReturn(0); 1080e6b6b59SJacob Faibussowitsch } 1090e6b6b59SJacob Faibussowitsch 1100e6b6b59SJacob Faibussowitsch } // anonymous namespace 1110e6b6b59SJacob Faibussowitsch 1120e6b6b59SJacob Faibussowitsch #endif // PETSCDEVICE_INTERFACE_INTERNAL_HPP 113