
Hi, I am trying to improve the memory usage of regex-tdfa and I wanted to ask an array question. If I have two identical STUArrays (same type and bounds) then what is the most efficient way to overwrite the data in the destination with the data in the source? Does this work for STArrays? Is there a GHC only solution? Is there a way to avoid the long loop?
forM_ (range b) $ \index -> readArray source index >>= writeArray destination index
Is Data.Array.Storable the only route? I do not think Data.Array.Diff will work well since I have one source going to multiple destinations, each with a few different changes. -- Chris

Hello Chris, Friday, February 2, 2007, 4:44:37 PM, you wrote:
If I have two identical STUArrays (same type and bounds) then what is the most efficient way to overwrite the data in the destination with the data in the source? Does this work for STArrays?
Is there a way to avoid the long loop?
forM_ (range b) $ \index -> readArray source index >>= writeArray destination index
the topic of efficient looping over arrays is briefly covered in http://haskell.org/haskellwiki/Modern_array_libraries
Is there a GHC only solution?
yes, use "unsafeCoerce# memcpy": module Data.Array.Base where ... #ifdef __GLASGOW_HASKELL__ thawSTUArray :: Ix i => UArray i e -> ST s (STUArray s i e) thawSTUArray (UArray l u arr#) = ST $ \s1# -> case sizeofByteArray# arr# of { n# -> case newByteArray# n# s1# of { (# s2#, marr# #) -> case unsafeCoerce# memcpy marr# arr# n# s2# of { (# s3#, () #) -> (# s3#, STUArray l u marr# #) }}} foreign import ccall unsafe "memcpy" memcpy :: MutableByteArray# RealWorld -> ByteArray# -> Int# -> IO () #endif /* __GLASGOW_HASKELL__ */ -- Best regards, Bulat mailto:Bulat.Ziganshin@gmail.com

On Fri, 2007-02-02 at 17:02 +0300, Bulat Ziganshin wrote:
Hello Chris,
Friday, February 2, 2007, 4:44:37 PM, you wrote:
If I have two identical STUArrays (same type and bounds) then what is the most efficient way to overwrite the data in the destination with the data in the source? Does this work for STArrays?
Is there a way to avoid the long loop?
forM_ (range b) $ \index -> readArray source index >>= writeArray destination index
the topic of efficient looping over arrays is briefly covered in http://haskell.org/haskellwiki/Modern_array_libraries
I should note that it is possible to generate good loops, though it's not easy yet from high level code. The binary package has a memory throughput benchmark which compares C and Haskell byte/word read/write loops: http://darcs.haskell.org/binary/tests/ All the Haskell versions compile down to good loops, though the loop body is bigger than in the C case (take a look at the assembly output for the -fasm route). However that's enough for the Haskell versions to get a significant fraction of the memory throughput of the C versions: C memory throughput benchmarks: 500MB of bytes written in 0.468s, at: 1068.3MB/s 500MB of bytes read in 0.380s, at: 1315.7MB/s 500MB of words written in 0.376s, at: 1329.7MB/s 500MB of words read in 0.192s, at: 2604.0MB/s Haskell memory throughput benchmarks: 500MB of bytes written in 1.560s, at: 320.5MB/s 500MB of bytes read in 2.192s, at: 228.1MB/s 500MB of words written in 0.340s, at: 1470.5MB/s 500MB of words read in 0.344s, at: 1453.4MB/s As you can see, the extra size of the loop body hurts us more in the byte size cases than in the word size one, where we're getting much closer to saturating the memory bandwidth of the box. It's a 64bit box so the words are 8 bytes. I'm not quite sure what is going on in the "words written" case. Perhaps someone can see why the C one is loosing out to the Haskell version. Duncan
participants (3)
-
Bulat Ziganshin
-
Chris Kuklewicz
-
Duncan Coutts