| Safe Haskell | None |
|---|---|
| Language | Haskell2010 |
Feldspar.Data.Buffered
Description
Double-buffered storage
This module provides a safer alternative to the methods of the classes
Manifestable and Manifestable2:
storeinstead ofmanifeststore2instead ofmanifest2setStoreinstead ofmanifestStoresetStore2instead ofmanifestStore2
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 allocates
twice as much memory as newStore l. However, none of the other functions in
this module allocate any memory.newArr l
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
- data Store a
- newStore :: (Syntax a, MonadComp m) => Data Length -> m (Store a)
- unsafeInplaceStore :: (Syntax a, MonadComp m) => Data Length -> m (Store a)
- unsafeFreezeStore :: (Syntax a, MonadComp m) => Data Length -> Store a -> m (Manifest a)
- unsafeFreezeStore2 :: (Syntax a, MonadComp m) => Data Length -> Data Length -> Store a -> m (Manifest2 a)
- setStore :: (Manifestable Run vec a, Finite vec, Syntax a) => Store a -> vec -> Run ()
- setStore2 :: (Manifestable2 Run vec a, Finite2 vec, Syntax a) => Store a -> vec -> Run ()
- store :: (Manifestable Run vec a, Finite vec, Syntax a) => Store a -> vec -> Run (Manifest a)
- store2 :: (Manifestable2 Run vec a, Finite2 vec, Syntax a) => Store a -> vec -> Run (Manifest2 a)
- 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)
- 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)
Documentation
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.
store :: (Manifestable Run vec a, Finite vec, Syntax a) => Store a -> vec -> Run (Manifest a) Source #
store2 :: (Manifestable2 Run vec a, Finite2 vec, Syntax a) => Store a -> vec -> Run (Manifest2 a) Source #