hw-simd 0.1.1.2 → 0.1.1.3
raw patch · 6 files changed
+91/−4 lines, 6 filesPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
API changes (from Hackage documentation)
+ HaskellWorks.Data.Simd.Comparison.Avx2: class CmpEqWord8sPara a where {
+ HaskellWorks.Data.Simd.Comparison.Avx2: cmpEqWord8sPara :: CmpEqWord8sPara a => Vector Word8 -> a -> CmpEqWord8sParaTarget a
+ HaskellWorks.Data.Simd.Comparison.Avx2: instance HaskellWorks.Data.Simd.Comparison.Avx2.CmpEqWord8sPara (Data.Vector.Storable.Vector GHC.Word.Word64)
+ HaskellWorks.Data.Simd.Internal.Foreign: avx2Cmpeq8Para :: Ptr UInt8 -> Size -> Ptr (Ptr UInt8) -> Size -> Ptr UInt8 -> IO ()
+ HaskellWorks.Data.Simd.Internal.Foreign: c_cmpeq8_para :: Ptr CUChar -> CULong -> Ptr (Ptr CUChar) -> CULong -> Ptr CUChar -> IO ()
- HaskellWorks.Data.Simd.Comparison.Avx2: type family Target a;
+ HaskellWorks.Data.Simd.Comparison.Avx2: type family CmpEqWord8sParaTarget a;
- HaskellWorks.Data.Simd.Internal.Foreign: c_avx2_and_bits :: ((Ptr CUChar) -> (CULong -> ((Ptr CUChar) -> ((Ptr CUChar) -> (IO ())))))
+ HaskellWorks.Data.Simd.Internal.Foreign: c_avx2_and_bits :: Ptr CUChar -> CULong -> Ptr CUChar -> Ptr CUChar -> IO ()
- HaskellWorks.Data.Simd.Internal.Foreign: c_avx2_and_not_bits :: ((Ptr CUChar) -> (CULong -> ((Ptr CUChar) -> ((Ptr CUChar) -> (IO ())))))
+ HaskellWorks.Data.Simd.Internal.Foreign: c_avx2_and_not_bits :: Ptr CUChar -> CULong -> Ptr CUChar -> Ptr CUChar -> IO ()
- HaskellWorks.Data.Simd.Internal.Foreign: c_avx2_not_bits :: ((Ptr CUChar) -> (CULong -> ((Ptr CUChar) -> (IO ()))))
+ HaskellWorks.Data.Simd.Internal.Foreign: c_avx2_not_bits :: Ptr CUChar -> CULong -> Ptr CUChar -> IO ()
- HaskellWorks.Data.Simd.Internal.Foreign: c_avx2_or_bits :: ((Ptr CUChar) -> (CULong -> ((Ptr CUChar) -> ((Ptr CUChar) -> (IO ())))))
+ HaskellWorks.Data.Simd.Internal.Foreign: c_avx2_or_bits :: Ptr CUChar -> CULong -> Ptr CUChar -> Ptr CUChar -> IO ()
- HaskellWorks.Data.Simd.Internal.Foreign: c_avx2_xor_bits :: ((Ptr CUChar) -> (CULong -> ((Ptr CUChar) -> ((Ptr CUChar) -> (IO ())))))
+ HaskellWorks.Data.Simd.Internal.Foreign: c_avx2_xor_bits :: Ptr CUChar -> CULong -> Ptr CUChar -> Ptr CUChar -> IO ()
- HaskellWorks.Data.Simd.Internal.Foreign: c_build_ibs :: ((Ptr CUChar) -> ((Ptr CUChar) -> (CULong -> (IO ()))))
+ HaskellWorks.Data.Simd.Internal.Foreign: c_build_ibs :: Ptr CUChar -> Ptr CUChar -> CULong -> IO ()
- HaskellWorks.Data.Simd.Internal.Foreign: c_cmpeq8 :: (CUChar -> ((Ptr CUChar) -> (CULong -> ((Ptr CUChar) -> (IO ())))))
+ HaskellWorks.Data.Simd.Internal.Foreign: c_cmpeq8 :: CUChar -> Ptr CUChar -> CULong -> Ptr CUChar -> IO ()
Files
- cbits/simd.h +7/−0
- cbits/simd_avx2.c +27/−0
- hw-simd.cabal +1/−1
- src/HaskellWorks/Data/Simd/Comparison/Avx2.hs +33/−3
- src/HaskellWorks/Data/Simd/Internal/Foreign.chs +5/−0
- test/HaskellWorks/Data/Simd/ComparisonSpec.hs +18/−0
cbits/simd.h view
@@ -15,6 +15,13 @@ size_t target_length, uint8_t *source); +void avx2_cmpeq8_para(+ uint8_t *bytes,+ size_t bytes_length,+ uint8_t **targets,+ size_t targets_length,+ uint8_t *source);+ void avx2_and_bits( uint8_t *target, size_t target_length,
cbits/simd_avx2.c view
@@ -54,6 +54,33 @@ #endif } +void avx2_cmpeq8_para(+ uint8_t *bytes,+ size_t bytes_length,+ uint8_t **targets,+ size_t targets_length,+ uint8_t *source) {+#if defined(AVX2_ENABLED)+ size_t i;++ for (i = 0; i < targets_length * 2; ++i) {+ size_t j;++ __m256i v_data_a = *(__m256i *)(source + (i * 32));++ for (j = 0; j < bytes_length; ++j) {+ uint8_t *target = targets[j];+ uint32_t *target32 = (uint32_t *)target;+ __m256i v_comparand = _mm256_set1_epi8(bytes[j]);+ uint32_t *out_mask = (uint32_t*)target;+ __m256i v_results_a = _mm256_cmpeq_epi8(v_data_a, v_comparand);+ uint32_t mask = (uint32_t)_mm256_movemask_epi8(v_results_a);+ target32[i] = mask;+ }+ }+#endif+}+ void avx2_and_bits( uint8_t *target, size_t target_length,
hw-simd.cabal view
@@ -3,7 +3,7 @@ -- see: https://github.com/sol/hpack name: hw-simd-version: 0.1.1.2+version: 0.1.1.3 synopsis: SIMD library description: Please see the README on Github at <https://github.com/haskell-works/hw-simd#readme> category: Data, Bit, SIMD
src/HaskellWorks/Data/Simd/Comparison/Avx2.hs view
@@ -1,6 +1,7 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeFamilies #-} module HaskellWorks.Data.Simd.Comparison.Avx2 where @@ -9,6 +10,7 @@ import Data.Word import qualified Data.ByteString as BS+import qualified Data.Vector as DV import qualified Data.Vector.Storable as DVS import qualified Foreign.ForeignPtr as F import qualified Foreign.Marshal.Unsafe as F@@ -87,4 +89,32 @@ cmpEqWord8s w8 = CS.toChunkString . cmpEqWord8s w8 . BS.toByteStrings {-# INLINE cmpEqWord8s #-} +class CmpEqWord8sPara a where+ type CmpEqWord8sParaTarget a+ cmpEqWord8sPara :: DVS.Vector Word8 -> a -> CmpEqWord8sParaTarget a++instance CmpEqWord8sPara (DVS.Vector Word64) where+ type CmpEqWord8sParaTarget (DVS.Vector Word64) = DV.Vector (DVS.Vector Word64)+ cmpEqWord8sPara w8s v = case DVS.unsafeCast v :: DVS.Vector Word8 of+ u -> case DVS.unsafeToForeignPtr u of+ (srcFptr, srcOffset, srcLength) -> if disalignment == 0+ then F.unsafeLocalState $ do+ tgtFptr <- F.mallocForeignPtrBytes (srcLength * DVS.length w8s)+ F.withForeignPtr srcFptr $ \srcPtr -> do+ F.withForeignPtr tgtFptr $ \tgtPtr -> do+ let tgtsPtrsV :: DVS.Vector (F.Ptr Word8) = DVS.constructN (DVS.length w8s) $ \t ->+ tgtPtr `F.plusPtr` (DVS.length t * DVS.length v)+ let (w8sFptr, _, w8sLen) = DVS.unsafeToForeignPtr w8s+ let (tgtsPtrsFptr, _, _) = DVS.unsafeToForeignPtr tgtsPtrsV+ F.withForeignPtr w8sFptr $ \w8sPtr -> do+ F.withForeignPtr tgtsPtrsFptr $ \tgtsPtrsPtr -> do+ F.avx2Cmpeq8Para (F.castPtr w8sPtr) (fromIntegral w8sLen) (F.castPtr tgtsPtrsPtr) (fromIntegral w64sLen) (srcPtr `F.plusPtr` srcOffset)++ let tgtV = DVS.unsafeFromForeignPtr tgtFptr 0 (w64sLen * DVS.length w8s)+ return $ DV.constructN (DVS.length w8s) $ \t -> DVS.take w64sLen (DVS.drop (DV.length t * w64sLen) tgtV)++ else error $ "Unaligned byte string: " <> show disalignment+ where w64sLen = srcLength `div` 64+ disalignment = srcLength - w64sLen * 64+ {-# INLINE cmpEqWord8sPara #-}
src/HaskellWorks/Data/Simd/Internal/Foreign.chs view
@@ -21,6 +21,11 @@ {#call unsafe avx2_cmpeq8 as c_cmpeq8#} byte target targetLength source {-# INLINE avx2Cmpeq8 #-} +avx2Cmpeq8Para :: Ptr UInt8 -> Size -> Ptr (Ptr UInt8) -> Size -> Ptr UInt8 -> IO ()+avx2Cmpeq8Para bytes bytes_length target targetLength source = requireAvx2 $ do+ {#call unsafe avx2_cmpeq8_para as c_cmpeq8_para#} bytes bytes_length target targetLength source+{-# INLINE avx2Cmpeq8Para #-}+ avx2AndBits :: Ptr UInt8 -> Size -> Ptr UInt8 -> Ptr UInt8 -> IO () avx2AndBits target targetLength source_a source_b = requireAvx2 $ do {#call unsafe avx2_and_bits as c_avx2_and_bits#} target targetLength source_a source_b
test/HaskellWorks/Data/Simd/ComparisonSpec.hs view
@@ -11,6 +11,7 @@ import Hedgehog import Test.Hspec +import qualified Data.Vector as DV import qualified Data.Vector.Storable as DVS import qualified HaskellWorks.Data.Simd.Comparison.Avx2 as AVX import qualified HaskellWorks.Data.Simd.Comparison.Stock as STK@@ -35,3 +36,20 @@ $ G.word8x8 (G.choice [pure w, G.word8 R.constantBounded]) AVX.cmpEqWord8s w vs === STK.cmpEqWord8s w vs vs === vs+ it "AVX2 Para 1" $ requireProperty $ do+ w <- forAll $ G.word8 R.constantBounded+ vs :: DVS.Vector Word64 <- forAll+ $ G.storableVector (R.singleton 8)+ $ G.word8x8 (G.choice [pure w, G.word8 R.constantBounded])+ DV.head (AVX.cmpEqWord8sPara (DVS.singleton w) vs) === AVX.cmpEqWord8s w vs+ it "AVX2 Para 2" $ requireProperty $ do+ len <- forAll $ (* 8) <$> G.int (R.linear 0 8)+ w0 <- forAll $ G.word8 R.constantBounded+ w1 <- forAll $ G.word8 R.constantBounded+ vs :: DVS.Vector Word64 <- forAll+ $ G.storableVector (R.singleton len)+ $ G.word8x8 (G.choice [pure w0, pure w1, G.word8 R.constantBounded])+ let actual = AVX.cmpEqWord8sPara (DVS.fromList [w0, w1]) vs+ (actual DV.! 0) === AVX.cmpEqWord8s w0 vs+ (actual DV.! 1) === AVX.cmpEqWord8s w1 vs+