raw-feldspar-0.3: Resource-Aware Feldspar

Safe HaskellNone
LanguageHaskell2010

Feldspar.Data.Buffered

Description

Double-buffered storage

This module provides a safer alternative to the methods of the classes Manifestable and Manifestable2:

Consider the following example:

bad = do
  arr  <- newArr 20
  vec1 <- manifest arr (1...20)
  vec2 <- manifest arr $ map (*10) $ reverse vec1
  printf "%d\n" $ sum vec2

First the vector (1...20) is stored into arr. Then the result is used to compute a new vector which is also stored into arr. So the storage is updated while it is being read from, leading to unexpected results.

Using this module, we can make a small change to the program:

good = do
  st   <- newStore 20
  vec1 <- store st (1...20)
  vec2 <- store st $ map (*10) $ reverse vec1
  printf "%d\n" $ sum vec2

Now the program works as expected; i.e. gives the same result as the normal Haskell expression

sum $ map (*10) $ reverse [1..20]

The price we have to pay for safe storage is that newStore l allocates twice as much memory as newArr l. However, none of the other functions in this module allocate any memory.

Note that this module does not protect against improper use of unsafeFreezeStore. A vector from a frozen Store is only valid as long as the Store is not updated.

Synopsis

Documentation

data Store a Source #

Double-buffered storage

newStore :: (Syntax a, MonadComp m) => Data Length -> m (Store a) Source #

Create a new double-buffered Store

This operation allocates two arrays of the given length.

unsafeInplaceStore :: (Syntax a, MonadComp m) => Data Length -> m (Store a) Source #

Create a new single-buffered Store

Using unsafeInplaceStore instead of newStore allows double-buffered algorithms to run inplace.

unsafeFreezeStore :: (Syntax a, MonadComp m) => Data Length -> Store a -> m (Manifest a) Source #

Read the contents of a Store without making a copy. This is generally only safe if the the Store is not updated as long as the resulting vector is alive.

unsafeFreezeStore2 Source #

Arguments

:: (Syntax a, MonadComp m) 
=> Data Length

Number of rows

-> Data Length

Number of columns

-> Store a 
-> m (Manifest2 a) 

Read the contents of a Store without making a copy (2-dimensional version). This is generally only safe if the the Store is not updated as long as the resulting vector is alive.

setStore :: (Manifestable Run vec a, Finite vec, Syntax a) => Store a -> vec -> Run () Source #

Write a 1-dimensional vector to a Store. The operation may become a no-op if the vector is already in the Store.

setStore2 :: (Manifestable2 Run vec a, Finite2 vec, Syntax a) => Store a -> vec -> Run () Source #

Write a 2-dimensional vector to a Store. The operation may become a no-op if the vector is already in the Store.

store :: (Manifestable Run vec a, Finite vec, Syntax a) => Store a -> vec -> Run (Manifest a) Source #

Write the contents of a vector to a Store and get it back as a Manifest vector

store2 :: (Manifestable2 Run vec a, Finite2 vec, Syntax a) => Store a -> vec -> Run (Manifest2 a) Source #

Write the contents of a vector to a Store and get it back as a Manifest2 vector

loopStore :: (Integral i, PrimType i, Syntax a, Manifestable Run vec1 a, Finite vec1, Manifestable Run vec2 a, Finite vec2) => Store a -> IxRange (Data i) -> (Data i -> Manifest a -> Run vec1) -> vec2 -> Run (Manifest a) Source #

loopStore2 :: (Integral i, PrimType i, Syntax a, Manifestable2 Run vec1 a, Finite2 vec1, Manifestable2 Run vec2 a, Finite2 vec2) => Store a -> IxRange (Data i) -> (Data i -> Manifest2 a -> Run vec1) -> vec2 -> Run (Manifest2 a) Source #