1 // This file is part of Eigen, a lightweight C++ template library 2 // for linear algebra. 3 // 4 // Copyright (C) 2014 Benoit Steiner <benoit.steiner.goog@gmail.com> 5 // 6 // This Source Code Form is subject to the terms of the Mozilla 7 // Public License v. 2.0. If a copy of the MPL was not distributed 8 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. 9 10 #ifndef EIGEN_CXX11_TENSOR_TENSOR_FORCED_EVAL_H 11 #define EIGEN_CXX11_TENSOR_TENSOR_FORCED_EVAL_H 12 13 namespace Eigen { 14 15 /** \class TensorForcedEval 16 * \ingroup CXX11_Tensor_Module 17 * 18 * \brief Tensor reshaping class. 19 * 20 * 21 */ 22 /// template <class> class MakePointer_ is added to convert the host pointer to the device pointer. 23 /// It is added due to the fact that for our device compiler T* is not allowed. 24 /// If we wanted to use the same Evaluator functions we have to convert that type to our pointer T. 25 /// This is done through our MakePointer_ class. By default the Type in the MakePointer_<T> is T* . 26 /// Therefore, by adding the default value, we managed to convert the type and it does not break any 27 /// existing code as its default value is T*. 28 namespace internal { 29 template<typename XprType, template <class> class MakePointer_> 30 struct traits<TensorForcedEvalOp<XprType, MakePointer_> > 31 { 32 // Type promotion to handle the case where the types of the lhs and the rhs are different. 33 typedef typename XprType::Scalar Scalar; 34 typedef traits<XprType> XprTraits; 35 typedef typename traits<XprType>::StorageKind StorageKind; 36 typedef typename traits<XprType>::Index Index; 37 typedef typename XprType::Nested Nested; 38 typedef typename remove_reference<Nested>::type _Nested; 39 static const int NumDimensions = XprTraits::NumDimensions; 40 static const int Layout = XprTraits::Layout; 41 42 enum { 43 Flags = 0 44 }; 45 template <class T> struct MakePointer { 46 // Intermediate typedef to workaround MSVC issue. 47 typedef MakePointer_<T> MakePointerT; 48 typedef typename MakePointerT::Type Type; 49 }; 50 }; 51 52 template<typename XprType, template <class> class MakePointer_> 53 struct eval<TensorForcedEvalOp<XprType, MakePointer_>, Eigen::Dense> 54 { 55 typedef const TensorForcedEvalOp<XprType, MakePointer_>& type; 56 }; 57 58 template<typename XprType, template <class> class MakePointer_> 59 struct nested<TensorForcedEvalOp<XprType, MakePointer_>, 1, typename eval<TensorForcedEvalOp<XprType, MakePointer_> >::type> 60 { 61 typedef TensorForcedEvalOp<XprType, MakePointer_> type; 62 }; 63 64 } // end namespace internal 65 66 67 68 template<typename XprType, template <class> class MakePointer_> 69 class TensorForcedEvalOp : public TensorBase<TensorForcedEvalOp<XprType, MakePointer_>, ReadOnlyAccessors> 70 { 71 public: 72 typedef typename Eigen::internal::traits<TensorForcedEvalOp>::Scalar Scalar; 73 typedef typename Eigen::NumTraits<Scalar>::Real RealScalar; 74 typedef typename internal::remove_const<typename XprType::CoeffReturnType>::type CoeffReturnType; 75 typedef typename Eigen::internal::nested<TensorForcedEvalOp>::type Nested; 76 typedef typename Eigen::internal::traits<TensorForcedEvalOp>::StorageKind StorageKind; 77 typedef typename Eigen::internal::traits<TensorForcedEvalOp>::Index Index; 78 79 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorForcedEvalOp(const XprType& expr) 80 : m_xpr(expr) {} 81 82 EIGEN_DEVICE_FUNC 83 const typename internal::remove_all<typename XprType::Nested>::type& 84 expression() const { return m_xpr; } 85 86 protected: 87 typename XprType::Nested m_xpr; 88 }; 89 90 91 template<typename ArgType, typename Device, template <class> class MakePointer_> 92 struct TensorEvaluator<const TensorForcedEvalOp<ArgType, MakePointer_>, Device> 93 { 94 typedef TensorForcedEvalOp<ArgType, MakePointer_> XprType; 95 typedef typename ArgType::Scalar Scalar; 96 typedef typename TensorEvaluator<ArgType, Device>::Dimensions Dimensions; 97 typedef typename XprType::Index Index; 98 typedef typename XprType::CoeffReturnType CoeffReturnType; 99 typedef typename PacketType<CoeffReturnType, Device>::type PacketReturnType; 100 static const int PacketSize = internal::unpacket_traits<PacketReturnType>::size; 101 102 enum { 103 IsAligned = true, 104 PacketAccess = (PacketSize > 1), 105 Layout = TensorEvaluator<ArgType, Device>::Layout, 106 RawAccess = true 107 }; 108 109 EIGEN_DEVICE_FUNC TensorEvaluator(const XprType& op, const Device& device) 110 /// op_ is used for sycl 111 : m_impl(op.expression(), device), m_op(op.expression()), m_device(device), m_buffer(NULL) 112 { } 113 114 EIGEN_DEVICE_FUNC const Dimensions& dimensions() const { return m_impl.dimensions(); } 115 116 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool evalSubExprsIfNeeded(CoeffReturnType*) { 117 const Index numValues = internal::array_prod(m_impl.dimensions()); 118 m_buffer = (CoeffReturnType*)m_device.allocate(numValues * sizeof(CoeffReturnType)); 119 // Should initialize the memory in case we're dealing with non POD types. 120 if (NumTraits<CoeffReturnType>::RequireInitialization) { 121 for (Index i = 0; i < numValues; ++i) { 122 new(m_buffer+i) CoeffReturnType(); 123 } 124 } 125 typedef TensorEvalToOp< const typename internal::remove_const<ArgType>::type > EvalTo; 126 EvalTo evalToTmp(m_buffer, m_op); 127 const bool PacketAccess = internal::IsVectorizable<Device, const ArgType>::value; 128 internal::TensorExecutor<const EvalTo, typename internal::remove_const<Device>::type, PacketAccess>::run(evalToTmp, m_device); 129 return true; 130 } 131 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void cleanup() { 132 m_device.deallocate(m_buffer); 133 m_buffer = NULL; 134 } 135 136 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE CoeffReturnType coeff(Index index) const 137 { 138 return m_buffer[index]; 139 } 140 141 template<int LoadMode> 142 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketReturnType packet(Index index) const 143 { 144 return internal::ploadt<PacketReturnType, LoadMode>(m_buffer + index); 145 } 146 147 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorOpCost costPerCoeff(bool vectorized) const { 148 return TensorOpCost(sizeof(CoeffReturnType), 0, 0, vectorized, PacketSize); 149 } 150 151 EIGEN_DEVICE_FUNC typename MakePointer<Scalar>::Type data() const { return m_buffer; } 152 153 /// required by sycl in order to extract the sycl accessor 154 const TensorEvaluator<ArgType, Device>& impl() { return m_impl; } 155 /// used by sycl in order to build the sycl buffer 156 const Device& device() const{return m_device;} 157 private: 158 TensorEvaluator<ArgType, Device> m_impl; 159 const ArgType m_op; 160 const Device& m_device; 161 typename MakePointer<CoeffReturnType>::Type m_buffer; 162 }; 163 164 165 } // end namespace Eigen 166 167 #endif // EIGEN_CXX11_TENSOR_TENSOR_FORCED_EVAL_H 168