/Data/Array/Accelerate/CUDA/Analysis/Hash.hs

https://github.com/sajith/accelerate · Haskell · 143 lines · 79 code · 18 blank · 46 comment · 1 complexity · ce56c0f94da7beff4fad98f8c0d59841 MD5 · raw file

  1. {-# LANGUAGE CPP, GADTs #-}
  2. -- |
  3. -- Module : Data.Array.Accelerate.CUDA.Analysis.Hash
  4. -- Copyright : [2008..2011] Manuel M T Chakravarty, Gabriele Keller, Sean Lee, Trevor L. McDonell
  5. -- License : BSD3
  6. --
  7. -- Maintainer : Manuel M T Chakravarty <chak@cse.unsw.edu.au>
  8. -- Stability : experimental
  9. -- Portability : non-partable (GHC extensions)
  10. --
  11. module Data.Array.Accelerate.CUDA.Analysis.Hash (
  12. AccKey, accToKey, hashAccKey
  13. ) where
  14. import Data.Char
  15. import Language.C
  16. import Text.PrettyPrint
  17. import Codec.Compression.Zlib
  18. import Data.ByteString.Lazy.Char8 (ByteString)
  19. import qualified Data.ByteString.Lazy.Char8 as L
  20. import qualified Data.HashTable as Hash
  21. import Data.Array.Accelerate.AST
  22. import Data.Array.Accelerate.Type
  23. import Data.Array.Accelerate.Pretty ()
  24. import Data.Array.Accelerate.Analysis.Type
  25. import Data.Array.Accelerate.Analysis.Shape
  26. import Data.Array.Accelerate.CUDA.CodeGen
  27. import Data.Array.Accelerate.Array.Representation
  28. import qualified Data.Array.Accelerate.Array.Sugar as Sugar
  29. #include "accelerate.h"
  30. type AccKey = ByteString
  31. -- | Reimplementation of Data.HashTable.hashString to fold over a lazy
  32. -- bytestring rather than a list of characters.
  33. --
  34. hashAccKey :: AccKey -> Int32
  35. hashAccKey = L.foldl' f golden
  36. where
  37. f m c = fromIntegral (ord c) * magic + Hash.hashInt (fromIntegral m)
  38. magic = 0xdeadbeef
  39. golden = 1013904242 -- = round ((sqrt 5 - 1) * 2^32)
  40. -- | Generate a unique key for each kernel computation
  41. --
  42. accToKey :: OpenAcc aenv a -> AccKey
  43. accToKey acc =
  44. let key = compress . L.pack $ showAcc acc
  45. in L.head key `seq` key
  46. -- The first radical identifies the skeleton type (actually, this is arithmetic
  47. -- sequence A000978), followed by the salient features that parameterise
  48. -- skeleton instantiation.
  49. --
  50. showAcc :: OpenAcc aenv a -> String
  51. showAcc acc@(OpenAcc pacc) =
  52. case pacc of
  53. Generate e f -> chr 1 : showExp e ++ showFun f
  54. Replicate s e a -> chr 3 : showTy (accType a) ++ showExp e ++ showSI s e a acc
  55. Index s a e -> chr 5 : showTy (accType a) ++ showExp e ++ showSI s e acc a
  56. Map f a -> chr 7 : showTy (accType a) ++ showFun f
  57. ZipWith f x y -> chr 11 : showTy (accType x) ++ showTy (accType y) ++ showFun f
  58. Fold f e a -> chr 13 : chr (accDim a) : showTy (accType a) ++ showFun f ++ showExp e
  59. Fold1 f a -> chr 17 : chr (accDim a) : showTy (accType a) ++ showFun f
  60. FoldSeg f e a _ -> chr 19 : chr (accDim a) : showTy (accType a) ++ showFun f ++ showExp e
  61. Fold1Seg f a _ -> chr 23 : chr (accDim a) : showTy (accType a) ++ showFun f
  62. Scanl f e a -> chr 31 : showTy (accType a) ++ showFun f ++ showExp e
  63. Scanl' f e a -> chr 43 : showTy (accType a) ++ showFun f ++ showExp e
  64. Scanl1 f a -> chr 61 : showTy (accType a) ++ showFun f
  65. Scanr f e a -> chr 79 : showTy (accType a) ++ showFun f ++ showExp e
  66. Scanr' f e a -> chr 101 : showTy (accType a) ++ showFun f ++ showExp e
  67. Scanr1 f a -> chr 127 : showTy (accType a) ++ showFun f
  68. Permute c _ p a -> chr 167 : showTy (accType a) ++ showFun c ++ showFun p
  69. Backpermute _ p a -> chr 191 : showTy (accType a) ++ showFun p
  70. Stencil f _ a -> chr 199 : showTy (accType a) ++ showFun f
  71. Stencil2 f _ x _ y -> chr 313 : showTy (accType x) ++ showTy (accType y) ++ showFun f
  72. _ ->
  73. let msg = unlines ["incomplete patterns for key generation", render (nest 2 doc)]
  74. ppr = show acc
  75. doc | length ppr <= 250 = text ppr
  76. | otherwise = text (take 250 ppr) <+> text "... {truncated}"
  77. in
  78. INTERNAL_ERROR(error) "accToKey" msg
  79. where
  80. showTy :: TupleType a -> String
  81. showTy UnitTuple = []
  82. showTy (SingleTuple ty) = show ty
  83. showTy (PairTuple a b) = showTy a ++ showTy b
  84. showFun :: OpenFun env aenv a -> String
  85. showFun = render . hcat . map pretty . codeGenFun
  86. showExp :: OpenExp env aenv a -> String
  87. showExp = render . hcat . map pretty . codeGenExp
  88. showSI :: SliceIndex (Sugar.EltRepr slix) (Sugar.EltRepr sl) co (Sugar.EltRepr dim)
  89. -> Exp aenv slix {- dummy -}
  90. -> OpenAcc aenv (Sugar.Array sl e) {- dummy -}
  91. -> OpenAcc aenv (Sugar.Array dim e) {- dummy -}
  92. -> String
  93. showSI sl _ _ _ = slice sl 0
  94. where
  95. slice :: SliceIndex slix sl co dim -> Int -> String
  96. slice (SliceNil) _ = []
  97. slice (SliceAll sliceIdx) n = '_' : slice sliceIdx n
  98. slice (SliceFixed sliceIdx) n = show n ++ slice sliceIdx (n+1)
  99. {-
  100. -- hash function from the dragon book pp437; assumes 7 bit characters and needs
  101. -- the (nearly) full range of values guaranteed for `Int' by the Haskell
  102. -- language definition; can handle 8 bit characters provided we have 29 bit for
  103. -- the `Int's without sign
  104. --
  105. quad :: String -> Int32
  106. quad (c1:c2:c3:c4:s) = (( ord' c4 * bits21
  107. + ord' c3 * bits14
  108. + ord' c2 * bits7
  109. + ord' c1)
  110. `mod` bits28)
  111. + (quad s `mod` bits28)
  112. quad (c1:c2:c3:[] ) = ord' c3 * bits14 + ord' c2 * bits7 + ord' c1
  113. quad (c1:c2:[] ) = ord' c2 * bits7 + ord' c1
  114. quad (c1:[] ) = ord' c1
  115. quad ([] ) = 0
  116. ord' :: Char -> Int32
  117. ord' = fromIntegral . ord
  118. bits7, bits14, bits21, bits28 :: Int32
  119. bits7 = 2^(7 ::Int32)
  120. bits14 = 2^(14::Int32)
  121. bits21 = 2^(21::Int32)
  122. bits28 = 2^(28::Int32)
  123. -}