accelerate-cuda-0.12.0.0: Data/Array/Accelerate/CUDA/CodeGen/Mapping.hs
{-# LANGUAGE GADTs #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# OPTIONS -fno-warn-incomplete-patterns #-}
-- |
-- Module : Data.Array.Accelerate.CUDA.CodeGen.Mapping
-- Copyright : [2008..2010] Manuel M T Chakravarty, Gabriele Keller, Sean Lee
-- [2009..2012] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell
-- License : BSD3
--
-- Maintainer : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>
-- Stability : experimental
-- Portability : non-portable (GHC extensions)
--
module Data.Array.Accelerate.CUDA.CodeGen.Mapping (
mkMap, mkZipWith
) where
import Language.C.Quote.CUDA
import Data.Array.Accelerate.Array.Sugar ( Elt )
import Data.Array.Accelerate.CUDA.CodeGen.Base
import Data.Array.Accelerate.CUDA.CodeGen.Type
-- Apply the given unary function to each element of an array. Each thread
-- processes multiple elements, striding the array by the grid size.
--
-- map :: (Shape sh, Elt a, Elt b)
-- => (Exp a -> Exp b)
-- -> Acc (Array sh a)
-- -> Acc (Array sh b)
--
mkMap :: forall a b. Elt b => CUFun (a -> b) -> CUTranslSkel
mkMap (CULam use0 (CUBody (CUExp env fn))) =
CUTranslSkel "map" [cunit|
extern "C"
__global__ void
map
(
$params:argOut,
$params:argIn0,
const typename Ix num_elements
)
{
const int gridSize = __umul24(blockDim.x, gridDim.x);
int ix;
for ( ix = __umul24(blockDim.x, blockIdx.x) + threadIdx.x
; ix < num_elements
; ix += gridSize)
{
$decls:(getIn0 "ix")
$decls:env
$stms:(setOut "ix" fn)
}
}
|]
where
tyIn0 = eltType (undefined :: a)
tyOut = eltType (undefined :: b)
(argIn0, _, _, _, getIn0) = getters 0 tyIn0 use0
(argOut, _, setOut) = setters tyOut
-- Apply the given binary function element-wise to the two arrays. The extent of
-- the resulting array is the intersection of the extents of the two source
-- arrays. Each thread processes multiple elements, striding the array by the
-- grid size.
--
-- zipWith :: (Shape ix, Elt a, Elt b, Elt c)
-- => (Exp a -> Exp b -> Exp c)
-- -> Acc (Array ix a)
-- -> Acc (Array ix b)
-- -> Acc (Array ix c)
--
mkZipWith :: forall a b c. Elt c => Int -> CUFun (a -> b -> c) -> CUTranslSkel
mkZipWith dim (CULam use1 (CULam use0 (CUBody (CUExp env fn)))) =
CUTranslSkel "zipWith" [cunit|
$edecl:(cdim "DimOut" dim)
$edecl:(cdim "DimIn0" dim)
$edecl:(cdim "DimIn1" dim)
extern "C"
__global__ void
zipWith
(
$params:argOut,
$params:argIn1,
$params:argIn0,
const typename DimOut shOut,
const typename DimIn1 shIn1,
const typename DimIn0 shIn0
)
{
const int shapeSize = size(shOut);
const int gridSize = __umul24(blockDim.x, gridDim.x);
int ix;
for ( ix = __umul24(blockDim.x, blockIdx.x) + threadIdx.x
; ix < shapeSize
; ix += gridSize)
{
const int ix1 = toIndex(shIn1, fromIndex(shOut, ix));
const int ix0 = toIndex(shIn0, fromIndex(shOut, ix));
$decls:(getIn0 "ix0")
$decls:(getIn1 "ix1")
$decls:env
$stms:(setOut "ix" fn)
}
}
|]
where
tyIn1 = eltType (undefined :: a)
tyIn0 = eltType (undefined :: b)
tyOut = eltType (undefined :: c)
(argIn1, _, _, _, getIn1) = getters 1 tyIn1 use1
(argIn0, _, _, _, getIn0) = getters 0 tyIn0 use0
(argOut, _, setOut) = setters tyOut