1*0e6b6b59SJacob Faibussowitsch #ifndef PETSCDEVICE_INTERFACE_INTERNAL_HPP 2*0e6b6b59SJacob Faibussowitsch #define PETSCDEVICE_INTERFACE_INTERNAL_HPP 3*0e6b6b59SJacob Faibussowitsch 4*0e6b6b59SJacob Faibussowitsch #include <petsc/private/deviceimpl.h> 5*0e6b6b59SJacob Faibussowitsch 6*0e6b6b59SJacob Faibussowitsch #include <petsc/private/cpp/utility.hpp> // std::pair 7*0e6b6b59SJacob Faibussowitsch #include <petsc/private/cpp/functional.hpp> //std::equal_to 8*0e6b6b59SJacob Faibussowitsch 9*0e6b6b59SJacob Faibussowitsch #include <unordered_map> 10*0e6b6b59SJacob Faibussowitsch #include <unordered_set> 11*0e6b6b59SJacob Faibussowitsch 12*0e6b6b59SJacob Faibussowitsch #if PetscDefined(USE_DEBUG) && PetscDefined(USE_INFO) 13*0e6b6b59SJacob Faibussowitsch #define PETSC_USE_DEBUG_AND_INFO 1 14*0e6b6b59SJacob Faibussowitsch #define PetscDebugInfo(dctx, ...) PetscInfo(dctx, __VA_ARGS__) 15*0e6b6b59SJacob Faibussowitsch #else 16*0e6b6b59SJacob Faibussowitsch #define PetscDebugInfo(dctx, ...) 0 17*0e6b6b59SJacob Faibussowitsch #endif 18*0e6b6b59SJacob Faibussowitsch 19*0e6b6b59SJacob Faibussowitsch // this file contains functions needed to bridge the gap between dcontext.cxx and device.cxx 20*0e6b6b59SJacob Faibussowitsch // but are not useful enough to put in the impl header 21*0e6b6b59SJacob Faibussowitsch PETSC_INTERN PetscErrorCode PetscDeviceContextSetDefaultDeviceForType_Internal(PetscDeviceContext, PetscDeviceType); 22*0e6b6b59SJacob Faibussowitsch PETSC_INTERN PetscErrorCode PetscDeviceContextSetRootDeviceType_Internal(PetscDeviceType); 23*0e6b6b59SJacob Faibussowitsch PETSC_INTERN PetscErrorCode PetscDeviceContextSetRootStreamType_Internal(PetscStreamType); 24*0e6b6b59SJacob Faibussowitsch PETSC_INTERN PetscErrorCode PetscDeviceContextSyncClearMap_Internal(PetscDeviceContext); 25*0e6b6b59SJacob Faibussowitsch PETSC_INTERN PetscErrorCode PetscDeviceContextCheckNotOrphaned_Internal(PetscDeviceContext); 26*0e6b6b59SJacob Faibussowitsch 27*0e6b6b59SJacob Faibussowitsch // open up namespace std to specialize equal_to for unordered_map 28*0e6b6b59SJacob Faibussowitsch namespace std { 29*0e6b6b59SJacob Faibussowitsch 30*0e6b6b59SJacob Faibussowitsch template <> 31*0e6b6b59SJacob Faibussowitsch struct equal_to<PetscDeviceContext> { 32*0e6b6b59SJacob Faibussowitsch #if PETSC_CPP_VERSION <= 17 33*0e6b6b59SJacob Faibussowitsch using result_type = bool; 34*0e6b6b59SJacob Faibussowitsch using first_argument_type = PetscDeviceContext; 35*0e6b6b59SJacob Faibussowitsch using second_argument_type = PetscDeviceContext; 36*0e6b6b59SJacob Faibussowitsch #endif 37*0e6b6b59SJacob Faibussowitsch 38*0e6b6b59SJacob Faibussowitsch constexpr bool operator()(const PetscDeviceContext &x, const PetscDeviceContext &y) const noexcept { 39*0e6b6b59SJacob Faibussowitsch return PetscObjectCast(x)->id == PetscObjectCast(y)->id; 40*0e6b6b59SJacob Faibussowitsch } 41*0e6b6b59SJacob Faibussowitsch }; 42*0e6b6b59SJacob Faibussowitsch 43*0e6b6b59SJacob Faibussowitsch } // namespace std 44*0e6b6b59SJacob Faibussowitsch 45*0e6b6b59SJacob Faibussowitsch namespace { 46*0e6b6b59SJacob Faibussowitsch 47*0e6b6b59SJacob Faibussowitsch struct CxxData { 48*0e6b6b59SJacob Faibussowitsch struct parent_type { 49*0e6b6b59SJacob Faibussowitsch PetscObjectId id = 0; 50*0e6b6b59SJacob Faibussowitsch PetscObjectState state = 0; 51*0e6b6b59SJacob Faibussowitsch 52*0e6b6b59SJacob Faibussowitsch constexpr parent_type() noexcept = default; 53*0e6b6b59SJacob Faibussowitsch 54*0e6b6b59SJacob Faibussowitsch constexpr explicit parent_type(PetscDeviceContext dctx) noexcept : parent_type(PetscObjectCast(dctx)->id, PetscObjectCast(dctx)->state) { } 55*0e6b6b59SJacob Faibussowitsch 56*0e6b6b59SJacob Faibussowitsch constexpr parent_type(const parent_type &) noexcept = default; 57*0e6b6b59SJacob Faibussowitsch PETSC_CONSTEXPR_14 parent_type &operator=(const parent_type &) noexcept = default; 58*0e6b6b59SJacob Faibussowitsch constexpr parent_type(parent_type &&) noexcept = default; 59*0e6b6b59SJacob Faibussowitsch PETSC_CONSTEXPR_14 parent_type &operator=(parent_type &&) noexcept = default; 60*0e6b6b59SJacob Faibussowitsch 61*0e6b6b59SJacob Faibussowitsch private: 62*0e6b6b59SJacob Faibussowitsch // make this private, we do not want to accept any old id and state pairing 63*0e6b6b59SJacob Faibussowitsch constexpr parent_type(PetscObjectId id_, PetscObjectState state_) noexcept : id(id_), state(state_) { } 64*0e6b6b59SJacob Faibussowitsch }; 65*0e6b6b59SJacob Faibussowitsch 66*0e6b6b59SJacob Faibussowitsch using upstream_type = std::unordered_map<PetscDeviceContext, parent_type>; 67*0e6b6b59SJacob Faibussowitsch using dep_type = std::unordered_set<PetscObjectId>; 68*0e6b6b59SJacob Faibussowitsch 69*0e6b6b59SJacob Faibussowitsch // double check we didn't specialize for no reason 70*0e6b6b59SJacob Faibussowitsch static_assert(std::is_same<typename upstream_type::key_equal, std::equal_to<PetscDeviceContext>>::value, ""); 71*0e6b6b59SJacob Faibussowitsch 72*0e6b6b59SJacob Faibussowitsch upstream_type upstream{}; 73*0e6b6b59SJacob Faibussowitsch dep_type deps{}; 74*0e6b6b59SJacob Faibussowitsch 75*0e6b6b59SJacob Faibussowitsch PETSC_NODISCARD PetscErrorCode clear() noexcept; 76*0e6b6b59SJacob Faibussowitsch }; 77*0e6b6b59SJacob Faibussowitsch 78*0e6b6b59SJacob Faibussowitsch inline PetscErrorCode CxxData::clear() noexcept { 79*0e6b6b59SJacob Faibussowitsch PetscFunctionBegin; 80*0e6b6b59SJacob Faibussowitsch PetscCallCXX(this->upstream.clear()); 81*0e6b6b59SJacob Faibussowitsch PetscCallCXX(this->deps.clear()); 82*0e6b6b59SJacob Faibussowitsch PetscFunctionReturn(0); 83*0e6b6b59SJacob Faibussowitsch } 84*0e6b6b59SJacob Faibussowitsch 85*0e6b6b59SJacob Faibussowitsch PETSC_NODISCARD inline CxxData *CxxDataCast(PetscDeviceContext dctx) noexcept { 86*0e6b6b59SJacob Faibussowitsch return static_cast<CxxData *>(PetscObjectCast(dctx)->cpp); 87*0e6b6b59SJacob Faibussowitsch } 88*0e6b6b59SJacob Faibussowitsch 89*0e6b6b59SJacob Faibussowitsch /* 90*0e6b6b59SJacob Faibussowitsch needed because PetscInitialize() needs to also query these options to set the defaults. Since 91*0e6b6b59SJacob Faibussowitsch it does not yet have a PetscDeviceContext to call this with, the actual options queries are 92*0e6b6b59SJacob Faibussowitsch abstracted out, so you can call this without one. 93*0e6b6b59SJacob Faibussowitsch */ 94*0e6b6b59SJacob Faibussowitsch inline PetscErrorCode PetscDeviceContextQueryOptions_Internal(PetscOptionItems *PetscOptionsObject, std::pair<PetscDeviceType, PetscBool> &deviceType, std::pair<PetscStreamType, PetscBool> &streamType) { 95*0e6b6b59SJacob Faibussowitsch auto dtype = static_cast<PetscInt>(deviceType.first); 96*0e6b6b59SJacob Faibussowitsch auto stype = static_cast<PetscInt>(streamType.first); 97*0e6b6b59SJacob Faibussowitsch 98*0e6b6b59SJacob Faibussowitsch PetscFunctionBegin; 99*0e6b6b59SJacob Faibussowitsch /* set the device type first */ 100*0e6b6b59SJacob Faibussowitsch PetscCall(PetscOptionsEList("-device_context_device_type", "Underlying PetscDevice", "PetscDeviceContextSetDevice", PetscDeviceTypes, PETSC_DEVICE_MAX, PetscDeviceTypes[dtype], &dtype, &deviceType.second)); 101*0e6b6b59SJacob Faibussowitsch PetscCall(PetscOptionsEList("-device_context_stream_type", "PetscDeviceContext PetscStreamType", "PetscDeviceContextSetStreamType", PetscStreamTypes, PETSC_STREAM_MAX, PetscStreamTypes[stype], &stype, &streamType.second)); 102*0e6b6b59SJacob Faibussowitsch deviceType.first = PetscDeviceTypeCast(dtype); 103*0e6b6b59SJacob Faibussowitsch streamType.first = PetscStreamTypeCast(stype); 104*0e6b6b59SJacob Faibussowitsch PetscFunctionReturn(0); 105*0e6b6b59SJacob Faibussowitsch } 106*0e6b6b59SJacob Faibussowitsch 107*0e6b6b59SJacob Faibussowitsch } // anonymous namespace 108*0e6b6b59SJacob Faibussowitsch 109*0e6b6b59SJacob Faibussowitsch #endif // PETSCDEVICE_INTERFACE_INTERNAL_HPP 110