#1890: Regression in mandelbrot benchmark due to inlining
-------------------------------+--------------------------------------------
Reporter: dons | Owner:
Type: bug | Status: new
Priority: normal | Milestone:
Component: Compiler | Version: 6.8.1
Severity: normal | Keywords: inlining, performance
Difficulty: Unknown | Testcase:
Architecture: x86_64 (amd64) | Os: Unknown
-------------------------------+--------------------------------------------
The (rather delicate) mandelbrot benchmark on the Great Language Shootout
shows a large regression between ghc 6.6 and ghc 6.8. The unfold
function's inlining/worker wrapper changes quite a lot, in 6.8, wrt. the
6.6 code.
Here's the code:
{{{
{-# OPTIONS -fexcess-precision #-}
--
-- The Computer Language Shootout
-- http://shootout.alioth.debian.org/
--
-- Contributed by Spencer Janssen, Trevor McCort, Christophe Poucet and
Don Stewart
--
-- Must be compiled with the -fexcess-precision flag as a pragma. GHC
-- currently doesn't recognise the -fexcess-precision flag on the command
-- line (!).
--
-- The following flags are suggested when compiling:
--
-- -O -fglasgow-exts -optc-march=pentium4
-- -fbang-patterns -funbox-strict-fields -optc-O2 -optc-mfpmath=sse
-optc-msse2
--
import System
import System.IO
import Foreign
import Foreign.Marshal.Array
main = do
w <- getArgs >>= readIO . head
let n = w `div` 8
m = 2 / fromIntegral w
putStrLn ("P4\n"++show w++" "++show w)
p <- mallocArray0 n
unfold n (next_x w m n) p (T 1 0 0 (-1))
------------------------------------------------------------------------
--
-- compiled quite differently with ghc 6.8
--
-- This function is very sensitive to inlining
--
unfold :: Int -> (T -> Maybe (Word8,T)) -> Ptr Word8 -> T -> IO ()
unfold !i !f !ptr !x0 = loop x0
where
loop !x = go ptr 0 x
go !p !n !x = case f x of
Just (w,y) | n /= i -> poke p w >> go (p `plusPtr` 1) (n+1) y
Nothing -> hPutBuf stdout ptr i
_ -> hPutBuf stdout ptr i >> loop x
------------------------------------------------------------------------
--
-- These are all compiled the same:
--
data T = T !Int !Int !Int !Double
next_x :: Int -> Double -> Int -> T -> Maybe (Word8, T)
next_x !w !iw !bw (T bx x y ci)
| y == w = Nothing
| bx == bw = Just (loop_x w x 8 iw ci 0, T 1 0 (y+1) (iw+ci))
| otherwise = Just (loop_x w x 8 iw ci 0, T (bx+1) (x+8) y ci)
loop_x :: Int -> Int -> Int -> Double -> Double -> Word8 -> Word8
loop_x !w !x !n !iw !ci !b
| x < w = if n == 0
then b
else loop_x w (x+1) (n-1) iw ci (b+b+v)
| otherwise = b `shiftL` n
where
v = fractal 0 0 (fromIntegral x * iw - 1.5) ci 50
fractal :: Double -> Double -> Double -> Double -> Int -> Word8
fractal !r !i !cr !ci !k
| r2 + i2 > 4 = 0
| k == 0 = 1
| otherwise = fractal (r2-i2+cr) ((r+r)*i+ci) cr ci (k-1)
where
(!r2,!i2) = (r*r,i*i)
}}}
One change in 6.8 is that the shiftL is inlined (yay), and the other inner
loops are compiled identically to Core, however, the unfold function gets
moved around a lot.
Benchmarking:
{{{
$ ghc-6.6.1 -O2 -fglasgow-exts -fbang-patterns -funbox-strict-fields B.hs
-o B66 -no-recomp
$ time ./B68 4000 > /dev/null ; time ./B66 4000 > /dev/null
./B68 4000 > /dev/null 5.39s user 0.10s system 100% cpu 5.489 total
./B66 4000 > /dev/null 3.67s user 0.07s system 100% cpu 3.736 total
}}}
--
Ticket URL: <http://hackage.haskell.org/trac/ghc/ticket/1890>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler_______________________________________________
Glasgow-haskell-bugs mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/glasgow-haskell-bugs