Re: [eigen] about .lazy() |

[ Thread Index | Date Index | More lists.tuxfamily.org/eigen Archives ]

*To*: eigen@xxxxxxxxxxxxxxxxxxx*Subject*: Re: [eigen] about .lazy()*From*: Benoit Jacob <jacob.benoit.1@xxxxxxxxx>*Date*: Sat, 15 Aug 2009 17:48:34 -0400*Dkim-signature*: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:mime-version:received:in-reply-to:references :date:message-id:subject:from:to:content-type :content-transfer-encoding; bh=M/9HYyrmD0ettvo1JXrronmDMv3BLWhH3qgMDciDuIo=; b=UuuJKLvpw6Rksx3xVzJP3XsdXA0tk2Rp7NOaSTN9xAkNae1+pE3NI5uTi5RO3IYWEP vAaRPijG1Qfcu9hmQUF/RCI6xQrk7i6p0vkYJDz9HErykotDSgp+Fwtd8alOeBOegxkT WciGFRZBiTS1WaOgCrn6Wu0rKgX/cVuoTJM9Q=*Domainkey-signature*: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :content-type:content-transfer-encoding; b=vXa6VYm3cAbAphOfxxhU0IUT3auQJD1gTqIeMtbIpKpVxlL3DlCK+G7sKP9gUaxZcU O+OzOt9eTc9lKNrnsGppHVUENjLjdoFkiV2Dsy6TgC5WGvSI3MsT9vLTBP04KSB/TbhO 782wFM2oSWqzBwZmp3WL/tPWa7UChq2d6asvU=

2009/8/15 Gael Guennebaud <gael.guennebaud@xxxxxxxxx>: > On Sat, Aug 15, 2009 at 10:48 PM, Benoit Jacob<jacob.benoit.1@xxxxxxxxx> wrote: >> Mostly, indeed. Initially we didn't know to which expressions it would >> apply. Indeed it turns out that it's almost only product expressions. >> There are exceptions too: at least the Random expression (more >> generally any non-repeatable nullaryExpr, but afaik it's the only one >> so far). > > hm, right I forgot about that, but Random only have the > EvalBeforeNestingBit flags, so do we still need a way to remove that > flag ? If so .lazy() would be perfect but if we keep .lazy() for that > purpose we'll have strong backward compatibility issues. Unless we > overload .lazy() in CwiseNullaryOp... Oh I wasn't advocating keeping lazy(), even for that. Probably nobody cares that much about the performance of random matrices. The use case is very niche. If by now we haven't found a better use case, that probably means that it's OK to remove lazy(). >> I don't really understand the difference between c1 and c2, indeed >> lazy() used to do 2 things, remove EvalBeforeAssigning and >> EvalBeforeNesting flags, i guess that's what you meant. Anyway it >> doesn't matter. > > yes that's what I meant, and basically .lazy() would be good at > removing EvalBeforeNestingBit only (e.g., for Random) and .noalias() > to bypass EvalBeforeAssigning. Our mistake was to use .lazy() for > both. OK. You decide if you want to keep such a lazy() or remove it altogether (keeping it deprecated for now), I don't have a strong preference. >>> So to summary, I'd be in favor in removing .lazy(), replace the >>> EvalBeforeAssignBit flag by a MightAliasBit flag, and add a no-alias >>> mechanism on the result side. >> >> OK so a.noalias() = xpr would be the way to obtain what you called the >> "optimal" solution, right? > > hm, not really because: > > D.noalias() = A*B + C; > > it is the same as: > > D.lazyAssign( (A*B) + C); > > which is the same as: > > D = (A*B).eval() + C; > > But here you can avoid a temporary and still have an efficient > evaluation of the product by doing: > > D = C; > D.noalias() += A*B; > > (best for dynamic sizes) > > or: > > D.noalias() += A*B; > D += C; > > (best for small fixed sizes) Hm. Rather fascinating! And do you have a plan to make Eigen decide that automatically? >> But I have a question. since a+=b expands to a=a+b, as soon as b has >> the EvalBeforeNestingBit, there can be no aliasing problem. b will >> just be evaluated into a temporary c which won't have any >> EvalBefore... bit, and from there one we have a=a+c which will be >> lazy. On the other hand, noalias() allows to ignore >> EvalBeforeAssigning on the sum expression. So basically the only case >> where noalias() might be useful in a.noalias()+=b, is a case where b >> has EvalBeforeAssigning and NOT EvalBeforeNesting. I don't think >> there's any example of that??? So basically i'm saying that I don't >> see any use case for a.noalias()+=b. Do you see any? > > this is because we have overloads for += <product> and -= <product> so > that you can have: > > c += (a*b).lazy() > > oops, now you should rather write: > > c.noalias() += a*b; > > and evaluate it without temporary because this what the underlying > optimized routine does. I see. So you're saying that in this case, a.noalias()+=b is not equivalent to a.noalias()=a+b, it also has the effect of ignoring the EvalBeforeNesting bit on b? And that's not a general rule but rather a property of the underlying optimized routine? I'm OK with this behavior but I think that it needs to be a little more predictable. Perhaps it could be explicitly said that a.noalias()+=b assumes that there is no aliasing between a and b. In this way, the decision of evaluating b or not becomes purely an optimization issue and we're free to do what we want in the backyard :) Benoit > > And yes, if you write: > > c = c + a*b; > > then you lost this optimization, and a*b is evaluated into a temporary. > > However without noalias(): > > c += a*b; > > is the same as: > > c += (a*b).eval(); > > > > > Perhaps I should also say that: > > 2 * (a * b) > > actually returns a product expression, and not a CwiseUnaryOp because > the optimized routine performs this scaling anyway. > > ah, and another details: when you write c.noalias() = a*b (with c > large enough), it is actually evaluated as: > > c.setZero(); > c.noalias() += 1 * a * b; > > > Gael > > >

**Follow-Ups**:**Re: [eigen] about .lazy()***From:*Benoit Jacob

**Re: [eigen] about .lazy()***From:*Gael Guennebaud

**References**:**[eigen] about .lazy()***From:*Gael Guennebaud

**Re: [eigen] about .lazy()***From:*Benoit Jacob

**Re: [eigen] about .lazy()***From:*Gael Guennebaud

**Messages sorted by:**[ date | thread ]- Prev by Date:
**Re: [eigen] about .lazy()** - Next by Date:
**Re: [eigen] about .lazy()** - Previous by thread:
**Re: [eigen] about .lazy()** - Next by thread:
**Re: [eigen] about .lazy()**

Mail converted by MHonArc 2.6.19+ | http://listengine.tuxfamily.org/ |