Registered Member
|
I have read the eigen documentation on this back to front, and probably the most relevant document is the page on Writing Functions Taking Eigen Types as Parameters, which discusses void functions taking non-const references of Eigen types and modifying them. I am currently trying to write functions which build Eigen types (either expressions or matrices) and returns them by value. They are then received as const references by other functions which perform further operations on them.
This works fine until I try to perform an operation that actually creates a matrix. For example, the following function concatenates two matrices together:
Other functions then take the output of this function by const reference and perform other operations. However, this is giving me all sorts of errors in valgrind as well as garbage values. I haven't been able to reproduce the problem in a confined example, but I thought I'd ask here first to see if there was anything wrong with this kind of function. What other considerations are there to be taken into account when returning by value rather than modifying existing Eigen objects? |
Moderator
|
I don't see anything wrong in this precise example. The typical problem is when returning an expression involving temporary matrices created in the function itself, like:
because the returned Transpose expression stores a reference to tmp which is dead. But in your example you are returning a Matrix, not an expression. So you should be fine. |
Registered Member
|
Thanks ggael. I created the following test program to see what would happen if I pass the output of my Concatenate function into another function (which just passes it straight through). Here is the program:
I ran this program through valgrind with the --track-origins=yes flag and got a series of errors, namely uninitialised values. Why is this occuring? My understanding is that Pass should keep the output of Concatenate alive because it keeps a const reference, and auto Matrix should store the output by value. What's wrong with the above code, and how would you go about making this work without creating redundant copies? The following version of Pass avoids these errors, but I don't really understand why this works and the above doesn't:
|
Moderator
|
The problem is the "Pass" function which incorrectly return a DenseBase by value. You cannot create a DenseBase object: DenseBase is an empty abstract base class. Ideally, this example should fail to compile but we don't know how to do so.
|
Registered Member
|
Thanks Ggael. It sounds like you don't want to permit the object to be copy-constructed:
|
Moderator
|
Sure, but Eigen has to be C++03 compatible, so we have to emulate this feature by making it private, and manually implement the copy ctor of the numerous derived classes and verify that the compiler is still able to optimize out the numerous copies that occurs when assembling complex expressions...
|
Registered Member
|
Dear Gael,
I have a question about lazy evaluation related to the above question. My intuition says that even in C++11, returning matrices (or other eigen types) in the following way: template<typename Derived> Matrix<Derived::Scalar,Dynamic,Dynamic> myfunc(const MatrixBase<Derived> & inputParam) { Matrix<Derived::Scalar,Dynamic,Dynamic> retM; // assign to retM return retM; } will always trigger evaluation of retM. I mean, if I want lazy evaluation, then I still need to follow the "c++98-const_cast-hack" approach: template<typename DerivedA, typename DerivedB> void myfunc(const MatrixBase<DerivedA> & inputParam, const MatrixBase<DerivedB>& outputParam) { MatrixBase<DerivedB> & writableOutput = const_cast<decltype(writableOutput)>(outputParam); // write here to writableOutput } Is my intuition correct? Or is the first method also compatible with eigen's lazy evaluation system in C++11 because of move semantics? best regards, Niek [ EDIT ]: I've just seen that you've already answered a related question in the "Returning generic Eigen types" post started by alecjacobson https://forum.kde.org/viewtopic.php?f=74&t=130338 |
Moderator
|
Looks like you are misusing the concept of "lazy-evaluation". Actually what you are looking for is not lazy evaluation, but a way to write functions returning matrix-like objects and avoid any temp/copy if it is directly assigned to an object having some storage like:
so as you see, some trivial cases are already optimized away by the compiler. For the others, you indeed can refer the this thread: viewtopic.php?f=74&t=130338 |
Registered users: bartoloni, Bing [Bot], Evergrowing, Google [Bot], ourcraft