Subject: Re: [proto] Using proto with expressions containing matrices from the EIgen library
From: Bart Janssens (bart.janssens_at_[hidden])
Date: 2010-10-27 15:57:47
On Wed, Oct 27, 2010 at 6:57 PM, Eric Niebler <eric_at_[hidden]> wrote:
> Are you saying that proto::eval is generating temporary matrices? I
> don't understand why, but there's always a way to get Proto to store
> intermediate nodes by value instead of by reference. Without knowing
> what you're doing, I can't say more.
No, but the return value of the operator() in the eval structs in the
context (in my first attempt) or the object created by the object
transform is sometimes stored by reference in the Eigen expression
templates. I'll give more details on what exactly I need below, based
on the sample I posted to the Eigen forum.
> Can ContextEvaluator ever return a reference to a temporary object? Is
> Eigen::ProductReturnType<Left, Right>::Type ever a reference? Does that
> type hold Left and Right by reference?
Yes, sometimes, and that is exactly the problem :) It deduces the need
for by-reference storage if it would otherwise need to do an expensive
copy, so it is crucial that this system can do its job in order to
preserve the performance of Eigen.
> Looking at that code, I strongly suspect that
> Eigen::ProductReturnType<Left, Right>::Type is a type that holds Right
> by reference. In fact, I'm 99% sure it does. Print the name of the
> resulting type of Eigen::ProductReturnType<Left, Right>::Type and see if
> that's the case. If so, you've found your bug. Can you see why?
Yup, it took me a while to figure out, but the purpose of the sample I
posted to Eigen is indeed to show this: the result of multb is stored
by reference in the result of multa, and this only gets evaluated on
the call to operator<<, so it tries to access a dangling reference to
the multb result which disappeared. In proto, multb becomes operator()
of an eval struct in a context, or the object constructed using an
So to rephrase my question:
let's say I want to evaluate proto expression "_cout << A * B * C". To
do this, I traverse the tree and the following should happen:
1. B * C gets evaluated first, into an (Eigen) expression template
that stores a reference to B and C. This is OK, since B and C are not
2. A*(result of B*C) gets evaluated, which may produce something
that stores (result of B*C) by reference
3. The final expression result is output using <<, and at that point
the Eigen expression templates execute, expecting that all the
referred variables still exist.
So how can I make sure the (result of B*C) gets stored somewhere? If I
can do that, then I can use this stored data to construct the
A*(result of B*C) step, and it's safe even if it is done by reference.
For more complex expressions, all the steps in the tree would need to
be stored like this. Once the call to operator<< finishes, this
"temporary tree" can be discarded.
The problem I have here appears to be general to expression template
matrix libraries, before Eigen we used our own matrix lib, and it
exhibited the same problem.
Proto list run by eric at boostpro.com