Registered Member
|
Hi folks,
during development I have run into a problem with Eigen expressions. I have tried to create a minimal example (see below). The classes MockEquationSystem and MockTimeDeriv are mock classes for unit tests and should represent components of an equation system. I have some additional glue code that adds them together and should produce code as in the lambda g. I have also created the other lambda f which should in theory produce the same result as g. However when I run it, then the result of f is printed and as soon as g() is called, the program segfaults. I compiled it with:
with gdb I can reproduce the following back trace:
Interestingly, if I let the compiler optimize (additional -O3), then there is no segfault. But the output of f() and g() is not equal. Also with experimenting, I found out that the problem is in MockTimeDeriv, specifically in the part that eval returns the parameter x. When it doesn't return it, everything is fine. However I don't really get this, as MockEquationSystem also returns a function of x.
Thank you in advance for any suggestions since I am stuck. |
Moderator
|
Please don't abuse of the "auto" keyword when using expression template libraries. Your code creates a lot of expression referencing dead objects, see: http://eigen.tuxfamily.org/dox-devel/TopicPitfalls.html
|
Registered Member
|
Hi,
I was puzzled by your answer at first, since I can evaluate the single components without any problems, so I thought that shouldn't be a problem. So I forbid Eigen to allocate memory for temporaries and found out that MockEquationSystem seems to create a temporary during a call to eval(). I guess that could be probably one of the issues that leads to the segfault. This leads me to another question. Provided I should not use auto, how can I create expressions otherwise in an elegant way? I would like to be able to create something as the function f() does for different cases (e.g. only 1 or 2 MockEquationSystem or completely different components). How could I accomplish that without having to write every single case by hand (when I should not create functions return expressions)? Thanks for any suggestions |
Moderator
|
Yes, .eval() evaluate the expression and returns a temporary Matrix<> object (or Array or SparseMatrix, etc.).
Ok, auto is not always a bad idea, if you are 100% sure that 1) you really want an expression and not a Matrix-like object type, and 2) that no temporary has been created on the way. Regarding this second aspect, I strongly recommend you to move to Eigen3.3 (beta1 or devel branch) because in 3.2, some subexpressions are directly evaluated within a temporary (e.g., matrix products). So in your case this concerns matrix-vector products like "m1.A() * x". You can either move to 3.3, or if N is typically very small (say <20), move to lazy-products: m1.A().lazyProduct(x) which lazily evaluates the product in a coefficient-wise manner. |
Registered Member
|
I have tried your suggestion with using 3.3 and it fixed the segfault. Thank you for your help!
|
Registered users: Bing [Bot], Evergrowing, Google [Bot], rockscient