Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Eigen::MatrixXd to flann::Matrix<double> conversion

Assume that mat below is of type Eigen::MatrixXd and already contains some data. In an attempt to avoid duplicating memory, I tried to instantiate a flann::Matrix<double> object from the pointer to the raw memory chunk allocated by Eigen3:

flann::Matrix<double> input(const_cast<double *>(mat.data(), mat.rows(), mat.cols())

However, my algorithm outputs garbage, but is just fine with the ugly:

flann::Matrix<double> input(new double[mat.rows()*mat.cols()], mat.rows(),  mat.cols());
for (int i = 0; i  < mat.rows(); i++) {
for (int j = 0; j < mat.cols(); j++) {
  input[i][j] = mat(i, j);
}

}

I investigated the option to subclass the base Matrix_ type from flann to create an adaptor to Eigen3 matrices. The problem though is that Matrix_ relies on the implementation of the [] operator in its interace. It makes me feel that I might encounter the same memory issue than in the simple (but broken) solution shown above.

What do you think could explain such behaviour ?

  • Row/column-major issue
  • Inner, outer stride issue
  • Memory alignment incompatibilities
  • Eigen::Map is sweet, but not what I'm looking for. It would suck to re-write my code to use stl::vector<std::vector<double> > as base types and Eigen::Map them to Eigen::MatrixXd
  • http://nanoflann-reference.mrpt.org/svn/structnanoflann_1_1KDTreeEigenMatrixAdaptor.html unfortunately too far from the base libflann library to be usable.
like image 238
Pierre-Luc Bacon Avatar asked Nov 20 '12 02:11

Pierre-Luc Bacon


People also ask

How do I resize an eigen matrix?

Resizing. The current size of a matrix can be retrieved by rows(), cols() and size(). These methods return the number of rows, the number of columns and the number of coefficients, respectively. Resizing a dynamic-size matrix is done by the resize() method.

Is Eigen row or column major?

The default in Eigen is column-major. Naturally, most of the development and testing of the Eigen library is thus done with column-major matrices. This means that, even though we aim to support column-major and row-major storage orders transparently, the Eigen library may well work best with column-major matrices.

What is VectorXd?

The next line of the main function introduces a new type: VectorXd . This represents a (column) vector of arbitrary size. Here, the vector v is created to contain 3 coefficients which are left uninitialized.


2 Answers

I also got confirmation from Marius Muja, the author of libflann, that flann::Matrix stores in row-major order whereas Eigen uses column-major by default. Here's the answer that he gave me by email:

The problem is most likely the fact that Eigen stores matrices in column-major order > while FLANN requires them in row-major order.

A solution would be to use Matrix<double, Dynamic, Dynamic, RowMajor> instead of MatrixXd, then FLANN and Eigen matrices can share the same memory, otherwise a copy will be needed. Marius Muja

like image 108
Pierre-Luc Bacon Avatar answered Oct 11 '22 10:10

Pierre-Luc Bacon


Eigen::Matrix store data continously, so you shouldn't get stride problems. Alignment may be the problem if you are trying to construct an Eigen::Matrix on it (but I can't imagine how this is possible). By default Eigen::Matrix is column-major, this may be your problem. I don't know how flann treat matrices, if they are row-major, then that's it. The following example work with Eigen::Matrix< double, -1, -1, Eigen::RowMajor > for mat and fails with Eigen::MatrixXd.

int k = 0;
for (int i = 0; i<mat.rows(); ++i)
{
    for (int j = 0; j<mat.cols(); ++j, ++k) {
        mat(i, j) = k;
    }
}

double* mptr = mat.data();
for (int i = 0; i<mat.rows() * mat.cols(); ++i) {
    assert(mptr[i] == i);
}

I haven't got your complain about Eigen::Map. It is the nicest way to treat some data as eigen matrix (note that it will still be column-major by default), subclassing from matrix, or implementing custom eigen expression may be painfull.

like image 37
DikobrAz Avatar answered Oct 11 '22 10:10

DikobrAz