<div dir="ltr"><div></div><div>Thanks William!</div><div><br></div><div>For me it's quite unexpected to see a unit argument making that kind of difference for the optimizer...</div><div><br></div><div>Anyway, one new trick added to the bag... <br></div><div><br></div><div>Tks.<br></div><div><br></div><div><br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Mon, Aug 19, 2019 at 11:34 AM William Yager <<a href="mailto:will.yager@gmail.com" target="_blank">will.yager@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr">I'm not sure which exact optimizations are responsible, but based on --ddump-simple,<div><br></div><div>* "inside" is not allocating any lists at all. It's just a couple loops over unboxed ints</div><div>* "outside" is actually allocating a (single) list data structure and has an inner loop and an outer loop, both of which traverse the list</div><div><br></div><div>GHC seems to be too aggressive about sharing "range" in "outside". Adding a unit argument to "range" makes both functions go fast.</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Mon, Aug 19, 2019 at 8:14 PM Emilio Francesquini <<a href="mailto:francesquini@gmail.com" target="_blank">francesquini@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div>Hello Cafe,</div><div><br></div><div>While investigating a performance problem I stumbled upon what I eventually reduced to the example below:</div><div><br></div><span style="font-family:monospace">module Main where<br><br>import Data.Time.Clock<br><br>outside :: Int -> Int<br>outside n =<br>  sum [i + j | i <- range, j <- range]<br>  where<br>    range = [0..n-1]<br><br>inside :: Int -> Int<br>inside n =<br>  sum [i + j | i <- [0..n-1], j <- [0..n-1]]<br><br></span><div><span style="font-family:monospace">main :: IO ()</span></div><span style="font-family:monospace">main = do<br>  t0 <- getCurrentTime<br>  print $ inside 10000<br>  t1 <- getCurrentTime<br>  print $ outside 10000<br>  t2 <-getCurrentTime<br><br>  print (diffUTCTime t1 t0)<br>  print (diffUTCTime t2 t1)</span><br><div><br></div><div>Compiling with -O2, up to GHC 8.2.2, both `inside` and `outside` functions would take the same amount of time to execute. Somewhere between GHC 8.2.2 and 8.6.4 something changed (possibly some new optimization) making `inside` run ~4x faster on my machine. With LLVM the difference is even bigger.<br></div><div><br></div><div>It is not that `outside` got slower, but that `inside` got much faster. I'm curious to what optimizations might be happening to the `inside` function that would not fire on the outside function.</div><div><br></div><div></div><div>Any hints?</div><div><br></div><div>Best regards,</div><div><br></div><div>Emilio<br></div><div><br></div><div><br></div><div><br></div><div><br></div></div>
_______________________________________________<br>
Haskell-Cafe mailing list<br>
To (un)subscribe, modify options or view archives go to:<br>
<a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe" rel="noreferrer" target="_blank">http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe</a><br>
Only members subscribed via the mailman list are allowed to post.</blockquote></div>
</blockquote></div>