[Haskell-cafe] Repa: traverse delayed array multiple times

Andrey Yankin yankin013 at gmail.com
Sun Jan 13 22:58:13 CET 2013


Greetings to all!

Currently I'm trying to do physical simulations using finite difference
method. To accomplish this I need to repeat some manipulations on
2-dimensional grid several thousands or millions times, you know. Is it
possible to do using repa?

I wrote this rough sketch that shows what I am into. Apparently, program is
severely slow. I think reason is:
"Every time an element is requested from a delayed array it is calculated
anew, which means that delayed arrays are inefficient when the data is
needed multiple times"
(http://www.haskell.org/haskellwiki/Numeric_Haskell:_A_Repa_Tutorial).

I started diving into Guiding Parallel Array Fusion with Indexed
Types<http://www.cse.unsw.edu.au/%7Ebenl/papers/guiding/guiding-Haskell2012-sub.pdf>mentioned
there. Is it a right place to find any answer to my question?

To summarize, I want to apply my function to Array several thousand times
as fast as possible (using multi-threading and GPGPU). It seems I need a
lot of memory and throughput. Do I have to call iterate only once at a time
or in some kind of batches. What are my possibilities?

Thanks in advance!

Example program:

import System.Environment
import Data.Array.Repa as Repa

h = 50
w = 50

grid = fromListUnboxed (Z :. h :. w) $ take (h * w) [1, 1..]

main = do
  args <- getArgs
  let n = read $ head args
  g <- computeP $ accumulate n grid :: IO (Array U DIM2 Int)
  putStrLn "Ok"

accumulate :: Int -> Array U DIM2 Int -> Array D DIM2 Int
accumulate n g = repaIterate step n $ delay g

step :: (DIM2 -> Int) -> DIM2 -> Int
step f (Z :. i :. j) = center + right + left + top + bottom

 where
  left   = f'  j      (i - 1)
  center = f'  j       i
  right  = f'  j      (i + 1)
  top    = f' (j + 1)  i
  bottom = f' (j - 1)  i
  f' j i   =
    if j<0 || i<0 || i>=h || j>=w
    then 0
    else f (Z :. j :. i)

repaIterate :: ((DIM2 -> Int) -> DIM2 -> Int) -> Int -> Array D DIM2 Int ->
Array D DIM2 Int
repaIterate f n = (!! n) . iterate (\array -> traverse array id f)

Compilation:

ghc -O2 -threaded -rtsopts --make repatest.hs

time output:

./repatest 3 +RTS -N2 -H  0,02s user 0,02s system 109% cpu 0,033 total
./repatest 4 +RTS -N2 -H  0,09s user 0,02s system 126% cpu 0,089 total
./repatest 5 +RTS -N2 -H  0,30s user 0,02s system 155% cpu 0,200 total
./repatest 6 +RTS -N2 -H  1,16s user 0,06s system 185% cpu 0,663 total
./repatest 7 +RTS -N2 -H  5,63s user 0,24s system 191% cpu 3,071 total
./repatest 8 +RTS -N2 -H  27,72s user 0,89s system 191% cpu 14,960 total
./repatest 8 +RTS -N1 -H  26,23s user 0,19s system 100% cpu 26,388 total
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.haskell.org/pipermail/haskell-cafe/attachments/20130114/b74aafe8/attachment.htm>


More information about the Haskell-Cafe mailing list