[vector] #32: Performance of concatMap and O2/Odph
vector
vector at projects.haskell.org
Fri Nov 19 20:09:45 EST 2010
#32: Performance of concatMap and O2/Odph
---------------------+------------------------------------------------------
Reporter: choener | Owner:
Type: defect | Status: closed
Priority: critical | Milestone: 0.7.1
Version: 0.6 | Resolution: fixed
Keywords: |
---------------------+------------------------------------------------------
Changes (by rl):
* status: new => closed
* resolution: => fixed
Comment:
Doh, I'm such an idiot. GHC transforms `good` to:
{{{
good :: Int -> Int -> VU.Vector (Int,Int)
good i j
| 23 <= j-i-13 =
VU.map (\(k,l) -> (k-l,l)) $
VU.concatMap (
\d -> VU.map (\d' -> (d,d'))
$ VU.enumFromN 3 (d-5))
$ VU.enumFromN 8 23
| otherwise =
VU.map (\(k,l) -> (k-l,l)) $
VU.concatMap (
\d -> VU.map (\d' -> (d,d'))
$ VU.enumFromN 3 (d-5))
$ VU.enumFromN 8 (j-i-13)
}}}
Now, the first alternative doesn't depend on `i` and `j` at all and is
floated out:
{{{
vec :: VU.Vector (Int,Int)
vec = VU.map (\(k,l) -> (k-l,l)) $
VU.concatMap (
\d -> VU.map (\d' -> (d,d'))
$ VU.enumFromN 3 (d-5))
$ VU.enumFromN 8 23
good :: Int -> Int -> VU.Vector (Int,Int)
good i j
| 23 <= j-i-13 = vec
| otherwise = ...
}}}
Of course, `j-i-13` is indeed greater than 23 in the example so it's the
first alternative that get executed. When Criterion runs this multiple
times, the actual computation only happens once. In all subsequent runs,
`good` is basically a noop which, of course, explains why it appears to be
fast.
FWIW, the implementation of `concatMap` has changed in vector 0.7. The
result is that `bad` runs twice as fast as with 0.6 and `good` now has the
same performance as `bad`. I presume this is because GHC fails to float
out the computation.
I'm going to close this. It was a good example, helped find quite a few
bugs in !SpecConstr.
--
Ticket URL: <http://trac.haskell.org/vector/ticket/32#comment:13>
vector <http://trac.haskell.org/vector>
Package vector
More information about the vector
mailing list