5

Background

I am using repa more as a "management" tool. I pass around reactive-bananas AddHandlers in an Array: Array D DIM2 (AddHandler Bool).

Currently I am using this kludge:

mapMArray :: (Monad m, R.Source r a, R.Shape sh)  => (a -> m b) -> Array r sh a -> m (Array D sh b)
mapMArray f a = do
    l <- mapM f . R.toList $ a
    return $ R.fromFunction sh (\i -> l !! R.toIndex sh i)
  where sh = R.extent a

So I can do something like this:

makeNetworkDesc :: Frameworks t => Array D DIM2 (AddHandler Bool) -> Moment t ()
makeNetworkDesc events = do

    -- inputs
    aes <- mapMArray fromAddHandler events

    -- outputs
    _ <- mapMArray (reactimate . (print <$>)) aes

Question

Is there a reason why this is not included in repa?

fho
  • 6,787
  • 26
  • 71

1 Answers1

7

Basically for the same reason there's nothing like parMapM in parallel: mapM and mapM_ (or monadic actions in general) destroy parallelism. Here's a simple example:

next :: State Int Int
next = modify (+1) >> get

Now, a hypothetical repaMapM needs to sequence all steps in the State monad, if one would use repaMapM (const next). Since this clearly defies parallelism (and can also lead to low performance), it isn't part of repa. After all, high performance and parallelism is right there in repa's description (emphasis mine):

Repa provides high performance, regular, multi-dimensional, shape polymorphic parallel arrays.

Zeta
  • 103,620
  • 13
  • 194
  • 236
  • Hmm ... so as long as I don't need the parallelism, I should be fine. Otoh I seem to misuse repa. A cursory search on hackage provided no other matrix libraries that have stencil operations. Is there an alternative to repa in that regard? – fho Sep 17 '14 at 13:13
  • If the [three year old answer](http://stackoverflow.com/questions/6006304/what-haskell-representation-is-recommended-for-2d-unboxed-pixel-arrays-with-mil) still hold, then no. There's `accelerate`, but that's a whole other beast. All in all it depends on what you want to do. The code you provided in your answer can be easily accomplished with `Data.Vector(*)`, but in this case you need to write stencils yourself (also `Data.Vector` doesn't support multi-dimensional indices, but that's something you can easily fix with a wrapper and additional functions). – Zeta Sep 17 '14 at 13:41
  • Yeah ... I was hoping to get around that ;) – fho Sep 17 '14 at 14:08
  • Couple years later and we now do have a library called [`massiv`](https://github.com/lehins/massiv) that has all of the desired features. It has sequential `mapM` for any Monad, it has `mapIO` that can be parallelized and it has much better implementation of stencils that work for arbitrary dimension. Overall it is more performant than `Repa`, easier to use than `accelerate` (and just as fast with llvm backend) – lehins Jun 04 '19 at 20:55