{-# LANGUAGE CPP, GADTs #-} -- | -- Module : Data.Array.Accelerate.CUDA.Analysis.Hash -- Copyright : [2008..2011] Manuel M T Chakravarty, Gabriele Keller, Sean Lee, Trevor L. McDonell -- License : BSD3 -- -- Maintainer : Manuel M T Chakravarty -- Stability : experimental -- Portability : non-partable (GHC extensions) -- module Data.Array.Accelerate.CUDA.Analysis.Hash ( AccKey, accToKey, hashAccKey ) where import Data.Char import Language.C import Text.PrettyPrint import Codec.Compression.Zlib import Data.ByteString.Lazy.Char8 (ByteString) import qualified Data.ByteString.Lazy.Char8 as L import qualified Data.HashTable as Hash import Data.Array.Accelerate.AST import Data.Array.Accelerate.Type import Data.Array.Accelerate.Pretty () import Data.Array.Accelerate.Analysis.Type import Data.Array.Accelerate.Analysis.Shape import Data.Array.Accelerate.CUDA.CodeGen import Data.Array.Accelerate.Array.Representation import qualified Data.Array.Accelerate.Array.Sugar as Sugar #include "accelerate.h" type AccKey = ByteString -- | Reimplementation of Data.HashTable.hashString to fold over a lazy -- bytestring rather than a list of characters. -- hashAccKey :: AccKey -> Int32 hashAccKey = L.foldl' f golden where f m c = fromIntegral (ord c) * magic + Hash.hashInt (fromIntegral m) magic = 0xdeadbeef golden = 1013904242 -- = round ((sqrt 5 - 1) * 2^32) -- | Generate a unique key for each kernel computation -- accToKey :: OpenAcc aenv a -> AccKey accToKey acc = let key = compress . L.pack $ showAcc acc in L.head key `seq` key -- The first radical identifies the skeleton type (actually, this is arithmetic -- sequence A000978), followed by the salient features that parameterise -- skeleton instantiation. -- showAcc :: OpenAcc aenv a -> String showAcc acc@(OpenAcc pacc) = case pacc of Generate e f -> chr 1 : showExp e ++ showFun f Replicate s e a -> chr 3 : showTy (accType a) ++ showExp e ++ showSI s e a acc Index s a e -> chr 5 : showTy (accType a) ++ showExp e ++ showSI s e acc a Map f a -> chr 7 : showTy (accType a) ++ showFun f ZipWith f x y -> chr 11 : showTy (accType x) ++ showTy (accType y) ++ showFun f Fold f e a -> chr 13 : chr (accDim a) : showTy (accType a) ++ showFun f ++ showExp e Fold1 f a -> chr 17 : chr (accDim a) : showTy (accType a) ++ showFun f FoldSeg f e a _ -> chr 19 : chr (accDim a) : showTy (accType a) ++ showFun f ++ showExp e Fold1Seg f a _ -> chr 23 : chr (accDim a) : showTy (accType a) ++ showFun f Scanl f e a -> chr 31 : showTy (accType a) ++ showFun f ++ showExp e Scanl' f e a -> chr 43 : showTy (accType a) ++ showFun f ++ showExp e Scanl1 f a -> chr 61 : showTy (accType a) ++ showFun f Scanr f e a -> chr 79 : showTy (accType a) ++ showFun f ++ showExp e Scanr' f e a -> chr 101 : showTy (accType a) ++ showFun f ++ showExp e Scanr1 f a -> chr 127 : showTy (accType a) ++ showFun f Permute c _ p a -> chr 167 : showTy (accType a) ++ showFun c ++ showFun p Backpermute _ p a -> chr 191 : showTy (accType a) ++ showFun p Stencil f _ a -> chr 199 : showTy (accType a) ++ showFun f Stencil2 f _ x _ y -> chr 313 : showTy (accType x) ++ showTy (accType y) ++ showFun f _ -> let msg = unlines ["incomplete patterns for key generation", render (nest 2 doc)] ppr = show acc doc | length ppr <= 250 = text ppr | otherwise = text (take 250 ppr) <+> text "... {truncated}" in INTERNAL_ERROR(error) "accToKey" msg where showTy :: TupleType a -> String showTy UnitTuple = [] showTy (SingleTuple ty) = show ty showTy (PairTuple a b) = showTy a ++ showTy b showFun :: OpenFun env aenv a -> String showFun = render . hcat . map pretty . codeGenFun showExp :: OpenExp env aenv a -> String showExp = render . hcat . map pretty . codeGenExp showSI :: SliceIndex (Sugar.EltRepr slix) (Sugar.EltRepr sl) co (Sugar.EltRepr dim) -> Exp aenv slix {- dummy -} -> OpenAcc aenv (Sugar.Array sl e) {- dummy -} -> OpenAcc aenv (Sugar.Array dim e) {- dummy -} -> String showSI sl _ _ _ = slice sl 0 where slice :: SliceIndex slix sl co dim -> Int -> String slice (SliceNil) _ = [] slice (SliceAll sliceIdx) n = '_' : slice sliceIdx n slice (SliceFixed sliceIdx) n = show n ++ slice sliceIdx (n+1) {- -- hash function from the dragon book pp437; assumes 7 bit characters and needs -- the (nearly) full range of values guaranteed for `Int' by the Haskell -- language definition; can handle 8 bit characters provided we have 29 bit for -- the `Int's without sign -- quad :: String -> Int32 quad (c1:c2:c3:c4:s) = (( ord' c4 * bits21 + ord' c3 * bits14 + ord' c2 * bits7 + ord' c1) `mod` bits28) + (quad s `mod` bits28) quad (c1:c2:c3:[] ) = ord' c3 * bits14 + ord' c2 * bits7 + ord' c1 quad (c1:c2:[] ) = ord' c2 * bits7 + ord' c1 quad (c1:[] ) = ord' c1 quad ([] ) = 0 ord' :: Char -> Int32 ord' = fromIntegral . ord bits7, bits14, bits21, bits28 :: Int32 bits7 = 2^(7 ::Int32) bits14 = 2^(14::Int32) bits21 = 2^(21::Int32) bits28 = 2^(28::Int32) -}