repa-3.4.1.2: High performance, regular, shape polymorphic parallel arrays.

Safe Haskell | None
Language | Haskell98

Data.Array.Repa.Eval

Contents

- Element types
- Parallel array filling
- Converting between representations
- Chunked filling
- Interleaved filling
- Blockwise filling
- Cursored blockwise filling
- Chunked selection

Description

Low level interface to parallel array filling operators.

Synopsis

- class Elt a where
- class Target r e where
  - data MVec r e
- class (Source r1 e, Shape sh) => Load r1 sh e where
- class (Source r1 e, Shape sh) => LoadRange r1 sh e where
- fromList :: (Shape sh, Target r e) => sh -> [e] -> Array r sh e
- computeS :: (Load r1 sh e, Target r2 e) => Array r1 sh e -> Array r2 sh e
- computeP :: (Load r1 sh e, Target r2 e, Source r2 e, Monad m) => Array r1 sh e -> m (Array r2 sh e)
- suspendedComputeP :: (Load r1 sh e, Target r2 e) => Array r1 sh e -> Array r2 sh e
- copyS :: (Source r1 e, Load D sh e, Target r2 e) => Array r1 sh e -> Array r2 sh e
- copyP :: (Source r1 e, Source r2 e, Load D sh e, Target r2 e, Monad m) => Array r1 sh e -> m (Array r2 sh e)
- suspendedCopyP :: (Source r1 e, Load D sh e, Target r2 e) => Array r1 sh e -> Array r2 sh e
- now :: (Shape sh, Source r e, Monad m) => Array r sh e -> m (Array r sh e)
- fillLinearS :: Int -> (Int -> a -> IO ()) -> (Int -> a) -> IO ()
- fillChunkedP :: Int -> (Int -> a -> IO ()) -> (Int -> a) -> IO ()
- fillChunkedIOP :: Int -> (Int -> a -> IO ()) -> (Int -> IO (Int -> IO a)) -> IO ()
- fillInterleavedP :: Int -> (Int -> a -> IO ()) -> (Int -> a) -> IO ()
- fillBlock2P :: Elt a => (Int -> a -> IO ()) -> (DIM2 -> a) -> Int# -> Int# -> Int# -> Int# -> Int# -> IO ()
- fillBlock2S :: (Int -> a -> IO ()) -> (DIM2 -> a) -> Int# -> Int# -> Int# -> Int# -> Int# -> IO ()
- fillCursoredBlock2S :: Elt a => (Int -> a -> IO ()) -> (DIM2 -> cursor) -> (DIM2 -> cursor -> cursor) -> (cursor -> a) -> Int# -> Int# -> Int# -> Int# -> Int# -> IO ()
- fillCursoredBlock2P :: Elt a => (Int -> a -> IO ()) -> (DIM2 -> cursor) -> (DIM2 -> cursor -> cursor) -> (cursor -> a) -> Int# -> Int# -> Int# -> Int# -> Int# -> IO ()
- selectChunkedS :: Shape sh => (sh -> a -> IO ()) -> (sh -> Bool) -> (sh -> a) -> sh -> IO Int
- selectChunkedP :: forall a. Unbox a => (Int -> Bool) -> (Int -> a) -> Int -> IO [IOVector a]

# Element types

class Elt a where Source #

Element types that can be used with the blockwise filling functions.

This class is mainly used to define the `touch` method. This is used internally in the imeplementation of Repa to prevent let-binding from being floated inappropriately by the GHC simplifier. Doing a `seq` sometimes isn't enough, because the GHC simplifier can erase these, and still move around the bindings.

Methods

touch :: a -> IO () Source #

Place a demand on a value at a particular point in an IO computation.

touch :: (Generic a, GElt (Rep a)) => a -> IO () Source #

Place a demand on a value at a particular point in an IO computation.

zero :: a Source #

Generic zero value, helpful for debugging.

zero :: (Generic a, GElt (Rep a)) => a Source #

Generic zero value, helpful for debugging.

one :: a Source #

Generic one value, helpful for debugging.

one :: (Generic a, GElt (Rep a)) => a Source #

Generic one value, helpful for debugging.

Instances

Elt Bool Source # |
Methods touch :: Bool -> IO () Source # zero :: Bool Source # one :: Bool Source #
Elt Double Source # |
Methods touch :: Double -> IO () Source # zero :: Double Source # one :: Double Source #
Elt Float Source # |
Methods touch :: Float -> IO () Source # zero :: Float Source # one :: Float Source #
Elt Int Source # |
Methods touch :: Int -> IO () Source # zero :: Int Source # one :: Int Source #
Elt Int8 Source # |
Methods touch :: Int8 -> IO () Source # zero :: Int8 Source # one :: Int8 Source #
Elt Int16 Source # |
Methods touch :: Int16 -> IO () Source # zero :: Int16 Source # one :: Int16 Source #
Elt Int32 Source # |
Methods touch :: Int32 -> IO () Source # zero :: Int32 Source # one :: Int32 Source #
Elt Int64 Source # |
Methods touch :: Int64 -> IO () Source # zero :: Int64 Source # one :: Int64 Source #
Elt Word Source # |
Methods touch :: Word -> IO () Source # zero :: Word Source # one :: Word Source #
Elt Word8 Source # |
Methods touch :: Word8 -> IO () Source # zero :: Word8 Source # one :: Word8 Source #
Elt Word16 Source # |
Methods touch :: Word16 -> IO () Source # zero :: Word16 Source # one :: Word16 Source #
Elt Word32 Source # |
Methods touch :: Word32 -> IO () Source # zero :: Word32 Source # one :: Word32 Source #
Elt Word64 Source # |
Methods touch :: Word64 -> IO () Source # zero :: Word64 Source # one :: Word64 Source #
(Elt a, Elt b) => Elt (a, b) Source # |
Methods touch :: (a, b) -> IO () Source # zero :: (a, b) Source # one :: (a, b) Source #
(Elt a, Elt b, Elt c) => Elt (a, b, c) Source # |
Methods touch :: (a, b, c) -> IO () Source # zero :: (a, b, c) Source # one :: (a, b, c) Source #
(Elt a, Elt b, Elt c, Elt d) => Elt (a, b, c, d) Source # |
Methods touch :: (a, b, c, d) -> IO () Source # zero :: (a, b, c, d) Source # one :: (a, b, c, d) Source #
(Elt a, Elt b, Elt c, Elt d, Elt e) => Elt (a, b, c, d, e) Source # |
Methods touch :: (a, b, c, d, e) -> IO () Source # zero :: (a, b, c, d, e) Source # one :: (a, b, c, d, e) Source #
(Elt a, Elt b, Elt c, Elt d, Elt e, Elt f) => Elt (a, b, c, d, e, f) Source # |
Methods touch :: (a, b, c, d, e, f) -> IO () Source # zero :: (a, b, c, d, e, f) Source # one :: (a, b, c, d, e, f) Source #

# Parallel array filling

class Target r e where Source #

Class of manifest array representations that can be constructed in parallel.

Minimal complete definition

newMVec, unsafeWriteMVec, unsafeFreezeMVec, deepSeqMVec, touchMVec

Associated Types

data MVec r e Source #

Mutable version of the representation.

Methods

newMVec :: Int -> IO (MVec r e) Source #

Allocate a new mutable array of the given size.

unsafeWriteMVec :: MVec r e -> Int -> e -> IO () Source #

Write an element into the mutable array.

unsafeFreezeMVec :: sh -> MVec r e -> IO (Array r sh e) Source #

Freeze the mutable array into an immutable Repa array.

deepSeqMVec :: MVec r e -> a -> a Source #

Ensure the strucure of a mutable array is fully evaluated.

touchMVec :: MVec r e -> IO () Source #

Ensure the array is still live at this point. Needed when the mutable array is a ForeignPtr with a finalizer.

Instances

