repa-3.0.0.1: Data/Array/Repa/Eval.hs
{-# LANGUAGE UndecidableInstances #-}
-- | Low level interface to parallel array filling operators.
module Data.Array.Repa.Eval
( -- * Element types
Elt (..)
-- * Parallel array filling
, Fillable (..)
, Fill (..)
, FillRange (..)
, fromList
-- * Converting between representations
, computeP, computeS
, copyP, copyS
, now
-- * Chunked filling
, fillChunkedS
, fillChunkedP
, fillChunkedIOP
-- * Blockwise filling
, fillBlock2P
, fillBlock2S
-- * Cursored blockwise filling
, fillCursoredBlock2S
, fillCursoredBlock2P
-- * Chunked selection
, selectChunkedS
, selectChunkedP)
where
import Data.Array.Repa.Eval.Elt
import Data.Array.Repa.Eval.Fill
import Data.Array.Repa.Eval.Chunked
import Data.Array.Repa.Eval.Cursored
import Data.Array.Repa.Eval.Selection
import Data.Array.Repa.Repr.Delayed
import Data.Array.Repa.Base
import Data.Array.Repa.Shape
import System.IO.Unsafe
-- | Parallel computation of array elements.
--
-- * The `Fill` class is defined so that the source array must have a
-- delayed representation (`D` or `C`)
--
-- * 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.
--
computeP :: Fill r1 r2 sh e
=> Array r1 sh e -> Array r2 sh e
{-# INLINE [4] computeP #-}
computeP arr1
= arr1 `deepSeqArray`
unsafePerformIO
$ do marr2 <- newMArr (size $ extent arr1)
fillP arr1 marr2
unsafeFreezeMArr (extent arr1) marr2
-- | Sequential computation of array elements.
computeS
:: Fill r1 r2 sh e
=> Array r1 sh e -> Array r2 sh e
{-# INLINE [4] computeS #-}
computeS arr1
= arr1 `deepSeqArray`
unsafePerformIO
$ do marr2 <- newMArr (size $ extent arr1)
fillS arr1 marr2
unsafeFreezeMArr (extent arr1) marr2
-- | 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.
--
copyP :: (Repr r1 e, Fill D r2 sh e)
=> Array r1 sh e -> Array r2 sh e
{-# INLINE [4] copyP #-}
copyP arr1 = computeP $ delay arr1
-- | Sequential copying of arrays.
copyS :: (Repr r1 e, Fill D r2 sh e)
=> Array r1 sh e -> Array r2 sh e
{-# INLINE [4] copyS #-}
copyS arr1 = computeS $ delay arr1
-- | 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
-- @
--
now :: (Shape sh, Repr r e, Monad m)
=> Array r sh e -> m (Array r sh e)
{-# INLINE [4] now #-}
now arr
= do arr `deepSeqArray` return ()
return arr