diff options
author | Gael Guennebaud <g.gael@free.fr> | 2010-02-09 11:05:39 +0100 |
---|---|---|
committer | Gael Guennebaud <g.gael@free.fr> | 2010-02-09 11:05:39 +0100 |
commit | 5686eca7b1017738a19a32ce0627249e56cfd3eb (patch) | |
tree | eae2f93d90cb58c7625334c3cb754b9c528754fe | |
parent | 0398e21198caaf7206851a9081033cddb0797d47 (diff) |
* fix multiple temporary copies for coeff based products
* introduce a lazy product version of the coefficient based implementation
=> flagged is not used anymore
=> small outer product are now lazy by default (aliasing is really unlikely for outer products)
-rw-r--r-- | Eigen/Core | 2 | ||||
-rw-r--r-- | Eigen/src/Core/NoAlias.h | 12 | ||||
-rw-r--r-- | Eigen/src/Core/Product.h | 24 | ||||
-rw-r--r-- | Eigen/src/Core/ProductBase.h | 18 | ||||
-rw-r--r-- | Eigen/src/Core/products/CoeffBasedProduct.h (renamed from Eigen/src/Core/products/GeneralCoeffBased.h) | 60 | ||||
-rw-r--r-- | Eigen/src/Core/util/Constants.h | 2 | ||||
-rw-r--r-- | Eigen/src/Core/util/ForwardDeclarations.h | 5 | ||||
-rw-r--r-- | Eigen/src/Core/util/StaticAssert.h | 1 |
8 files changed, 75 insertions, 49 deletions
diff --git a/Eigen/Core b/Eigen/Core index b6e383210..b9241a730 100644 --- a/Eigen/Core +++ b/Eigen/Core @@ -205,7 +205,7 @@ struct Dense {}; #include "src/Core/TriangularMatrix.h" #include "src/Core/SelfAdjointView.h" #include "src/Core/SolveTriangular.h" -#include "src/Core/products/GeneralUnrolled.h" +#include "src/Core/products/CoeffBasedProduct.h" #include "src/Core/products/GeneralBlockPanelKernel.h" #include "src/Core/products/GeneralMatrixVector.h" #include "src/Core/products/GeneralMatrixMatrix.h" diff --git a/Eigen/src/Core/NoAlias.h b/Eigen/src/Core/NoAlias.h index 7e2e501b3..9d6cab7f9 100644 --- a/Eigen/src/Core/NoAlias.h +++ b/Eigen/src/Core/NoAlias.h @@ -70,13 +70,13 @@ class NoAlias EIGEN_STRONG_INLINE ExpressionType& operator-=(const ProductBase<ProductDerived, Lhs,Rhs>& other) { other.derived().subTo(m_expression); return m_expression; } - template<typename Lhs, typename Rhs> - EIGEN_STRONG_INLINE ExpressionType& operator+=(const GeneralProduct<Lhs,Rhs,CoeffBasedProduct>& other) - { return m_expression.derived() += other.template flagged<0,EvalBeforeAssigningBit|EvalBeforeNestingBit>(); } + template<typename Lhs, typename Rhs, int NestingFlags> + EIGEN_STRONG_INLINE ExpressionType& operator+=(const CoeffBasedProduct<Lhs,Rhs,NestingFlags>& other) + { return m_expression.derived() += CoeffBasedProduct<Lhs,Rhs,0>(other.lhs(), other.rhs()); } - template<typename Lhs, typename Rhs> - EIGEN_STRONG_INLINE ExpressionType& operator-=(const GeneralProduct<Lhs,Rhs,CoeffBasedProduct>& other) - { return m_expression.derived() -= other.template flagged<0,EvalBeforeAssigningBit|EvalBeforeNestingBit>(); } + template<typename Lhs, typename Rhs, int NestingFlags> + EIGEN_STRONG_INLINE ExpressionType& operator-=(const CoeffBasedProduct<Lhs,Rhs,NestingFlags>& other) + { return m_expression.derived() -= CoeffBasedProduct<Lhs,Rhs,0>(other.lhs(), other.rhs()); } #endif protected: diff --git a/Eigen/src/Core/Product.h b/Eigen/src/Core/Product.h index 5e531c467..e643b2ea7 100644 --- a/Eigen/src/Core/Product.h +++ b/Eigen/src/Core/Product.h @@ -87,12 +87,12 @@ public: template<int Rows, int Cols> struct ei_product_type_selector<Rows, Cols, 1> { enum { ret = OuterProduct }; }; template<int Depth> struct ei_product_type_selector<1, 1, Depth> { enum { ret = InnerProduct }; }; template<> struct ei_product_type_selector<1, 1, 1> { enum { ret = InnerProduct }; }; -template<> struct ei_product_type_selector<Small,1, Small> { enum { ret = CoeffBasedProduct }; }; -template<> struct ei_product_type_selector<1, Small,Small> { enum { ret = CoeffBasedProduct }; }; -template<> struct ei_product_type_selector<Small,Small,Small> { enum { ret = CoeffBasedProduct }; }; -template<> struct ei_product_type_selector<Small, Small, 1> { enum { ret = CoeffBasedProduct }; }; -template<> struct ei_product_type_selector<Small, Large, 1> { enum { ret = CoeffBasedProduct }; }; -template<> struct ei_product_type_selector<Large, Small, 1> { enum { ret = CoeffBasedProduct }; }; +template<> struct ei_product_type_selector<Small,1, Small> { enum { ret = CoeffBasedProductMode }; }; +template<> struct ei_product_type_selector<1, Small,Small> { enum { ret = CoeffBasedProductMode }; }; +template<> struct ei_product_type_selector<Small,Small,Small> { enum { ret = CoeffBasedProductMode }; }; +template<> struct ei_product_type_selector<Small, Small, 1> { enum { ret = LazyCoeffBasedProductMode }; }; +template<> struct ei_product_type_selector<Small, Large, 1> { enum { ret = LazyCoeffBasedProductMode }; }; +template<> struct ei_product_type_selector<Large, Small, 1> { enum { ret = LazyCoeffBasedProductMode }; }; template<> struct ei_product_type_selector<1, Large,Small> { enum { ret = GemvProduct }; }; template<> struct ei_product_type_selector<1, Large,Large> { enum { ret = GemvProduct }; }; template<> struct ei_product_type_selector<1, Small,Large> { enum { ret = GemvProduct }; }; @@ -134,11 +134,19 @@ struct ProductReturnType }; template<typename Lhs, typename Rhs> -struct ProductReturnType<Lhs,Rhs,CoeffBasedProduct> +struct ProductReturnType<Lhs,Rhs,CoeffBasedProductMode> { typedef typename ei_nested<Lhs, Rhs::ColsAtCompileTime, typename ei_plain_matrix_type<Lhs>::type >::type LhsNested; typedef typename ei_nested<Rhs, Lhs::RowsAtCompileTime, typename ei_plain_matrix_type<Rhs>::type >::type RhsNested; - typedef GeneralProduct<LhsNested, RhsNested, CoeffBasedProduct> Type; + typedef CoeffBasedProduct<LhsNested, RhsNested, EvalBeforeAssigningBit | EvalBeforeNestingBit> Type; +}; + +template<typename Lhs, typename Rhs> +struct ProductReturnType<Lhs,Rhs,LazyCoeffBasedProductMode> +{ + typedef typename ei_nested<Lhs, Rhs::ColsAtCompileTime, typename ei_plain_matrix_type<Lhs>::type >::type LhsNested; + typedef typename ei_nested<Rhs, Lhs::RowsAtCompileTime, typename ei_plain_matrix_type<Rhs>::type >::type RhsNested; + typedef CoeffBasedProduct<LhsNested, RhsNested, 0> Type; }; diff --git a/Eigen/src/Core/ProductBase.h b/Eigen/src/Core/ProductBase.h index 6eb02f386..9fdb74f1c 100644 --- a/Eigen/src/Core/ProductBase.h +++ b/Eigen/src/Core/ProductBase.h @@ -83,8 +83,7 @@ class ProductBase : public MatrixBase<Derived> typedef typename RhsBlasTraits::DirectLinearAccessType ActualRhsType; typedef typename ei_cleantype<ActualRhsType>::type _ActualRhsType; - typedef typename ProductReturnType<Lhs,Rhs,CoeffBasedProduct>::Type CoeffBaseProductType; - typedef Flagged<CoeffBaseProductType,0,EvalBeforeNestingBit> LazyCoeffBaseProductType; + typedef typename ProductReturnType<Lhs,Rhs,LazyCoeffBasedProductMode>::Type LazyCoeffBaseProductType; public: typedef typename Base::PlainMatrixType PlainMatrixType; @@ -112,31 +111,28 @@ class ProductBase : public MatrixBase<Derived> template<typename Dest> inline void scaleAndAddTo(Dest& dst,Scalar alpha) const { derived().scaleAndAddTo(dst,alpha); } - EIGEN_DEPRECATED const Flagged<ProductBase, 0, EvalBeforeAssigningBit> lazy() const - { return *this; } - const _LhsNested& lhs() const { return m_lhs; } const _RhsNested& rhs() const { return m_rhs; } const Diagonal<LazyCoeffBaseProductType,0> diagonal() const - { return Diagonal<LazyCoeffBaseProductType,0>(CoeffBaseProductType(m_lhs, m_rhs)); } + { return LazyCoeffBaseProductType(m_lhs, m_rhs); } Diagonal<LazyCoeffBaseProductType,0> diagonal() - { return Diagonal<LazyCoeffBaseProductType,0>(CoeffBaseProductType(m_lhs, m_rhs)); } + { return LazyCoeffBaseProductType(m_lhs, m_rhs); } template<int Index> const Diagonal<LazyCoeffBaseProductType,Index> diagonal() const - { return Diagonal<LazyCoeffBaseProductType,Index>(CoeffBaseProductType(m_lhs, m_rhs)); } + { return LazyCoeffBaseProductType(m_lhs, m_rhs); } template<int Index> Diagonal<LazyCoeffBaseProductType,Index> diagonal() - { return Diagonal<LazyCoeffBaseProductType,Index>(CoeffBaseProductType(m_lhs, m_rhs)); } + { return LazyCoeffBaseProductType(m_lhs, m_rhs); } const Diagonal<LazyCoeffBaseProductType,Dynamic> diagonal(int index) const - { return Diagonal<LazyCoeffBaseProductType,Dynamic>(LazyCoeffBaseProductType(CoeffBaseProductType(m_lhs, m_rhs))).diagonal(index); } + { return LazyCoeffBaseProductType(m_lhs, m_rhs).diagonal(index); } Diagonal<LazyCoeffBaseProductType,Dynamic> diagonal(int index) - { return Diagonal<LazyCoeffBaseProductType,Dynamic>(LazyCoeffBaseProductType(CoeffBaseProductType(m_lhs, m_rhs))).diagonal(index); } + { return LazyCoeffBaseProductType(m_lhs, m_rhs).diagonal(index); } // Implicit convertion to the nested type (trigger the evaluation of the product) operator const PlainMatrixType& () const diff --git a/Eigen/src/Core/products/GeneralCoeffBased.h b/Eigen/src/Core/products/CoeffBasedProduct.h index 0cca2d417..d947bfc58 100644 --- a/Eigen/src/Core/products/GeneralCoeffBased.h +++ b/Eigen/src/Core/products/CoeffBasedProduct.h @@ -23,11 +23,14 @@ // License and a copy of the GNU General Public License along with // Eigen. If not, see <http://www.gnu.org/licenses/>. -#ifndef EIGEN_GENERAL_UNROLLED_PRODUCT_H -#define EIGEN_GENERAL_UNROLLED_PRODUCT_H +#ifndef EIGEN_COEFFBASED_PRODUCT_H +#define EIGEN_COEFFBASED_PRODUCT_H /********************************************************************************* -* Specialization of GeneralProduct<> for products with small fixed sizes +* Coefficient based product implementation. +* It is designed for the following use cases: +* - small fixed sizes +* - lazy products *********************************************************************************/ /* Since the all the dimensions of the product are small, here we can rely @@ -42,8 +45,8 @@ struct ei_product_coeff_impl; template<int StorageOrder, int Index, typename Lhs, typename Rhs, typename PacketScalar, int LoadMode> struct ei_product_packet_impl; -template<typename LhsNested, typename RhsNested> -struct ei_traits<GeneralProduct<LhsNested,RhsNested,CoeffBasedProduct> > +template<typename LhsNested, typename RhsNested, int NestingFlags> +struct ei_traits<CoeffBasedProduct<LhsNested,RhsNested,NestingFlags> > { typedef DenseStorageMatrix DenseStorageType; typedef typename ei_cleantype<LhsNested>::type _LhsNested; @@ -79,14 +82,13 @@ struct ei_traits<GeneralProduct<LhsNested,RhsNested,CoeffBasedProduct> > RemovedBits = ~(EvalToRowMajor ? 0 : RowMajorBit), Flags = ((unsigned int)(LhsFlags | RhsFlags) & HereditaryBits & RemovedBits) - | EvalBeforeAssigningBit - | EvalBeforeNestingBit + | NestingFlags | (CanVectorizeLhs || CanVectorizeRhs ? PacketAccessBit : 0) | (LhsFlags & RhsFlags & AlignedBit), - CoeffReadCost = InnerSize == Dynamic ? Dynamic - : InnerSize * (NumTraits<Scalar>::MulCost + LhsCoeffReadCost + RhsCoeffReadCost) - + (InnerSize - 1) * NumTraits<Scalar>::AddCost, + CoeffReadCost = 1000,//InnerSize == Dynamic ? Dynamic +// : InnerSize * (NumTraits<Scalar>::MulCost + LhsCoeffReadCost + RhsCoeffReadCost) +// + (InnerSize - 1) * NumTraits<Scalar>::AddCost, /* CanVectorizeInner deserves special explanation. It does not affect the product flags. It is not used outside * of Product. If the Product itself is not a packet-access expression, there is still a chance that the inner @@ -98,25 +100,27 @@ struct ei_traits<GeneralProduct<LhsNested,RhsNested,CoeffBasedProduct> > }; }; -template<typename LhsNested, typename RhsNested> class GeneralProduct<LhsNested,RhsNested,CoeffBasedProduct> +template<typename LhsNested, typename RhsNested, int NestingFlags> +class CoeffBasedProduct : ei_no_assignment_operator, - public MatrixBase<GeneralProduct<LhsNested, RhsNested, CoeffBasedProduct> > + public MatrixBase<CoeffBasedProduct<LhsNested, RhsNested, NestingFlags> > { public: - typedef MatrixBase<GeneralProduct> Base; - EIGEN_DENSE_PUBLIC_INTERFACE(GeneralProduct) + typedef MatrixBase<CoeffBasedProduct> Base; + EIGEN_DENSE_PUBLIC_INTERFACE(CoeffBasedProduct) + typedef typename Base::PlainMatrixType PlainMatrixType; private: - typedef typename ei_traits<GeneralProduct>::_LhsNested _LhsNested; - typedef typename ei_traits<GeneralProduct>::_RhsNested _RhsNested; + typedef typename ei_traits<CoeffBasedProduct>::_LhsNested _LhsNested; + typedef typename ei_traits<CoeffBasedProduct>::_RhsNested _RhsNested; enum { PacketSize = ei_packet_traits<Scalar>::size, - InnerSize = ei_traits<GeneralProduct>::InnerSize, + InnerSize = ei_traits<CoeffBasedProduct>::InnerSize, Unroll = CoeffReadCost <= EIGEN_UNROLLING_LIMIT, - CanVectorizeInner = ei_traits<GeneralProduct>::CanVectorizeInner + CanVectorizeInner = ei_traits<CoeffBasedProduct>::CanVectorizeInner }; typedef ei_product_coeff_impl<CanVectorizeInner ? InnerVectorizedTraversal : DefaultTraversal, @@ -126,7 +130,7 @@ template<typename LhsNested, typename RhsNested> class GeneralProduct<LhsNested, public: template<typename Lhs, typename Rhs> - inline GeneralProduct(const Lhs& lhs, const Rhs& rhs) + inline CoeffBasedProduct(const Lhs& lhs, const Rhs& rhs) : m_lhs(lhs), m_rhs(rhs) { // we don't allow taking products of matrices of different real types, as that wouldn't be vectorizable. @@ -171,11 +175,27 @@ template<typename LhsNested, typename RhsNested> class GeneralProduct<LhsNested, return res; } + // Implicit convertion to the nested type (trigger the evaluation of the product) + operator const PlainMatrixType& () const + { + m_result = *this; + return m_result; + } + protected: const LhsNested m_lhs; const RhsNested m_rhs; + + mutable PlainMatrixType m_result; }; +// here we need to overload the nested rule for products +// such that the nested type is a const reference to a plain matrix +template<typename Lhs, typename Rhs, int N, typename PlainMatrixType> +struct ei_nested<CoeffBasedProduct<Lhs,Rhs,EvalBeforeNestingBit|EvalBeforeAssigningBit>, N, PlainMatrixType> +{ + typedef PlainMatrixType const& type; +}; /*************************************************************************** * Normal product .coeff() implementation (with meta-unrolling) @@ -386,4 +406,4 @@ struct ei_product_packet_impl<ColMajor, Dynamic, Lhs, Rhs, PacketScalar, LoadMod } }; -#endif // EIGEN_GENERAL_UNROLLED_PRODUCT_H +#endif // EIGEN_COEFFBASED_PRODUCT_H diff --git a/Eigen/src/Core/util/Constants.h b/Eigen/src/Core/util/Constants.h index dc7b3eea9..51590b03d 100644 --- a/Eigen/src/Core/util/Constants.h +++ b/Eigen/src/Core/util/Constants.h @@ -269,6 +269,6 @@ namespace Architecture enum DenseStorageMatrix {}; enum DenseStorageArray {}; -enum { OuterProduct, InnerProduct, CoeffBasedProduct, GemvProduct, GemmProduct }; +enum { CoeffBasedProductMode, LazyCoeffBasedProductMode, OuterProduct, InnerProduct, GemvProduct, GemmProduct }; #endif // EIGEN_CONSTANTS_H diff --git a/Eigen/src/Core/util/ForwardDeclarations.h b/Eigen/src/Core/util/ForwardDeclarations.h index ac7824dc1..aed0abe6d 100644 --- a/Eigen/src/Core/util/ForwardDeclarations.h +++ b/Eigen/src/Core/util/ForwardDeclarations.h @@ -49,9 +49,10 @@ template<typename NullaryOp, typename MatrixType> class CwiseNullaryOp; template<typename UnaryOp, typename MatrixType> class CwiseUnaryOp; template<typename ViewOp, typename MatrixType> class CwiseUnaryView; template<typename BinaryOp, typename Lhs, typename Rhs> class CwiseBinaryOp; -template<typename BinOp, typename MatrixType> class SelfCwiseBinaryOp; +template<typename BinOp, typename MatrixType> class SelfCwiseBinaryOp; template<typename Derived, typename Lhs, typename Rhs> class ProductBase; -template<typename Lhs, typename Rhs, int Mode> class GeneralProduct; +template<typename Lhs, typename Rhs, int Mode> class GeneralProduct; +template<typename Lhs, typename Rhs, int NestingFlags> class CoeffBasedProduct; template<typename Derived> class DiagonalBase; template<typename _DiagonalVectorType> class DiagonalWrapper; diff --git a/Eigen/src/Core/util/StaticAssert.h b/Eigen/src/Core/util/StaticAssert.h index 56a57b706..619e7664d 100644 --- a/Eigen/src/Core/util/StaticAssert.h +++ b/Eigen/src/Core/util/StaticAssert.h @@ -61,6 +61,7 @@ THIS_METHOD_IS_ONLY_FOR_VECTORS_OF_A_SPECIFIC_SIZE, THIS_METHOD_IS_ONLY_FOR_MATRICES_OF_A_SPECIFIC_SIZE, YOU_MADE_A_PROGRAMMING_MISTAKE, + EIGEN_INTERNAL_COMPILATION_ERROR_OR_YOU_MADE_A_PROGRAMMING_MISTAKE, YOU_CALLED_A_FIXED_SIZE_METHOD_ON_A_DYNAMIC_SIZE_MATRIX_OR_VECTOR, YOU_CALLED_A_DYNAMIC_SIZE_METHOD_ON_A_FIXED_SIZE_MATRIX_OR_VECTOR, UNALIGNED_LOAD_AND_STORE_OPERATIONS_UNIMPLEMENTED_ON_ALTIVEC, |