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