[Haskell-beginners] Performance of function defined in a 'where' clause

Peter Verswyvelen bugfact at gmail.com
Sun May 10 07:41:14 EDT 2009


Did you compile with -O or -O2?
On Sat, May 9, 2009 at 6:50 PM, Kevin Haines <kevin.haines at ntlworld.com>wrote:

> Hi All,
>
> I'm trying to write a bit of code that maps each byte in a block of Word8's
> to 3xWord8 using an array; i.e. mapping from 8 bit to 24 bit colour (this is
> an OpenGL application, and I'm using textures).
>
> I should point out that this is experimental code, and I'm still learning
> Haskell (and *loving* it, by the way!), so it probably looks a little
> unpolished.
>
> First, some data:
>
> data Palette = Palette { palRed :: Word8, palGrn :: Word8, palBlu :: Word8
> }
>
> palette = listArray (0,49) paletteList
> paletteList = [
>            Palette 0 0 0,
>            Palette 0 0 0,
>            Palette 0 0 0,
>                .....
>
>
>
> Then, my first implementation, which took 57% time under profiling, was:
>
> loadTile :: Int -> Int -> IO (Ptr Word8)
> loadTile lat lon = do
>    terrainBytes <- readTile lat lon
>
>    -- implementation #1
>    mapM_ (paletteMapper terrainBytes rgbBytes) [0..tileSize^2-1]
>
>    free terrainBytes
>    return rgbBytes
>
>    where tileSize = 128
>          paletteMapper :: Ptr Word8 -> Ptr Word8 -> Int -> IO ()
>          paletteMapper tb rgb idx = do
>                v <- peekElemOff tb idx
>                pokeByteOff rgb (idx*3) (palRed (palette!v))
>                pokeByteOff rgb (idx*3+1) (palGrn (palette!v))
>                pokeByteOff rgb (idx*3+2) (palBlu (palette!v))
>
>
> I tried moving paletterMapper out of the 'where' clause and into the top
> level, which then took only 26% of time - i.e. half the time:
>
>
> paletteMapper :: Ptr Word8 -> Ptr Word8 -> Int -> IO ()
> paletteMapper tb rgb idx = do
>   v <- peekElemOff tb idx
>   pokeByteOff rgb (idx*3) (palRed (palette!v))
>   pokeByteOff rgb (idx*3+1) (palGrn (palette!v))
>  pokeByteOff rgb (idx*3+2) (palBlu (palette!v))
>
> loadTile :: Int -> Int -> IO (Ptr Word8)
> loadTile lat lon = do
>    terrainBytes <- readTile lat lon
>
>    -- implementation #1
>    mapM_ (paletteMapper terrainBytes rgbBytes) [0..tileSize^2-1]
>
>    free terrainBytes
>    return rgbBytes
>
>    where tileSize = 128
>
>
> I don't understand why - the functions are the same, except for the scope
> they're in. Can anyone elaborate on what's happening?
>
>
> Incidentally, I now realise a faster way (14%) is:
>
> loadTile :: Int -> Int -> IO (Ptr Word8)
> loadTile lat lon = do
>
>    terrainBytes <- readTile lat lon
>
>    rgbBytes <- mallocBytes (3*(tileSize^2))
>    mapM_ (\x -> do
>        v <- peekElemOff terrainBytes x
>        pokeByteOff rgbBytes (x*3) (palRed (palette!v))
>        pokeByteOff rgbBytes (x*3+1) (palGrn (palette!v))
>        pokeByteOff rgbBytes (x*3+2) (palBlu (palette!v))
>        ) [0..tileSize^2-1]
>
>
>    free terrainBytes
>    return rgbBytes
>
>    where tileSize = 128
>
>
> (There may be faster/better ways still, I'm all ears :-)
>
> Cheers
>
> Kevin
> _______________________________________________
> Beginners mailing list
> Beginners at haskell.org
> http://www.haskell.org/mailman/listinfo/beginners
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.haskell.org/pipermail/beginners/attachments/20090510/47998c0d/attachment-0001.htm


More information about the Beginners mailing list