Thread View: comp.lang.functional
2 messages
2 total messages
Started by jtdubs
Tue, 27 Jun 2006 03:16
Haskell optimization (mandelbrot generator)
Author: jtdubs
Date: Tue, 27 Jun 2006 03:16
Date: Tue, 27 Jun 2006 03:16
72 lines
3481 bytes
3481 bytes
I am teaching myself Haskell and decided to write a Mandelbrot
generator as a learning exercise.
It works fine and the code is nice and short, but I'm not happy with
the performance. I am generating a 131 x 101 pixel image (-2 to 1.6 on
the real axis and -1 to 1 on the imaginary axis with a step size of
0.02).
I wrote an equivalent C program real quick, just for the sake of
comparison.
I compiled the C code with: gcc -O2 fractal.c -o fractal
I compiled the Haskell code with: ghc -funbox-strict-fields -O2
fractal.hs -o fractal
The speeds are:
C: 0.05s
Haskell: 8.3s
So, that's 166x slower. I'm hoping someone can give me some pointers
to help me optimize this. I've tried:
1. Passing the file handle through fractal and escape so that escape
returns IO (), fractal returns IO (), the map calls are changed to
mapM_ and escape just prints its result directly with hPutStrLn. My
theory was that the consing of the result list was slowing the app
down. However, this change did not affect the speed at all.
2. Changing from double's to floats. This actually slowed things down.
The GHC manual backed this up by saying that Double's are much more
heavily optimized than floats, especially complex double compared to
complex float.
Any other ideas? Oh, and since I'm a Haskell newbie, any stylistic
suggestions or other constructive criticism would be
welcome/appreciated.
Thanks,
Justin Dubs
Here's the code:
import Complex
import IO
type Dimensions = (Double, Double, Double, Double) -- top, left,
bottom, right
type Resolution = Double
fractal :: Dimensions -> Resolution -> [[Int]]
fractal (t,l,b,r) d = map (\y -> map (\x -> escape 255 (0:+0) (x:+y))
[l,l+d..r]) [b,b+d..t]
where
escape :: Int -> Complex Double -> Complex Double -> Int
escape 0 _ _ = 0
escape i z c = if (magnitude z > 2) then i else escape (i-1) (z*z+c)
c
make_pgm :: String -> [[Int]] -> IO ()
make_pgm f v = do
h <- openFile f WriteMode
hPutStrLn h "P2"
hPutStrLn h (show (length (head v)) ++ " " ++ show
(length v))
hPutStrLn h "255"
mapM_ (mapM_ ((hPutStrLn h) . show)) v
hClose h
main :: IO ()
main = make_pgm "foo.pgm" (fractal (1,-2,-1,0.6) 0.02)
Re: Haskell optimization (mandelbrot generator)
Author: Ian Osgood
Date: Tue, 27 Jun 2006 21:18
Date: Tue, 27 Jun 2006 21:18
18 lines
1770 bytes
1770 bytes
jtdubs@gmail.com wrote: > I am teaching myself Haskell and decided to write a Mandelbrot > generator as a learning exercise. > > It works fine and the code is nice and short, but I'm not happy with > the performance. This happens to be one of the benchmarks in the Computer Language Shootout. Perhaps you can gain some insight from its Haskell implementation: http://shootout.alioth.debian.org/debian/benchmark.php?test=mandelbrot&lang=ghc&id=2 (This is also an order of magnitude slower than the C benchmark.) Ian
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads