Safe Haskell | Safe-Infered |
---|

Low level interface to parallel array filling operators.

- class Elt a where
- class Fillable r e where
- class (Shape sh, Repr r1 e, Fillable r2 e) => Fill r1 r2 sh e where
- class (Shape sh, Repr r1 e, Fillable r2 e) => FillRange r1 r2 sh e where
- fillRangeS :: Array r1 sh e -> MArr r2 e -> sh -> sh -> IO ()
- fillRangeP :: Array r1 sh e -> MArr r2 e -> sh -> sh -> IO ()

- fromList :: (Shape sh, Fillable r e) => sh -> [e] -> Array r sh e
- computeP :: Fill r1 r2 sh e => Array r1 sh e -> Array r2 sh e
- computeS :: Fill r1 r2 sh e => Array r1 sh e -> Array r2 sh e
- copyP :: (Repr r1 e, Fill D r2 sh e) => Array r1 sh e -> Array r2 sh e
- copyS :: (Repr r1 e, Fill D r2 sh e) => Array r1 sh e -> Array r2 sh e
- now :: (Shape sh, Repr r e, Monad m) => Array r sh e -> m (Array r sh e)
- fillChunkedS :: 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 ()
- fillBlock2P :: Elt a => (Int -> a -> IO ()) -> (DIM2 -> a) -> Int -> Int -> Int -> Int -> Int -> IO ()
- fillBlock2S :: Elt a => (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

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.

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

Generic zero value, helpful for debugging.

Generic one value, helpful for debugging.

Elt Bool | |

Elt Double | |

Elt Float | |

Elt Int | |

Elt Int8 | |

Elt Int16 | |

Elt Int32 | |

Elt Int64 | |

Elt Word | |

Elt Word8 | |

Elt Word16 | |

Elt Word32 | |

Elt Word64 | |

(Elt a, Elt b) => Elt (a, b) | |

(Elt a, Elt b, Elt c) => Elt (a, b, c) | |

(Elt a, Elt b, Elt c, Elt d) => Elt (a, b, c, d) | |

(Elt a, Elt b, Elt c, Elt d, Elt e) => Elt (a, b, c, d, e) | |

(Elt a, Elt b, Elt c, Elt d, Elt e, Elt f) => Elt (a, b, c, d, e, f) |

# Parallel array filling

class Fillable r e whereSource

Class of manifest array representations that can be filled in parallel and then frozen into immutable Repa arrays.

class (Shape sh, Repr r1 e, Fillable r2 e) => Fill r1 r2 sh e whereSource

Compute all elements defined by an array and write them to a fillable 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.

class (Shape sh, Repr r1 e, Fillable r2 e) => FillRange r1 r2 sh e whereSource

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

fromList :: (Shape sh, Fillable r e) => sh -> [e] -> Array r sh eSource

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

# Converting between representations

computeP :: Fill r1 r2 sh e => Array r1 sh e -> Array r2 sh eSource

Parallel computation of array elements.

computeS :: Fill r1 r2 sh e => Array r1 sh e -> Array r2 sh eSource

Sequential computation of array elements.

copyP :: (Repr r1 e, Fill D r2 sh e) => Array r1 sh e -> Array r2 sh eSource

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.
- You can also use it to compute elements, but doing this may not be as efficient. This is because delaying it the second time can hide information about the structure of the original computation.

copyS :: (Repr r1 e, Fill D r2 sh e) => Array r1 sh e -> Array r2 sh eSource

Sequential copying of arrays.

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

Apply `deepSeqArray`

to an array so the result is actually constructed
at this point in a monadic computation.

- Haskell's laziness means that applications of
`computeP`

and`copyP`

are automatically suspended. - Laziness can be problematic for data parallel programs, because we want each array to be constructed in parallel before moving onto the next one.

For example:

do arr2 <- now $ computeP $ map f arr1 arr3 <- now $ computeP $ zipWith arr2 arr1 return arr3

# Chunked filling

:: 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.

:: 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.

:: 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 |

-> IO () |

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

# Blockwise filling

:: 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 | x1 upper right corner of block to fill |

-> Int | y1 |

-> 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.

:: 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# | x1 upper right corner of block to fill |

-> Int# | y1 |

-> IO () |

Fill a block in a rank-2 array sequentially.

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

# Cursored blockwise filling

:: 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# | x1 upper right corner of block to fill. |

-> Int# | y1 |

-> 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.

:: 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 | x1 upper right corner of block to fill |

-> Int | y1 |

-> 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

:: 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.

:: forall a . 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.