Storable e => Target F e Source # | Filling foreign buffers.
Associated Types data MVec F e :: * Source # Methods newMVec :: Int -> IO (MVec F e) Source # unsafeWriteMVec :: MVec F e -> Int -> e -> IO () Source # unsafeFreezeMVec :: sh -> MVec F e -> IO (Array F sh e) Source # deepSeqMVec :: MVec F e -> a -> a Source # touchMVec :: MVec F e -> IO () Source #
Unbox e => Target U e Source # | Filling of unboxed vector arrays.
Associated Types data MVec U e :: * Source # Methods newMVec :: Int -> IO (MVec U e) Source # unsafeWriteMVec :: MVec U e -> Int -> e -> IO () Source # unsafeFreezeMVec :: sh -> MVec U e -> IO (Array U sh e) Source # deepSeqMVec :: MVec U e -> a -> a Source # touchMVec :: MVec U e -> IO () Source #
Target V e Source # | Filling of boxed vector arrays.
Associated Types data MVec V e :: * Source # Methods newMVec :: Int -> IO (MVec V e) Source # unsafeWriteMVec :: MVec V e -> Int -> e -> IO () Source # unsafeFreezeMVec :: sh -> MVec V e -> IO (Array V sh e) Source # deepSeqMVec :: MVec V e -> a -> a Source # touchMVec :: MVec V e -> IO () Source #

class (Source r1 e, Shape sh) => Load r1 sh e where Source #

Compute all elements defined by an array and write them to a manifest target representation.

Note that instances require that the source array to have a delayed representation such as `D` or `C`. If you want to use a pre-existing manifest array as the source then `delay` it first.

Minimal complete definition

loadS, loadP

Methods

loadS :: Target r2 e => Array r1 sh e -> MVec r2 e -> IO () Source #

Fill an entire array sequentially.

loadP :: Target r2 e => Array r1 sh e -> MVec r2 e -> IO () Source #

Fill an entire array in parallel.

Instances

Shape sh => Load D sh e Source # | Compute all elements in an array.
Methods loadS :: Target r2 e => Array D sh e -> MVec r2 e -> IO () Source # loadP :: Target r2 e => Array D sh e -> MVec r2 e -> IO () Source #
Shape sh => Load X sh e Source # |
Methods loadS :: Target r2 e => Array X sh e -> MVec r2 e -> IO () Source # loadP :: Target r2 e => Array X sh e -> MVec r2 e -> IO () Source #
Elt e => Load C DIM2 e Source # | Compute all elements in an rank-2 array.
Methods loadS :: Target r2 e => Array C DIM2 e -> MVec r2 e -> IO () Source # loadP :: Target r2 e => Array C DIM2 e -> MVec r2 e -> IO () Source #
(Shape sh, Load D sh e) => Load (I D) sh e Source # |
Methods loadS :: Target r2 e => Array (I D) sh e -> MVec r2 e -> IO () Source # loadP :: Target r2 e => Array (I D) sh e -> MVec r2 e -> IO () Source #
(Shape sh, Load r1 sh e) => Load (S r1) sh e Source # |
Methods loadS :: Target r2 e => Array (S r1) sh e -> MVec r2 e -> IO () Source # loadP :: Target r2 e => Array (S r1) sh e -> MVec r2 e -> IO () Source #
(LoadRange r1 sh e, Load r2 sh e) => Load (P r1 r2) sh e Source # |
Methods loadS :: Target r2 e => Array (P r1 r2) sh e -> MVec r2 e -> IO () Source # loadP :: Target r2 e => Array (P r1 r2) sh e -> MVec r2 e -> IO () Source #

class (Source r1 e, Shape sh) => LoadRange r1 sh e where Source #

Compute a range of elements defined by an array and write them to a fillable representation.

Minimal complete definition

loadRangeS, loadRangeP

Methods

loadRangeS :: Target r2 e => Array r1 sh e -> MVec r2 e -> sh -> sh -> IO () Source #

Fill a range of an array sequentially.

loadRangeP :: Target r2 e => Array r1 sh e -> MVec r2 e -> sh -> sh -> IO () Source #

Fill a range of an array in parallel.

Instances

Elt e => LoadRange D DIM2 e Source # | Compute a range of elements in a rank-2 array.
Methods loadRangeS :: Target r2 e => Array D DIM2 e -> MVec r2 e -> DIM2 -> DIM2 -> IO () Source # loadRangeP :: Target r2 e => Array D DIM2 e -> MVec r2 e -> DIM2 -> DIM2 -> IO () Source #
Elt e => LoadRange C DIM2 e Source # | Compute a range of elements in a rank-2 array.
Methods loadRangeS :: Target r2 e => Array C DIM2 e -> MVec r2 e -> DIM2 -> DIM2 -> IO () Source # loadRangeP :: Target r2 e => Array C DIM2 e -> MVec r2 e -> DIM2 -> DIM2 -> IO () Source #
(Shape sh, LoadRange r1 sh e) => LoadRange (S r1) sh e Source # |
Methods loadRangeS :: Target r2 e => Array (S r1) sh e -> MVec r2 e -> sh -> sh -> IO () Source # loadRangeP :: Target r2 e => Array (S r1) sh e -> MVec r2 e -> sh -> sh -> IO () Source #

fromList :: (Shape sh, Target r e) => sh -> [e] -> Array r sh e Source #

O(n). Construct a manifest array from a list.

# Converting between representations

computeS :: (Load r1 sh e, Target r2 e) => Array r1 sh e -> Array r2 sh e Source #

Sequential computation of array elements.

computeP :: (Load r1 sh e, Target r2 e, Source r2 e, Monad m) => Array r1 sh e -> m (Array r2 sh e) Source #

Parallel computation of array elements.

- The source array must have a delayed representation like `D`, `C` or `P`, and the result a manifest representation like `U` or `F`.
- If you want to copy data between manifest representations then use `copyP` instead.
- If you want to convert a manifest array back to a delayed representation then use `delay` instead.

suspendedComputeP :: (Load r1 sh e, Target r2 e) => Array r1 sh e -> Array r2 sh e Source #

Suspended parallel computation of array elements.

This version creates a thunk that will evaluate the array on demand. If you force it when another parallel computation is already running then you will get a runtime warning and evaluation will be sequential. Use `deepSeqArray` and `now` to ensure that each array is evaluated before proceeding to the next one.

If unsure then just use the monadic version `computeP`. This one ensures that each array is fully evaluated before continuing.

copyS :: (Source r1 e, Load D sh e, Target r2 e) => Array r1 sh e -> Array r2 sh e Source #

Sequential copying of arrays.

copyP :: (Source r1 e, Source r2 e, Load D sh e, Target r2 e, Monad m) => Array r1 sh e -> m (Array r2 sh e) Source #

Parallel copying of arrays.

- This is a wrapper that delays an array before calling `computeP`.
- You can use it to copy manifest arrays between representations.

suspendedCopyP :: (Source r1 e, Load D sh e, Target r2 e) => Array r1 sh e -> Array r2 sh e Source #

Suspended parallel copy of array elements.

now :: (Shape sh, Source r e, Monad m) => Array r sh e -> m (Array r sh e) Source #

Monadic version of `deepSeqArray`.

Forces an suspended array computation to be completed at this point in a monadic computation.

     do  let arr2 = suspendedComputeP arr1
         ...
         arr3 <- now $ arr2
         ...

# Chunked filling

fillLinearS Source #

Arguments

:: Int | Number of elements.
-> (Int -> a -> IO ()) | Update function to write into result buffer.
-> (Int -> a) | Fn to get the value at a given index.
-> IO () |

Fill something sequentially.

- The array is filled linearly from start to finish.

fillChunkedP Source #

Arguments

:: Int | Number of elements.
-> (Int -> a -> IO ()) | Update function to write into result buffer.
-> (Int -> a) | Fn to get the value at a given index.
-> IO () |

Fill something in parallel.

- The array is split into linear chunks, and each thread linearly fills one chunk.

fillChunkedIOP Source #

Arguments

:: Int | Number of elements.
-> (Int -> a -> IO ()) | Update fn to write into result buffer.
-> (Int -> IO (Int -> IO a)) | Create a fn to get the value at a given index. The first `Int` is the thread number, so you can do some per-thread initialisation.
-> IO () |

Fill something in parallel, using a separate IO action for each thread.

- The array is split into linear chunks, and each thread linearly fills one chunk.

# Interleaved filling

fillInterleavedP Source #

Arguments

:: Int | Number of elements.
-> (Int -> a -> IO ()) | Update function to write into result buffer.
-> (Int -> a) | Fn to get the value at a given index.
-> IO () |

