hw-simd 0.1.0.3 → 0.1.1.0
raw patch · 8 files changed
+179/−17 lines, 8 filesdep ~hw-primPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependency ranges changed: hw-prim
API changes (from Hackage documentation)
+ HaskellWorks.Data.Simd.ChunkString: class ToChunkString a
+ HaskellWorks.Data.Simd.ChunkString: data ChunkString
+ HaskellWorks.Data.Simd.ChunkString: hGetContents :: Handle -> IO ChunkString
+ HaskellWorks.Data.Simd.ChunkString: toChunkString :: ToChunkString a => a -> ChunkString
+ HaskellWorks.Data.Simd.Comparison.Avx2: instance HaskellWorks.Data.Simd.Comparison.Avx2.CmpEqWord8s [Data.ByteString.Internal.ByteString]
+ HaskellWorks.Data.Simd.Comparison.Avx2: type family Target a;
+ HaskellWorks.Data.Simd.Comparison.Avx2: }
+ HaskellWorks.Data.Simd.Comparison.Stock: instance HaskellWorks.Data.Simd.Comparison.Stock.CmpEqWord8s HaskellWorks.Data.Simd.Internal.ChunkString.ChunkString
+ HaskellWorks.Data.Simd.Comparison.Stock: instance HaskellWorks.Data.Simd.Comparison.Stock.CmpEqWord8s [Data.ByteString.Internal.ByteString]
+ HaskellWorks.Data.Simd.Internal.ChunkString: ChunkString :: [ByteString] -> ChunkString
+ HaskellWorks.Data.Simd.Internal.ChunkString: [chunks] :: ChunkString -> [ByteString]
+ HaskellWorks.Data.Simd.Internal.ChunkString: chunkSize :: Int
+ HaskellWorks.Data.Simd.Internal.ChunkString: class ToChunkString a
+ HaskellWorks.Data.Simd.Internal.ChunkString: instance GHC.Classes.Eq HaskellWorks.Data.Simd.Internal.ChunkString.ChunkString
+ HaskellWorks.Data.Simd.Internal.ChunkString: instance GHC.Show.Show HaskellWorks.Data.Simd.Internal.ChunkString.ChunkString
+ HaskellWorks.Data.Simd.Internal.ChunkString: instance HaskellWorks.Data.ByteString.Lazy.ToLazyByteString HaskellWorks.Data.Simd.Internal.ChunkString.ChunkString
+ HaskellWorks.Data.Simd.Internal.ChunkString: instance HaskellWorks.Data.ByteString.ToByteStrings HaskellWorks.Data.Simd.Internal.ChunkString.ChunkString
+ HaskellWorks.Data.Simd.Internal.ChunkString: instance HaskellWorks.Data.Simd.Internal.ChunkString.ToChunkString (Data.Vector.Storable.Vector GHC.Word.Word16)
+ HaskellWorks.Data.Simd.Internal.ChunkString: instance HaskellWorks.Data.Simd.Internal.ChunkString.ToChunkString (Data.Vector.Storable.Vector GHC.Word.Word32)
+ HaskellWorks.Data.Simd.Internal.ChunkString: instance HaskellWorks.Data.Simd.Internal.ChunkString.ToChunkString (Data.Vector.Storable.Vector GHC.Word.Word64)
+ HaskellWorks.Data.Simd.Internal.ChunkString: instance HaskellWorks.Data.Simd.Internal.ChunkString.ToChunkString (Data.Vector.Storable.Vector GHC.Word.Word8)
+ HaskellWorks.Data.Simd.Internal.ChunkString: instance HaskellWorks.Data.Simd.Internal.ChunkString.ToChunkString Data.ByteString.Lazy.Internal.ByteString
+ HaskellWorks.Data.Simd.Internal.ChunkString: instance HaskellWorks.Data.Simd.Internal.ChunkString.ToChunkString [Data.ByteString.Internal.ByteString]
+ HaskellWorks.Data.Simd.Internal.ChunkString: instance HaskellWorks.Data.Simd.Internal.ChunkString.ToChunkString [Data.Vector.Storable.Vector GHC.Word.Word16]
+ HaskellWorks.Data.Simd.Internal.ChunkString: instance HaskellWorks.Data.Simd.Internal.ChunkString.ToChunkString [Data.Vector.Storable.Vector GHC.Word.Word32]
+ HaskellWorks.Data.Simd.Internal.ChunkString: instance HaskellWorks.Data.Simd.Internal.ChunkString.ToChunkString [Data.Vector.Storable.Vector GHC.Word.Word64]
+ HaskellWorks.Data.Simd.Internal.ChunkString: instance HaskellWorks.Data.Simd.Internal.ChunkString.ToChunkString [Data.Vector.Storable.Vector GHC.Word.Word8]
+ HaskellWorks.Data.Simd.Internal.ChunkString: newtype ChunkString
+ HaskellWorks.Data.Simd.Internal.ChunkString: toChunkString :: ToChunkString a => a -> ChunkString
- HaskellWorks.Data.Simd.Comparison.Avx2: class CmpEqWord8s a
+ HaskellWorks.Data.Simd.Comparison.Avx2: class CmpEqWord8s a where {
- HaskellWorks.Data.Simd.Comparison.Avx2: cmpEqWord8s :: CmpEqWord8s a => Word8 -> a -> a
+ HaskellWorks.Data.Simd.Comparison.Avx2: cmpEqWord8s :: CmpEqWord8s a => Word8 -> a -> Target a
- HaskellWorks.Data.Simd.Internal.Foreign: avx2Cmpeq8 :: UInt8 -> Ptr UInt64 -> Size -> Ptr UInt8 -> IO ()
+ HaskellWorks.Data.Simd.Internal.Foreign: avx2Cmpeq8 :: UInt8 -> Ptr UInt8 -> Size -> Ptr UInt8 -> IO ()
- HaskellWorks.Data.Simd.Internal.Foreign: c_cmpeq8 :: (CUChar -> ((Ptr CULong) -> (CULong -> ((Ptr CUChar) -> (IO ())))))
+ HaskellWorks.Data.Simd.Internal.Foreign: c_cmpeq8 :: (CUChar -> ((Ptr CUChar) -> (CULong -> ((Ptr CUChar) -> (IO ())))))
Files
- cbits/simd.h +1/−7
- cbits/simd_avx2.c +1/−1
- hw-simd.cabal +6/−4
- src/HaskellWorks/Data/Simd/ChunkString.hs +14/−0
- src/HaskellWorks/Data/Simd/Comparison/Avx2.hs +42/−3
- src/HaskellWorks/Data/Simd/Comparison/Stock.hs +12/−1
- src/HaskellWorks/Data/Simd/Internal/ChunkString.hs +102/−0
- src/HaskellWorks/Data/Simd/Internal/Foreign.chs +1/−1
cbits/simd.h view
@@ -11,13 +11,7 @@ void avx2_cmpeq8( uint8_t byte,- uint64_t *target,- size_t target_length,- uint8_t *source);--void avx2_cmpeq8(- uint8_t byte,- uint64_t *target,+ uint8_t *target, size_t target_length, uint8_t *source);
cbits/simd_avx2.c view
@@ -33,7 +33,7 @@ void avx2_cmpeq8( uint8_t byte,- uint64_t *target,+ uint8_t *target, size_t target_length, uint8_t *source) { #if defined(AVX2_ENABLED)
hw-simd.cabal view
@@ -3,7 +3,7 @@ -- see: https://github.com/sol/hpack name: hw-simd-version: 0.1.0.3+version: 0.1.1.0 synopsis: SIMD library description: Please see the README on Github at <https://github.com/haskell-works/hw-simd#readme> category: Data, Bit, SIMD@@ -60,7 +60,7 @@ , hw-bits >= 0.7.0.2 && < 0.8 , hw-rankselect >= 0.12.0.2 && < 0.13 , hw-rankselect-base >= 0.3.2.0 && < 0.4- , hw-prim >= 0.6.2.0 && < 0.7+ , hw-prim >= 0.6.2.12 && < 0.7 , vector >= 0.12.0.1 && < 0.13 build-tools: c2hs@@ -84,11 +84,13 @@ , semigroups >= 0.8.4 && < 0.19 exposed-modules: HaskellWorks.Data.Simd.Capabilities+ HaskellWorks.Data.Simd.ChunkString HaskellWorks.Data.Simd.Comparison HaskellWorks.Data.Simd.Comparison.Avx2 HaskellWorks.Data.Simd.Comparison.Stock HaskellWorks.Data.Simd.Internal.Bits HaskellWorks.Data.Simd.Internal.Broadword+ HaskellWorks.Data.Simd.Internal.ChunkString HaskellWorks.Data.Simd.Internal.Foreign HaskellWorks.Data.Simd.Internal.Marshal HaskellWorks.Data.Simd.Logical@@ -112,7 +114,7 @@ , hw-bits >= 0.7.0.2 && < 0.8 , hw-rankselect >= 0.12.0.2 && < 0.13 , hw-rankselect-base >= 0.3.2.0 && < 0.4- , hw-prim >= 0.6.2.0 && < 0.7+ , hw-prim >= 0.6.2.12 && < 0.7 , vector >= 0.12.0.1 && < 0.13 , directory >= 1.2.2 && < 1.4 , lens@@ -160,7 +162,7 @@ , hw-bits >= 0.7.0.2 && < 0.8 , hw-rankselect >= 0.12.0.2 && < 0.13 , hw-rankselect-base >= 0.3.2.0 && < 0.4- , hw-prim >= 0.6.2.0 && < 0.7+ , hw-prim >= 0.6.2.12 && < 0.7 , vector >= 0.12.0.1 && < 0.13 , cassava >= 0.5.1.0 && < 0.6 , containers
+ src/HaskellWorks/Data/Simd/ChunkString.hs view
@@ -0,0 +1,14 @@+module HaskellWorks.Data.Simd.ChunkString+ ( ChunkString+ , ToChunkString(..)+ , hGetContents+ ) where++import HaskellWorks.Data.Simd.Internal.ChunkString++import qualified HaskellWorks.Data.ByteString as BS+import qualified System.IO as IO++hGetContents :: IO.Handle -> IO ChunkString+hGetContents = (ChunkString <$>) . BS.hGetContentsChunkedBy chunkSize+{-# INLINE hGetContents #-}
src/HaskellWorks/Data/Simd/Comparison/Avx2.hs view
@@ -1,26 +1,53 @@ {-# LANGUAGE CPP #-} {-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE TypeFamilies #-} module HaskellWorks.Data.Simd.Comparison.Avx2 where -import Data.Monoid ((<>))+import Control.Monad+import Data.Monoid ((<>)) import Data.Word +import qualified Data.ByteString as BS import qualified Data.Vector.Storable as DVS import qualified Foreign.ForeignPtr as F import qualified Foreign.Marshal.Unsafe as F import qualified Foreign.Ptr as F+import qualified HaskellWorks.Data.ByteString as BS import qualified HaskellWorks.Data.Simd.Internal.Foreign as F+import qualified HaskellWorks.Data.Vector.AsVector8 as V+import qualified HaskellWorks.Data.Vector.Storable as DVS {-# ANN module ("HLint: ignore Redundant do" :: String) #-} class CmpEqWord8s a where- cmpEqWord8s :: Word8 -> a -> a+ type Target a+ cmpEqWord8s :: Word8 -> a -> Target a instance CmpEqWord8s (DVS.Vector Word8) where- cmpEqWord8s w8 v = DVS.unsafeCast (cmpEqWord8s w8 (DVS.unsafeCast v :: DVS.Vector Word64))+ type Target (DVS.Vector Word8) = DVS.Vector Word8+ cmpEqWord8s w8 v = F.unsafeLocalState $ do+ tgtFptr <- F.mallocForeignPtrBytes bufLen+ F.withForeignPtr srcFptr $ \srcPtr -> do+ F.withForeignPtr tgtFptr $ \tgtPtr -> do+ _ <- F.avx2Cmpeq8 (fromIntegral w8) (F.castPtr tgtPtr) (fromIntegral w64sLen) (srcPtr `F.plusPtr` srcOffset)+ when (disalignment /= 0) $ do+ let ending = DVS.padded ((DVS.length v + 63) `div` 64) (DVS.drop alignment v)+ let (endFptr, _, _) = DVS.unsafeToForeignPtr ending+ F.withForeignPtr endFptr $ \endPtr -> do+ void $ F.avx2Cmpeq8 (fromIntegral w8) (tgtPtr `F.plusPtr` (w64sLen * 64)) (fromIntegral w64sLen) (F.castPtr endPtr) + return $ DVS.unsafeFromForeignPtr tgtFptr 0 tgtLen+ where (srcFptr, srcOffset, srcLen) = DVS.unsafeToForeignPtr v+ bufLen = (srcLen + 63) `div` 8+ tgtLen = (srcLen + 7) `div` 8+ w64sLen = srcLen `div` 64+ alignment = w64sLen * 64+ disalignment = srcLen - alignment+ {-# INLINE cmpEqWord8s #-}+ instance CmpEqWord8s (DVS.Vector Word64) where+ type Target (DVS.Vector Word64) = DVS.Vector Word64 cmpEqWord8s w8 v = case DVS.unsafeCast v :: DVS.Vector Word8 of u -> case DVS.unsafeToForeignPtr u of (srcFptr, srcOffset, srcLength) -> if disalignment == 0@@ -40,9 +67,21 @@ {-# INLINE cmpEqWord8s #-} instance CmpEqWord8s [DVS.Vector Word64] where+ type Target [DVS.Vector Word64] = [DVS.Vector Word64] cmpEqWord8s w8 vs = cmpEqWord8s w8 <$> vs {-# INLINE cmpEqWord8s #-} instance CmpEqWord8s [DVS.Vector Word8] where+ type Target [DVS.Vector Word8] = [DVS.Vector Word8] cmpEqWord8s w8 vs = cmpEqWord8s w8 <$> vs {-# INLINE cmpEqWord8s #-}++instance CmpEqWord8s [BS.ByteString] where+ type Target [BS.ByteString] = [BS.ByteString]+ cmpEqWord8s w8 vs = BS.toByteString . cmpEqWord8s w8 . V.asVector8 <$> vs+ {-# INLINE cmpEqWord8s #-}++-- instance CmpEqWord8s CS.ChunkString where+-- type Target CS.ChunkString = CS.ChunkString+-- cmpEqWord8s w8 = CS.toChunkString . cmpEqWord8s w8 . BS.toByteStrings+-- {-# INLINE cmpEqWord8s #-}
src/HaskellWorks/Data/Simd/Comparison/Stock.hs view
@@ -10,7 +10,11 @@ import HaskellWorks.Data.Simd.Internal.Bits import HaskellWorks.Data.Simd.Internal.Broadword -import qualified Data.Vector.Storable as DVS+import qualified Data.ByteString as BS+import qualified Data.Vector.Storable as DVS+import qualified HaskellWorks.Data.ByteString as BS+import qualified HaskellWorks.Data.Simd.ChunkString as CS+import qualified HaskellWorks.Data.Vector.AsVector8 as V class CmpEqWord8s a where cmpEqWord8s :: Word8 -> a -> a@@ -70,3 +74,10 @@ cmpEqWord8s w8 vs = cmpEqWord8s w8 <$> vs {-# INLINE cmpEqWord8s #-} +instance CmpEqWord8s [BS.ByteString] where+ cmpEqWord8s w8 vs = BS.toByteString . cmpEqWord8s w8 . V.asVector8 <$> vs+ {-# INLINE cmpEqWord8s #-}++instance CmpEqWord8s CS.ChunkString where+ cmpEqWord8s w8 = CS.toChunkString . cmpEqWord8s w8 . BS.toByteStrings+ {-# INLINE cmpEqWord8s #-}
+ src/HaskellWorks/Data/Simd/Internal/ChunkString.hs view
@@ -0,0 +1,102 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE FlexibleInstances #-}++module HaskellWorks.Data.Simd.Internal.ChunkString where++import Data.Word+import HaskellWorks.Data.AtIndex+import HaskellWorks.Data.Bits.BitWise+import HaskellWorks.Data.ByteString+import HaskellWorks.Data.ByteString.Lazy++import qualified Data.ByteString as BS+import qualified Data.ByteString.Lazy as LBS+import qualified Data.Vector.Storable as DVS+import qualified HaskellWorks.Data.ByteString as BS++newtype ChunkString = ChunkString+ { chunks :: [BS.ByteString]+ } deriving (Eq, Show)++instance ToLazyByteString ChunkString where+ toLazyByteString (ChunkString cs) = LBS.fromChunks cs++instance ToByteStrings ChunkString where+ toByteStrings (ChunkString bss) = bss++class ToChunkString a where+ toChunkString :: a -> ChunkString++instance ToChunkString LBS.ByteString where+ toChunkString = toChunkString . LBS.toChunks++instance ToChunkString [BS.ByteString] where+ toChunkString = ChunkString . BS.rechunk chunkSize++instance ToChunkString [DVS.Vector Word8] where+ toChunkString = toChunkString . (toByteString <$>)++instance ToChunkString [DVS.Vector Word16] where+ toChunkString = toChunkString . (toByteString <$>)++instance ToChunkString [DVS.Vector Word32] where+ toChunkString = toChunkString . (toByteString <$>)++instance ToChunkString [DVS.Vector Word64] where+ toChunkString = toChunkString . (toByteString <$>)++instance ToChunkString (DVS.Vector Word8) where+ toChunkString v = toChunkString [toByteString v]++instance ToChunkString (DVS.Vector Word16) where+ toChunkString v = toChunkString [toByteString v]++instance ToChunkString (DVS.Vector Word32) where+ toChunkString v = toChunkString [toByteString v]++instance ToChunkString (DVS.Vector Word64) where+ toChunkString v = toChunkString [toByteString v]++#if 0+instance BitWise ChunkString where+ ChunkString (a:as) .&. ChunkString (b:bs) = ChunkString (c:cs)+ where len = end a `min` end b+ c = toByteString $ DVS.constructN (fromIntegral len) go+ ChunkString cs = ChunkString as .&. ChunkString bs+ go u = let ui = end u in (a !!! ui) .&. (b !!! ui)+ ChunkString _ .&. ChunkString _ = ChunkString []+ {-# INLINE (.&.) #-}++ ChunkString (a:as) .|. ChunkString (b:bs) = ChunkString (c:cs)+ where len = end a `min` end b+ c = toByteString $ DVS.constructN (fromIntegral len) go+ ChunkString cs = ChunkString as .|. ChunkString bs+ go u = let ui = end u in (a !!! ui) .&. (b !!! ui)+ ChunkString _ .|. ChunkString _ = ChunkString []+ {-# INLINE (.|.) #-}++ ChunkString (a:as) .^. ChunkString (b:bs) = ChunkString (c:cs)+ where len = end a `min` end b+ c = toByteString $ DVS.constructN (fromIntegral len) go+ ChunkString cs = ChunkString as .^. ChunkString bs+ go u = let ui = end u in (a !!! ui) .&. (b !!! ui)+ ChunkString _ .^. ChunkString _ = ChunkString []+ {-# INLINE (.^.) #-}++ comp (ChunkString (a:as)) = ChunkString (c:cs)+ where c = toByteString $ DVS.constructN (fromIntegral (end a)) go+ ChunkString cs = comp (ChunkString as)+ go u = let ui = end u in comp (a !!! ui)+ comp (ChunkString _) = ChunkString []+ {-# INLINE comp #-}++ all0s = ChunkString $ repeat $ toByteString $ DVS.replicate chunkSize (0x00 :: Word8)+ {-# INLINE all0s #-}++ all1s = ChunkString $ repeat $ toByteString $ DVS.replicate chunkSize (0xff :: Word8)+ {-# INLINE all1s #-}+#endif++chunkSize :: Int+chunkSize = 32 * 1024 - 64+{-# INLINE chunkSize #-}
src/HaskellWorks/Data/Simd/Internal/Foreign.chs view
@@ -16,7 +16,7 @@ {#call unsafe avx2_memcpy as c_build_ibs#} target source len {-# INLINE avx2Memcpy #-} -avx2Cmpeq8 :: UInt8 -> Ptr UInt64 -> Size -> Ptr UInt8 -> IO ()+avx2Cmpeq8 :: UInt8 -> Ptr UInt8 -> Size -> Ptr UInt8 -> IO () avx2Cmpeq8 byte target targetLength source = requireAvx2 $ do {#call unsafe avx2_cmpeq8 as c_cmpeq8#} byte target targetLength source {-# INLINE avx2Cmpeq8 #-}