{-# LANGUAGE GADTs #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# OPTIONS_GHC -fno-warn-name-shadowing #-}
{-# OPTIONS_HADDOCK hide #-}
module Data.Array.Accelerate.LLVM.Array.Data (
Remote(..),
newRemote,
useRemote, useRemoteAsync,
copyToRemote, copyToRemoteAsync,
copyToHost, copyToHostAsync,
copyToPeer, copyToPeerAsync,
runIndexArray,
runArrays,
runArray,
module Data.Array.Accelerate.Array.Data,
) where
import Data.Array.Accelerate.Array.Data
import Data.Array.Accelerate.Array.Sugar
import Data.Array.Accelerate.LLVM.State
import Data.Array.Accelerate.LLVM.Execute.Async
import Control.Monad ( liftM, liftM2 )
import Control.Monad.Trans
import Data.Typeable
import Foreign.C.Types
import Foreign.Ptr
import Foreign.Storable
import Prelude
class Async arch => Remote arch where
{-# INLINEABLE allocateRemote #-}
allocateRemote :: (Shape sh, Elt e) => sh -> LLVM arch (Array sh e)
allocateRemote sh = liftIO $ allocateArray sh
{-# INLINEABLE useRemoteR #-}
useRemoteR
:: (ArrayElt e, ArrayPtrs e ~ Ptr a, Storable a, Typeable a, Typeable e)
=> Int
-> Maybe (StreamR arch)
-> ArrayData e
-> LLVM arch ()
useRemoteR _ _ _ = return ()
{-# INLINEABLE copyToRemoteR #-}
copyToRemoteR
:: (ArrayElt e, ArrayPtrs e ~ Ptr a, Storable a, Typeable a, Typeable e)
=> Int
-> Int
-> Maybe (StreamR arch)
-> ArrayData e
-> LLVM arch ()
copyToRemoteR _ _ _ _ = return ()
{-# INLINEABLE copyToHostR #-}
copyToHostR
:: (ArrayElt e, ArrayPtrs e ~ Ptr a, Storable a, Typeable a, Typeable e)
=> Int
-> Int
-> Maybe (StreamR arch)
-> ArrayData e
-> LLVM arch ()
copyToHostR _ _ _ _ = return ()
{-# INLINEABLE copyToPeerR #-}
copyToPeerR
:: (ArrayElt e, ArrayPtrs e ~ Ptr a, Storable a, Typeable a, Typeable e)
=> Int
-> Int
-> arch
-> Maybe (StreamR arch)
-> ArrayData e
-> LLVM arch ()
copyToPeerR _ _ _ _ _ = return ()
{-# INLINEABLE indexRemote #-}
indexRemote :: Array sh e -> Int -> LLVM arch e
indexRemote (Array _ adata) i = return . toElt $! unsafeIndexArrayData adata i
{-# INLINEABLE newRemote #-}
newRemote
:: (Remote arch, Shape sh, Elt e)
=> sh
-> (sh -> e)
-> LLVM arch (Array sh e)
newRemote sh f =
useRemote $! fromFunction sh f
{-# INLINEABLE useRemote #-}
useRemote :: (Remote arch, Arrays arrs) => arrs -> LLVM arch arrs
useRemote arrs = do
AsyncR _ a <- async (useRemoteAsync arrs)
get a
{-# INLINEABLE useRemoteAsync #-}
useRemoteAsync
:: (Remote arch, Arrays arrs)
=> arrs
-> StreamR arch
-> LLVM arch (AsyncR arch arrs)
useRemoteAsync arrs stream = do
arrs' <- runArrays arrs $ \arr@Array{} ->
let n = size (shape arr)
in runArray arr $ \ad -> do
s <- fork
useRemoteR n (Just s) ad
after stream =<< checkpoint s
join s
return ad
event <- checkpoint stream
return $! AsyncR event arrs'
{-# INLINEABLE copyToRemote #-}
copyToRemote :: (Remote arch, Arrays a) => a -> LLVM arch a
copyToRemote arrs = do
AsyncR _ a <- async (copyToRemoteAsync arrs)
get a
{-# INLINEABLE copyToRemoteAsync #-}
copyToRemoteAsync
:: (Remote arch, Arrays a)
=> a
-> StreamR arch
-> LLVM arch (AsyncR arch a)
copyToRemoteAsync arrs stream = do
arrs' <- runArrays arrs $ \arr@Array{} ->
let n = size (shape arr)
in runArray arr $ \ad -> do
s <- fork
copyToRemoteR 0 n (Just s) ad
after stream =<< checkpoint s
join s
return ad
event <- checkpoint stream
return $! AsyncR event arrs'
{-# INLINEABLE copyToHost #-}
copyToHost :: (Remote arch, Arrays a) => a -> LLVM arch a
copyToHost arrs = do
AsyncR _ a <- async (copyToHostAsync arrs)
get a
{-# INLINEABLE copyToHostAsync #-}
copyToHostAsync
:: (Remote arch, Arrays a)
=> a
-> StreamR arch
-> LLVM arch (AsyncR arch a)
copyToHostAsync arrs stream = do
arrs' <- runArrays arrs $ \arr@Array{} ->
let n = size (shape arr)
in runArray arr $ \ad -> do
s <- fork
copyToHostR 0 n (Just s) ad
after stream =<< checkpoint s
join s
return ad
event <- checkpoint stream
return $! AsyncR event arrs'
{-# INLINEABLE copyToPeer #-}
copyToPeer :: (Remote arch, Arrays a) => arch -> a -> LLVM arch a
copyToPeer peer arrs = do
AsyncR _ a <- async (copyToPeerAsync peer arrs)
get a
{-# INLINEABLE copyToPeerAsync #-}
copyToPeerAsync
:: (Remote arch, Arrays a)
=> arch
-> a
-> StreamR arch
-> LLVM arch (AsyncR arch a)
copyToPeerAsync peer arrs stream = do
arrs' <- runArrays arrs $ \arr@Array{} ->
let n = size (shape arr)
in runArray arr $ \ad -> do
s <- fork
copyToPeerR 0 n peer (Just s) ad
after stream =<< checkpoint s
join s
return ad
event <- checkpoint stream
return $! AsyncR event arrs'
{-# INLINEABLE runIndexArray #-}
runIndexArray
:: forall m sh e. Monad m
=> (forall e a. (ArrayElt e, ArrayPtrs e ~ Ptr a, Storable a, Typeable a, Typeable e) => ArrayData e -> Int -> m a)
-> Array sh e
-> Int
-> m e
runIndexArray worker (Array _ adata) i = toElt `liftM` indexR arrayElt adata
where
indexR :: ArrayEltR a -> ArrayData a -> m a
indexR ArrayEltRunit _ = return ()
indexR (ArrayEltRpair aeR1 aeR2) ad = liftM2 (,) (indexR aeR1 (fstArrayData ad))
(indexR aeR2 (sndArrayData ad))
indexR ArrayEltRint ad = worker ad i
indexR ArrayEltRint8 ad = worker ad i
indexR ArrayEltRint16 ad = worker ad i
indexR ArrayEltRint32 ad = worker ad i
indexR ArrayEltRint64 ad = worker ad i
indexR ArrayEltRword ad = worker ad i
indexR ArrayEltRword8 ad = worker ad i
indexR ArrayEltRword16 ad = worker ad i
indexR ArrayEltRword32 ad = worker ad i
indexR ArrayEltRword64 ad = worker ad i
indexR ArrayEltRfloat ad = worker ad i
indexR ArrayEltRdouble ad = worker ad i
indexR ArrayEltRchar ad = worker ad i
indexR ArrayEltRcshort ad = CShort `liftM` worker ad i
indexR ArrayEltRcushort ad = CUShort `liftM` worker ad i
indexR ArrayEltRcint ad = CInt `liftM` worker ad i
indexR ArrayEltRcuint ad = CUInt `liftM` worker ad i
indexR ArrayEltRclong ad = CLong `liftM` worker ad i
indexR ArrayEltRculong ad = CULong `liftM` worker ad i
indexR ArrayEltRcllong ad = CLLong `liftM` worker ad i
indexR ArrayEltRcullong ad = CULLong `liftM` worker ad i
indexR ArrayEltRcchar ad = CChar `liftM` worker ad i
indexR ArrayEltRcschar ad = CSChar `liftM` worker ad i
indexR ArrayEltRcuchar ad = CUChar `liftM` worker ad i
indexR ArrayEltRcfloat ad = CFloat `liftM` worker ad i
indexR ArrayEltRcdouble ad = CDouble `liftM` worker ad i
indexR ArrayEltRbool ad = toBool `liftM` worker ad i
where
toBool 0 = False
toBool _ = True
{-# INLINE runArrays #-}
runArrays
:: forall m arrs. (Monad m, Arrays arrs)
=> arrs
-> (forall sh e. Array sh e -> m (Array sh e))
-> m arrs
runArrays arrs worker = toArr `liftM` runR (arrays arrs) (fromArr arrs)
where
runR :: ArraysR a -> a -> m a
runR ArraysRunit () = return ()
runR ArraysRarray arr = worker arr
runR (ArraysRpair aeR2 aeR1) (arrs2, arrs1) = liftM2 (,) (runR aeR2 arrs2) (runR aeR1 arrs1)
{-# INLINE runArray #-}
runArray
:: forall m sh e. Monad m
=> Array sh e
-> (forall e' p. (ArrayElt e', ArrayPtrs e' ~ Ptr p, Storable p, Typeable p, Typeable e') => ArrayData e' -> m (ArrayData e'))
-> m (Array sh e)
runArray (Array sh adata) worker = Array sh `liftM` runR arrayElt adata
where
runR :: ArrayEltR e' -> ArrayData e' -> m (ArrayData e')
runR ArrayEltRunit AD_Unit = return AD_Unit
runR (ArrayEltRpair aeR2 aeR1) (AD_Pair ad2 ad1) = liftM2 AD_Pair (runR aeR2 ad2) (runR aeR1 ad1)
runR ArrayEltRint ad = worker ad
runR ArrayEltRint8 ad = worker ad
runR ArrayEltRint16 ad = worker ad
runR ArrayEltRint32 ad = worker ad
runR ArrayEltRint64 ad = worker ad
runR ArrayEltRword ad = worker ad
runR ArrayEltRword8 ad = worker ad
runR ArrayEltRword16 ad = worker ad
runR ArrayEltRword32 ad = worker ad
runR ArrayEltRword64 ad = worker ad
runR ArrayEltRfloat ad = worker ad
runR ArrayEltRdouble ad = worker ad
runR ArrayEltRbool ad = worker ad
runR ArrayEltRchar ad = worker ad
runR ArrayEltRcshort ad = worker ad
runR ArrayEltRcushort ad = worker ad
runR ArrayEltRcint ad = worker ad
runR ArrayEltRcuint ad = worker ad
runR ArrayEltRclong ad = worker ad
runR ArrayEltRculong ad = worker ad
runR ArrayEltRcllong ad = worker ad
runR ArrayEltRcullong ad = worker ad
runR ArrayEltRcfloat ad = worker ad
runR ArrayEltRcdouble ad = worker ad
runR ArrayEltRcchar ad = worker ad
runR ArrayEltRcschar ad = worker ad
runR ArrayEltRcuchar ad = worker ad