Submatrix view from indices in Eigen

2019-09-08 08:22发布

问题:

Is it possible in Eigen to do the equivalent of the following operation in Matlab?

A=rand(10,10);
indices = [2,5,6,8,9];

B=A(indices,indices)

I want to have a submatrix as a view on the original matrix with given, non consecutive indices. The best option would be to have a shared memory view of the original matrix, is this possible?

I've figured out a method that works but is not very fast, since it involves non vectorized for loops:

MatrixXi slice(const MatrixXi &A, const std::set<int> &indices)
{
    int n = indices.size();
    Eigen::MatrixXi B;
    B.setZero(n,n);

    std::set<int>::const_iterator iInd1 = indices.begin();
    for (int i=0; i<n;++i)
    {
        std::set<int>::const_iterator iInd2=indices.begin();
        for (int j=0; j<n;++j)
        {
            B(i,j) = A.coeffRef(*iInd1,*iInd2);
            ++iInd2;
        }
        ++iInd1;
    }

    return B;
}

How can this be made faster?

回答1:

Make your matrix traversal col-major (which is default in Eigen) http://eigen.tuxfamily.org/dox-devel/group__TopicStorageOrders.html

Disable debug asserts, EIGEN_NO_DEBUG, see http://eigen.tuxfamily.org/dox/TopicPreprocessorDirectives.html, as the comment by Deepfreeze suggested.

It is very non-trivial to implement vectorized version since elements are not contiguous in general. If you are up to it, take a look at AVX2 gather instructions (provided you have CPU with AVX2 support)

To implement matrix view (you called it shared-memory) you'd need to implement an Eigen expression, which is not too hard if you are well versed in C++ and know Eigen codebase. I can help you to get started if you so want.