[Haskell-cafe] How can I pass IOUArrays to FFI functions?

Stefan O'Rear stefanor at cox.net
Tue Aug 21 03:19:34 EDT 2007

On Mon, Aug 20, 2007 at 11:47:06PM -0700, Ryan Ingram wrote:
> > Your code is broken in a most evil and insidious way.
> Interesting.  This is for a toy project, so I'm not too worried, but lets
> say I wanted to do this "correctly" and I was set on using IOUArray for some
> reason.

Heh, I'm a lot less worried now.  (Somehow I thought this was going into
a high-visibility library!)

> (The Haskell wiki claims that StorableArray is slower; is that
> actually the case?)

Good question!  I wrote a basic CA benchmark and a much simpler array
benchmark, both parameterized by the array type, and couldn't get
consistent results, so I'll take this as a "no".

stefan at stefans:/tmp$ cat ArrayTest.hs
{-# OPTIONS_GHC -fglasgow-exts -cpp #-}

import Data.Array.MArray
import Data.Bits
import Data.Array.IO
import Data.Array.Base
import Data.Array.Storable
import GHC.Exts

-- #define ARRAY IOUArray

-- uch!

iter :: Int -> ARRAY Int Word -> IO ()
iter 4096 arr = arr `seq` return ()
iter ix   arr = do
    unsafeWrite arr ix . succ =<< unsafeRead arr ix
    iter (ix+1) arr

bench 100000 arr = arr `seq` return ()
bench ct arr = do
    iter 0 arr
    bench (ct+1) arr

main = do
    arr <- newListArray (0,4095) [1..]
    bench 0 arr

    print =<< getElems arr
stefan at stefans:/tmp$ ghc -fforce-recomp -DARRAY=IOUArray -O2 ArrayTest.hs && time ./a.out > /dev/null

real	0m2.006s
user	0m2.028s
sys	0m0.008s
stefan at stefans:/tmp$ ghc -fforce-recomp -DARRAY=StorableArray -O2 ArrayTest.hs && time ./a.out > /dev/null

real	0m1.845s
user	0m1.872s
sys	0m0.004s
stefan at stefans:/tmp$ 

> Which of the following fixes would work now?  Which has the lowest
> probability of not working in the future?
> 1) Declare f to take Addr# and don't construct a Ptr Word32
>     I suspect this would be enough unless the GC changed to some sort of
> continous GC which can happen even without an allocation

Would work now, I think.

> 2) Declare f to take MutableByteArray#
>     Is this good enough to make the collector happy?

Maybe.  In theory the collector should know that an argument passed to a
foreign function as a pointer type, should be followed.  I'd tentatively
call it a bug if this breaks, but it's fragile enough that you should
expect to find yourself reporting said bug.

> 3) Something else I haven't thought of?
> If there was no other option, and StorableArray wasn't slower, and I was
> working on a real project, I'd probably wrap my own around ForeignPtr like
> Data.ByteString.

-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
Url : http://www.haskell.org/pipermail/haskell-cafe/attachments/20070821/ded5ed02/attachment.bin

More information about the Haskell-Cafe mailing list