Fill something in parallel.

- The array is split into linear chunks and each thread fills one chunk.

# Blockwise filling

fillBlock2P Source #

Arguments

:: Elt a |
=> (Int -> a -> IO ()) | Update function to write into result buffer.
-> (DIM2 -> a) | Function to evaluate the element at an index.
-> Int# | Width of the whole array.
-> Int# | x0 lower left corner of block to fill
-> Int# | y0
-> Int# | w0 width of block to fill.
-> Int# | h0 height of block to fill.
-> IO () |

Fill a block in a rank-2 array in parallel.

- Blockwise filling can be more cache-efficient than linear filling for rank-2 arrays.
- Coordinates given are of the filled edges of the block.
- We divide the block into columns, and give one column to each thread.
- Each column is filled in row major order from top to bottom.

fillBlock2S Source #

Arguments

:: (Int -> a -> IO ()) | Update function to write into result buffer.
-> (DIM2 -> a) | Fn to get the value at the given index.
-> Int# | Width of the whole array.
-> Int# | x0 lower left corner of block to fill.
-> Int# | y0
-> Int# | w0 width of block to fill
-> Int# | h0 height of block to fill
-> IO () |

Fill a block in a rank-2 array, sequentially.

- Blockwise filling can be more cache-efficient than linear filling for rank-2 arrays.
- The block is filled in row major order from top to bottom.

# Cursored blockwise filling

fillCursoredBlock2S Source #

Arguments

:: Elt a |
=> (Int -> a -> IO ()) | Update function to write into result buffer.
-> (DIM2 -> cursor) | Make a cursor to a particular element.
-> (DIM2 -> cursor -> cursor) | Shift the cursor by an offset.
-> (cursor -> a) | Function to evaluate an element at the given index.
-> Int# | Width of the whole array.
-> Int# | x0 lower left corner of block to fill.
-> Int# | y0
-> Int# | w0 width of block to fill
-> Int# | h0 height of block to fill
-> IO () |

Fill a block in a rank-2 array, sequentially.

- Blockwise filling can be more cache-efficient than linear filling for rank-2 arrays.
- Using cursor functions can help to expose inter-element indexing computations to the GHC and LLVM optimisers.
- Coordinates given are of the filled edges of the block.
- The block is filled in row major order from top to bottom.

fillCursoredBlock2P Source #

Arguments

:: Elt a |
=> (Int -> a -> IO ()) | Update function to write into result buffer.
-> (DIM2 -> cursor) | Make a cursor to a particular element.
-> (DIM2 -> cursor -> cursor) | Shift the cursor by an offset.
-> (cursor -> a) | Function to evaluate the element at an index.
-> Int# | Width of the whole array.
-> Int# | x0 lower left corner of block to fill
-> Int# | y0
-> Int# | w0 width of block to fill
-> Int# | h0 height of block to fill
-> IO () |

Fill a block in a rank-2 array in parallel.

- Blockwise filling can be more cache-efficient than linear filling for rank-2 arrays.
- Using cursor functions can help to expose inter-element indexing computations to the GHC and LLVM optimisers.
- Coordinates given are of the filled edges of the block.
- We divide the block into columns, and give one column to each thread.
- Each column is filled in row major order from top to bottom.

# Chunked selection

selectChunkedS Source #

Arguments

:: Shape sh |
=> (sh -> a -> IO ()) | Update function to write into result.
-> (sh -> Bool) | See if this predicate matches.
-> (sh -> a) | .. and apply fn to the matching index
-> sh | Extent of indices to apply to predicate.
-> IO Int | Number of elements written to destination array.

Select indices matching a predicate.

- This primitive can be useful for writing filtering functions.

selectChunkedP Source #

Arguments

:: Unbox a |
=> (Int -> Bool) | See if this predicate matches.
-> (Int -> a) |
-> Int |
-> IO [IOVector a] |

Select indices matching a predicate, in parallel.

- This primitive can be useful for writing filtering functions.
- The array is split into linear chunks, with one chunk being given to each thread.
- The number of elements in the result array depends on how many threads you're running the program with.