Externalizing data from an Eigen matrix
Asked Answered
F

1

7

I'm trying to take ownership of the memory backing an Eigen::Matrix without copying the memory. The data() method retains ownership. The only way I've figured out how to do this is by swapping the mapped array:

Matrix<float, Dynamic, Dynamic, RowMajor> mat = m1 * m2;
// want ownership of mat's float*

float* data = mat.data(); // get the pointer
new (&mat) Eigen::Map<Matrix3f>(NULL); // swap the mapped array with anything else
// do something with data

It doesn't look like this causes a copy under the hood, but I'm not positive. I'm also not sure that this is safe.

Freemasonry answered 21/2, 2017 at 21:20 Comment(7)
Why not just keep the Eigen matrix object alive while you need its data?Laevo
@Laevo I need to hand the data off to another environment where I don't have that much control.Freemasonry
That is a very unclear statement. I still don't see the problem with keeping the Eigen object alive while that other environment does its thing.Laevo
@rubenv sorry -- basically I'm providing an API function that returns a float *.Freemasonry
Then you can provide the contract for how to handle that memory. And that means you can store the Eigen object until a user calls a certain "free" function, at which point you delete the object associated with the pointer. If the user then decides to do something bad, well, there wasn't anything you could have ever done to prevent that. We are talking C(++) here.Laevo
@Freemasonry A float* isn't a full API. A float* allocated by what means, and freed by what means? In C/C++ you must always keep track of who owns what, and how to dispose of leftover data. If you fail, you end up with leaks and corruption and mess.Blacken
Sorry for being cryptic -- This is a binding to another language, which wraps the float* and takes ownership of its memory, taking care of freeing it.Freemasonry
B
5

Tearing memory out of the guts of Eigen is impolite, not the least of which because you don't know how it was allocated or what else the Matrix owned.

There is, however, the Map template, which lets you wrap an unowned buffer into a Eigen-matrix-like type.

This type isn't an actual eigen matrix, so your own custom functions may not work with it, but it should work with Eigen functions.

In this case, you already own the data.

using matrix_type = Matrix<float, Dynamic, Dynamic, RowMajor>;
using mapped_matrix_type = Map<matrix_type>;

Now we create a buffer, wrap it in a mapped_matrix_type, and assign:

auto raw = std::make_unique<float[]>(m1.rows()*m2.cols()); // maybe backwards
mapped_matrix_type bob(raw.get(), m1.rows(), m2.cols());
bob = m1*m2;

the raw data of the bob is in raw, a unique_ptr owned buffer (which can release() if you need to to make it totally unowned).

Any raw storage mechanism (vector, raw new, whatever else) can take the place of raw.

Code not tested.

Blacken answered 21/2, 2017 at 21:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.