<div dir="ltr"><div>> the exampleC is the bound things that is eta-expanded.</div><div><br></div><div>Oh! I get it now. Thanks.</div><div><br></div><div>> The problem is that GHC’s optimizer uses a cost-model [...] that does not hold in your case.</div><div><br></div><div>Makes sense a well. I'll use `-fno-do-lambda-eta-expansion` for now and see well it works.</div><div><br></div><div>Thanks very much for these tips.</div><div><br></div><div>Regards, - Conal</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Tue, Jul 18, 2017 at 3:44 PM, Joachim Breitner <span dir="ltr"><<a href="mailto:mail@joachim-breitner.de" target="_blank">mail@joachim-breitner.de</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi Conal,<br>
<span class=""><br>
Am Dienstag, den 18.07.2017, 15:35 -0700 schrieb Conal Elliott:<br>
> Thanks very much for this reply, Joachim. I see that `-fno-do-lambda-<br>
> eta-expansion` with my example prevents moving the computation under<br>
> the lambda where it gets repeatedly evaluated. I don't understand<br>
> what this code motion/substitution has to do with eta-expansion. Is<br>
> it that the `let` expression itself is eta-expanded? The GHC Users<br>
> Guide describes this flag as "eta-expand let-bindings to increase<br>
> their arity", which doesn't seem to fit here, since the `let`-<br>
> bindings are not function-valued (though the `let` expression is).<br>
<br>
</span>In the code<br>
<span class=""><br>
exampleC :: Double -> Double -> Double<br>
exampleC = \ t -> let s = sin t in \ x -> x + s<br>
<br>
</span>the exampleC is the bound things that is eta-expanded. Ok, it is a top-<br>
level function, but that does not make a big difference. When eta-<br>
expanded, it becomes<br>
<span class=""><br>
exampleC :: Double -> Double -> Double<br>
</span>exampleC = \ t y -> (let s = sin<br>
t in \ x -> x + s) y<br>
<br>
and from then on, usual simplifications kick in to produce<br>
<span class=""><br>
exampleC :: Double -> Double -> Double<br>
</span>exampleC = \ t y -> let s = sin t in y + s<br>
<br>
and eventually<br>
<span class=""><br>
exampleC :: Double -> Double -> Double<br>
</span>exampleC = \ t y -> y + sin t<br>
<br>
(I ignore the unboxing of Doubles here).<br>
<span class=""><br>
<br>
> > Did you measure whether this really is a problem? The benefits of not<br>
> > dealing with dynamically allocated functions might outweigh the cost of<br>
> > recalculating sin.<br>
><br>
> No, I haven't measured. In this case, I'm compiling Haskell to GLSL<br>
> for execution on a GPU, where the inner lambda will be over space,<br>
> which means at least one application per pixel, so the computations<br>
> moved under the inner lambda will be redundantly computed a few<br>
> millions of times per frame (and much more with anti-aliasing).<br>
> Instead, I want to move those calculations to once per frame and<br>
> stored in quickly accessed video memory. As the space-independent<br>
> computation gets more complex, I expect the saving to grow.<br>
<br>
</span>Hmm. The problem is that GHC’s optimizer uses a cost-model (in this<br>
case: calling an anonymous function is worse than recomputing sind)<br>
that does not hold in your case. Besides simply turning off some<br>
transformations, I am not sure what best you could do to avoid this…<br>
<br>
Gruß,<br>
<div class="HOEnZb"><div class="h5">Joachim<br>
--<br>
Joachim Breitner<br>
  <a href="mailto:mail@joachim-breitner.de">mail@joachim-breitner.de</a><br>
  <a href="http://www.joachim-breitner.de/" rel="noreferrer" target="_blank">http://www.joachim-breitner.<wbr>de/</a><br>
</div></div><br>______________________________<wbr>_________________<br>
ghc-devs mailing list<br>
<a href="mailto:ghc-devs@haskell.org">ghc-devs@haskell.org</a><br>
<a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs" rel="noreferrer" target="_blank">http://mail.haskell.org/cgi-<wbr>bin/mailman/listinfo/ghc-devs</a><br>
<br></blockquote></div><br></div>