Article View: comp.lang.functional
Article #1125Haskell optimization (mandelbrot generator)
From: 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)
Technical Details
Message-ID:
<1151378213.631887.29960@r2g2000cwb.googlegroups.com>Path:
arc1-ca.pugleaf.net!g2news2.google.com!postnews.google.com!r2g2000cwb.googlegroups.com!not-for-mailShow Full Headers
Complete Article Headers
X-Google-Thread: 107f24,c4c6b7c72553cb95,start X-Google-Thread: 10707f,c4c6b7c72553cb95,start X-Google-Attributes: gid107f24,gid10707f,public X-Google-Language: ENGLISH,ASCII-7-bit Path: arc1-ca.pugleaf.net!g2news2.google.com!postnews.google.com!r2g2000cwb.googlegroups.com!not-for-mail From: jtdubs@gmail.com Newsgroups: comp.lang.functional,fa.haskell Subject: Haskell optimization (mandelbrot generator) Date: 26 Jun 2006 20:16:53 -0700 Organization: http://groups.google.com Lines: 73 Message-ID: <1151378213.631887.29960@r2g2000cwb.googlegroups.com> NNTP-Posting-Host: 71.77.94.5 Mime-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" X-Trace: posting.google.com 1151378218 957 127.0.0.1 (27 Jun 2006 03:16:58 GMT) X-Complaints-To: groups-abuse@google.com NNTP-Posting-Date: Tue, 27 Jun 2006 03:16:58 +0000 (UTC) User-Agent: G2/0.2 X-HTTP-UserAgent: Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/418 (KHTML, like Gecko) Safari/417.9.3,gzip(gfe),gzip(gfe) Complaints-To: groups-abuse@google.com Injection-Info: r2g2000cwb.googlegroups.com; posting-host=71.77.94.5; posting-account=6Ga3uw0AAADBBQ_AgT5Nx96fNWangc6s