[Haskell-cafe] some newbie FFI questions

Simon Marlow simonmar at microsoft.com
Thu Jul 1 10:33:51 EDT 2004

On 01 July 2004 11:53, John Kozak wrote:

> I'm trying to experiment with image processing in haskell (with which
> I haven't much experience).  I've written some FFI code to talk to
> the ImageMagick library which provokes a few questions (environment is
> ghc 6.2.1 on debian):
> 1. Speed: I'm reading in a 2000x1500 pixel image, and have defined a
>    Pixel type like this:
> data Pixel a = Pixel !a !a !a deriving Show
>   I use ImageMagick to load the image, then build an Array of Pixel
>   Floats.  Building the array takes 45 seconds on a 2.5Ghz P4 with
>   code compiled -O2, which seems slow to me - are my expectations
>   unrealistic?  I've tried various UNPACK things which didn't make
>   much difference.

It depends how you want to use the image data, but this is almost
certainly not the best representation.

The fastest choice would be simply 'Ptr CFloat' (i.e. do no conversion
or marshalling at all).  This is essentially what your C program is
doing.  In Haskell you can allocate the memory using allocaBytes or
mallocForeignPtr (no free required).

Your other choices are:

 - IOUArray Int Float
   Fast access, but you need to convert the entire array into one
   of these, and back again if you need to pass it back to C.
 - (IOUArray Int Float, IOUArray Int Float, IOUArray Int Float)
   i.e. split the planes.  Might be useful, depending on how
   you access the array.  Conversion required again.

 - StorableArray Int CFloat
   You can convert the 'Ptr CFloat' you get back from C directly
   into a StorableArray, which gives you easy access using the
   mutable array primitives in Haskell, and an easy way to pass the
   array back to C using withStorableArray.

   Unfortunately accessing StorableArrays isn't as fast as it could be.
   And there ought to be a way to convert between StorableArray and
   IOUArray.  This is one area that could do with some attention.

 - Array Pixel, and data Pixel = Pixel {-# UNPACK #-}!Float ...
   Not too great, because you have a few extra layers of indirection
   compared to IOUArrays, even with the UNPACKs.

 - Array (Float,Float,Float)
   Terrible :-)

> 2. How do I convert a CFloat into a Float?

Using realToFrac, I guess.

> 3. I get the wrong answer ;-)  I expect the C and haskell code below
>    to produce the same pixel data, but they don't (the C code is
>    right). 

I suggest fixing a more efficient representation first.  This will
reduce the amount of manipulation of the data, and either make the bug
go away or make it easier to find.


More information about the Haskell-Cafe mailing list