Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you compute a[i] = f(a[i-1]) in Repa?

Tags:

haskell

repa

Is it possible to compute an array which depends on the past value(s) (i.e., lesser indexes), in Repa? Initial part(s) of the array (e.g., a[0]) is given. (Note that I am using C-like notation to indicate an element of array; please don't confuse.)

I read the tutorial and quickly check the hackage but I could not find a function to do it.

(I guess doing this kind of computation in 1D array does not make sence in Repa because you can't parallelize it. But I think you can parallelize it in 2 or more dimensional case.)

EDIT: Probably I should be more specific about what kind of f I want to use. As there is no way to parallelize in the case a[i] is a scalar, let's focus on the case a[i] is a N dim vector. I don't need a[i] to be higher dimensional (such as matrix) because you can "unroll" it to a vector. So, f is a function which maps R^N to R^N.

Most of the case, it's like this:

b = M a[i-1]
a[i][j] = g(b)[j]

where b is a N dim vector, M is a N by N matrix (no assumption for sparseness), and g is some nonlinear function. And I want to compute it for i=1,..N-1 given a[0], g and M. My hope is that there are some generic way to (1) parallelize this type of calculation and (2) make allocation of intermediate variables such as b efficient (in C-like language, you can just reuse it, it would be nice if Repa or similar library can do it like a magic without breaking purity).

like image 322
tkf Avatar asked Jun 27 '12 14:06

tkf


2 Answers

I cannot see a Repa way of doing this. But there is for Vector: Data.Vector.iterateN builds the vector you want. Then Data.Array.Repa.fromUnboxed to convert it from Vector to Repa.

iterateN :: Int -> (a -> a) -> a -> Vector aSource

O(n) Apply function n times to value. Zeroth element is original value.

like image 92
Chris Kuklewicz Avatar answered Oct 20 '22 22:10

Chris Kuklewicz


Edit: Actually, I think I misinterpreted the question. I'll leave my answer here, in case it's useful for someone else...

You can use traverse http://hackage.haskell.org/packages/archive/repa/3.2.1.1/doc/html/Data-Array-Repa.html#v:traverse:

Prelude Data.Array.Repa R> let x = fromListUnboxed (Z :. 10 :: DIM1) [1..10]
Prelude Data.Array.Repa R> R.computeUnboxedS $ R.traverse x (\ (Z :. i) -> (Z :. (i - 1))) (\f  (Z :. i) -> f (Z :. (i + 1)) - f (Z :. i))
AUnboxed (Z :. 9) (fromList [1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0])

Dissecting it:

    R.computeUnboxedS $                            -- force the vector to be "real"
    R.traverse x                                   -- traverse the vector
    (\ (Z :. i) -> (Z :. (i - 1)))                 -- function to get the shape of the result
    (\f (Z :. i) -> f (Z :. (i + 1)) - f (Z :. i)) -- actual "stencil"

Extending it to multi-dimensional array should be trivial.

like image 34
lbolla Avatar answered Oct 20 '22 20:10

lbolla