REPA: computeS and computeP?
Asked Answered
P

1

1

I am trying this REPA library, and i want to process an image in both ways, parallel and sequentially.

I can read the image (with other library, DevIL) and process it with computeP (parallel). Here is the code (is from a example on the wiki of haskell).

import Foreign.Ptr
import System.Environment
import Data.Word
import Data.Array.Repa hiding ((++))
import Data.Array.Repa.IO.DevIL
import Data.Array.Repa.Repr.ForeignPtr

main :: IO () 
main = do
    [f] <- getArgs
    (RGB v) <- runIL $ readImage f
    rotated <- (computeP $ rot180 v) :: IO (Array F DIM3 Word8)
    runIL $ writeImage ("flip-"++f) (RGB rotated)

rot180 :: (Source r e) => Array r DIM3 e -> Array D DIM3 e
rot180 g = backpermute e flop g
    where
        e@(Z :. x :. y :. _)   = extent g
        flop (Z :. i         :. j         :. k) =
             (Z :. x - i - 1 :. y - j - 1 :. k)

Now i want to do it sequentially changing "computeP" with "computeS". But, when i try to compile it, this error appears:

Couldn't match expected type ‘IO (Array F DIM3 Word8)’
                with actual type ‘Array r20 DIM3 Word8’
    In a stmt of a 'do' block:
      rotated <- (computeS $ rot180 v) :: IO (Array F DIM3 Word8)

As you can probably guess, i am new at functional programming. I dont know why this error is happening. Any help would be great.

Thanks in advance.

Pancreas answered 28/7, 2017 at 21:17 Comment(7)
computeS does not occur in IO so you need to have let rotated = (computeS $ rot180 v) :: Array F DIM3 Word8 instead of rotated <- (computeP $ rot180 v) :: IO (Array F DIM3 Word8).Lethargy
What is computeP, anyway? I can't find anything of that name in the libraries you've quoted. Please always add concrete links to tha hackage haddocks, like this: computeS.Fuzzy
Ok, i will do it next time. Thanks guys.Pancreas
@Fuzzy To be fair, computeP and computeS are sort of at the centre of REPA. Here they are in the main Data.Array.Repa module.Lethargy
@leftaroundabout, question is about repa3, while you added a link to repa4Agminate
@AlexeyKuleshevich well, that underlines my point – a question should always link to the concrete versions of functions it asks about. Also, computeP is apparently obsolete then...Fuzzy
@leftaroundabout, your point was certainly a valid one. It's not that computeP is obsolete, it's that repa4 is still in experimental stage and doesn't have that function. Not sure if it does computation in parallel by default or simply doesn't support it, I'll have to figure it out.Agminate
A
1

You are doing everything almost right. The error you are getting is due to the fact that computeP is monadic, while computeS is not. If you compare their type signatures closely the difference that is biting you is the Monad m restriction and return type m (Array r2 sh e) for computeP vs (Array r2 sh e) for computeS. So long story short, just change

rotated <- (computeP $ rot180 v) :: IO (Array F DIM3 Word8)

to:

let rotated = (computeS $ rot180 v) :: (Array F DIM3 Word8)

The reason why parallel computation in Repa must be monadic has to do partially with lazyness, but mostly with Repa's inability to deal with nested parallelism. Sequential property of a Monad solves it for the most part:

rotated1 <- (computeP $ rot180 v) :: IO (Array F DIM3 Word8)
rotated2 <- (computeP $ rot180 rotated1) :: IO (Array F DIM3 Word8)

Using do notation above (and the fact that computeP uses deepSeqArray under the hood) makes sure rotated1 is evaluated before getting to second call to computeP. But since computeS doesn't use Repa's parallel scheduler it doesn't have that issue, thus doesn't need to use that property of a Monad and this code will work just fine:

let rotated1 = computeS (rot180 v) :: Array F DIM3 Word8
    rotated2 = computeS (rot180 rotated1) :: Array F DIM3 Word8
Agminate answered 2/8, 2017 at 1:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.