* added innerSize / outerSize functions to MatrixBase

* added complete implementation of sparse matrix product
  (with a little glue in Eigen/Core)
* added an exhaustive bench of sparse products including GMM++ and MTL4
  => Eigen outperforms in all transposed/density configurations !
This commit is contained in:
Gael Guennebaud
2008-06-28 23:07:14 +00:00
parent 6917be9113
commit 027818d739
16 changed files with 622 additions and 380 deletions

View File

@@ -204,8 +204,8 @@ struct ei_assign_impl<Derived1, Derived2, NoVectorization, NoUnrolling>
static void run(Derived1 &dst, const Derived2 &src)
{
const bool rowMajor = int(Derived1::Flags)&RowMajorBit;
const int innerSize = rowMajor ? dst.cols() : dst.rows();
const int outerSize = rowMajor ? dst.rows() : dst.cols();
const int innerSize = dst.innerSize();
const int outerSize = dst.outerSize();
for(int j = 0; j < outerSize; j++)
for(int i = 0; i < innerSize; i++)
{
@@ -233,7 +233,7 @@ struct ei_assign_impl<Derived1, Derived2, NoVectorization, InnerUnrolling>
{
const bool rowMajor = int(Derived1::Flags)&RowMajorBit;
const int innerSize = rowMajor ? Derived1::ColsAtCompileTime : Derived1::RowsAtCompileTime;
const int outerSize = rowMajor ? dst.rows() : dst.cols();
const int outerSize = dst.outerSize();
for(int j = 0; j < outerSize; j++)
ei_assign_novec_InnerUnrolling<Derived1, Derived2, 0, innerSize>
::run(dst, src, j);
@@ -250,8 +250,8 @@ struct ei_assign_impl<Derived1, Derived2, InnerVectorization, NoUnrolling>
static void run(Derived1 &dst, const Derived2 &src)
{
const bool rowMajor = int(Derived1::Flags)&RowMajorBit;
const int innerSize = rowMajor ? dst.cols() : dst.rows();
const int outerSize = rowMajor ? dst.rows() : dst.cols();
const int innerSize = dst.innerSize();
const int outerSize = dst.outerSize();
const int packetSize = ei_packet_traits<typename Derived1::Scalar>::size;
for(int j = 0; j < outerSize; j++)
{
@@ -282,7 +282,7 @@ struct ei_assign_impl<Derived1, Derived2, InnerVectorization, InnerUnrolling>
{
const bool rowMajor = int(Derived1::Flags)&RowMajorBit;
const int innerSize = rowMajor ? Derived1::ColsAtCompileTime : Derived1::RowsAtCompileTime;
const int outerSize = rowMajor ? dst.rows() : dst.cols();
const int outerSize = dst.outerSize();
for(int j = 0; j < outerSize; j++)
ei_assign_innervec_InnerUnrolling<Derived1, Derived2, 0, innerSize>
::run(dst, src, j);
@@ -337,8 +337,8 @@ struct ei_assign_impl<Derived1, Derived2, SliceVectorization, NoUnrolling>
{
const int packetSize = ei_packet_traits<typename Derived1::Scalar>::size;
const bool rowMajor = Derived1::Flags&RowMajorBit;
const int innerSize = rowMajor ? dst.cols() : dst.rows();
const int outerSize = rowMajor ? dst.rows() : dst.cols();
const int innerSize = dst.innerSize();
const int outerSize = dst.outerSize();
const int alignedInnerSize = (innerSize/packetSize)*packetSize;
for(int i = 0; i < outerSize; i++)

View File

@@ -154,11 +154,20 @@ template<typename Derived> class MatrixBase
/** \returns the number of coefficients, which is \a rows()*cols().
* \sa rows(), cols(), SizeAtCompileTime. */
inline int size() const { return rows() * cols(); }
/** \returns the number of nonzero coefficients which is in practice the number
* of stored coefficients. */
inline int nonZeros() const { return derived.nonZeros(); }
/** \returns true if either the number of rows or the number of columns is equal to 1.
* In other words, this function returns
* \code rows()==1 || cols()==1 \endcode
* \sa rows(), cols(), IsVectorAtCompileTime. */
inline bool isVector() const { return rows()==1 || cols()==1; }
/** \returns the size of the storage major dimension,
* i.e., the number of columns for a columns major matrix, and the number of rows otherwise */
int outerSize() const { return (int(Flags)&RowMajorBit) ? this->rows() : this->cols(); }
/** \returns the size of the inner dimension according to the storage order,
* i.e., the number of rows for a columns major matrix, and the number of cols otherwise */
int innerSize() const { return (int(Flags)&RowMajorBit) ? this->cols() : this->rows(); }
/** Represents a constant matrix */
typedef CwiseNullaryOp<ei_scalar_constant_op<Scalar>,Derived> ConstantReturnType;
@@ -206,6 +215,10 @@ template<typename Derived> class MatrixBase
template<typename Derived1, typename Derived2>
Derived& lazyAssign(const Product<Derived1,Derived2,CacheFriendlyProduct>& product);
/** Overloaded for sparse product evaluation */
template<typename Derived1, typename Derived2>
Derived& lazyAssign(const Product<Derived1,Derived2,SparseProduct>& product);
CommaInitializer operator<< (const Scalar& s);
template<typename OtherDerived>

View File

@@ -92,6 +92,8 @@ template<typename Lhs, typename Rhs> struct ei_product_mode
{
enum{ value = ((Rhs::Flags&Diagonal)==Diagonal) || ((Lhs::Flags&Diagonal)==Diagonal)
? DiagonalProduct
: (Rhs::Flags & Lhs::Flags & SparseBit)
? SparseProduct
: Lhs::MaxRowsAtCompileTime >= EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD
&& Rhs::MaxColsAtCompileTime >= EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD
&& Lhs::MaxColsAtCompileTime >= EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD
@@ -147,8 +149,7 @@ struct ei_traits<Product<LhsNested, RhsNested, ProductMode> >
CanVectorizeInner = LhsRowMajor && (!RhsRowMajor) && (LhsFlags & PacketAccessBit) && (RhsFlags & PacketAccessBit)
&& (InnerSize!=Dynamic) && (InnerSize % ei_packet_traits<Scalar>::size == 0),
EvalToRowMajor = (RhsFlags & RowMajorBit)
&& (ProductMode==(int)CacheFriendlyProduct ? (int)LhsFlags & RowMajorBit : (!CanVectorizeLhs)),
EvalToRowMajor = RhsRowMajor && (ProductMode==(int)CacheFriendlyProduct ? LhsRowMajor : (!CanVectorizeLhs)),
RemovedBits = ~((EvalToRowMajor ? 0 : RowMajorBit)
| ((RowsAtCompileTime == Dynamic || ColsAtCompileTime == Dynamic) ? 0 : LargeBit)),

View File

@@ -71,7 +71,7 @@ template<typename MatrixType> class Transpose
inline int rows() const { return m_matrix.cols(); }
inline int cols() const { return m_matrix.rows(); }
inline int nonZeros() const { return m_matrix.nonZeros(); }
inline int stride(void) const { return m_matrix.stride(); }
inline Scalar& coeffRef(int row, int col)

View File

@@ -211,6 +211,11 @@ template<typename T> struct ei_unref<T&> { typedef T type; };
template<typename T> struct ei_unconst { typedef T type; };
template<typename T> struct ei_unconst<const T> { typedef T type; };
template<typename T> struct ei_cleantype { typedef T type; };
template<typename T> struct ei_cleantype<const T> { typedef T type; };
template<typename T> struct ei_cleantype<const T&> { typedef T type; };
template<typename T> struct ei_cleantype<T&> { typedef T type; };
template<typename T> struct ei_must_nest_by_value { enum { ret = false }; };
template<typename T> struct ei_must_nest_by_value<NestByValue<T> > { enum { ret = true }; };