diff --git a/bench/Bench.hs b/bench/Bench.hs index b48b5b0..e2fd89e 100644 --- a/bench/Bench.hs +++ b/bench/Bench.hs @@ -4,6 +4,7 @@ import Test.Tasty.Bench import Test.Tasty.Patterns.Printer import Bench.BitIndex +import Bench.Common import Bench.GCD import Bench.Intersection import Bench.Invert @@ -18,27 +19,24 @@ import Bench.Union main :: IO () main = defaultMain $ map (mapLeafBenchmarks addCompare) - [ bgroup "bitIndex" $ map benchBitIndex [5..14] - , bgroup "invert" $ map benchInvert [5..14] + [ bgroup "add" $ map benchAdd [5..14] + , bgroup "bitIndex" $ map benchBitIndex [5..14] + , bgroup "flip" $ map benchRandomFlip [5..14] , bgroup "gcdExt" $ map benchGCD [5..14] , bgroup "intersection" $ map benchIntersection [5..14] + , bgroup "invert" $ map benchInvert [5..14] , bgroup "product" $ map benchProduct [5..14] , bgroup "productShort" $ map benchProductShort [5..14] - , bgroup "square" $ map benchSquare [5..14] - , bgroup "write" $ map benchRandomWrite [5..14] - , bgroup "flip" $ map benchRandomFlip [5..14] , bgroup "read" $ map benchRandomRead [5..14] - , bgroup "remainder" $ map benchRemainder [5..14] + , bgroup "remainder" $ map benchRemainder [5..11] , bgroup "reverse" $ map benchReverse [5..14] - , bgroup "add" $ map benchAdd [5..14] + , bgroup "square" $ map benchSquare [5..14] , bgroup "sum" $ map benchSum [5..14] , bgroup "union" $ map benchUnion [5..14] + , bgroup "write" $ map benchRandomWrite [5..14] ] -bitBenchName :: String -bitBenchName = "Bit" - addCompare :: ([String] -> Benchmark -> Benchmark) addCompare (name : path) - | name /= bitBenchName = bcompare (printAwkExpr (locateBenchmark (bitBenchName : path))) + | name /= labelBit = bcompare (printAwkExpr (locateBenchmark (labelBit : path))) addCompare _ = id diff --git a/bench/Bench/BitIndex.hs b/bench/Bench/BitIndex.hs index f652952..3893707 100644 --- a/bench/Bench/BitIndex.hs +++ b/bench/Bench/BitIndex.hs @@ -9,23 +9,16 @@ import qualified Data.Vector.Unboxed as U import qualified Data.Vector.Unboxed.Mutable as MU import Test.Tasty.Bench -randomVec :: MU.Unbox a => (Bool -> a) -> Int -> U.Vector a -randomVec f k = U.generate n (\i -> f (i == n - 1)) +import Bench.Common + +allFalseButLast :: MU.Unbox a => (Bool -> a) -> Int -> U.Vector a +allFalseButLast f k = U.generate n (\i -> f (i == n - 1)) where n = 1 `shiftL` k benchBitIndex :: Int -> Benchmark benchBitIndex k = bgroup (show (1 `shiftL` k :: Int)) - [ bench "Bit" $ nf bitIndexBit (randomVec Bit k) - , bench "BitTS" $ nf bitIndexBitTS (randomVec TS.Bit k) - , bench "Vector" $ nf elemIndexVector (randomVec id k) + [ bench labelBit $ nf (bitIndex (Bit True)) (allFalseButLast Bit k) + , bench labelBitTS $ nf (TS.bitIndex (TS.Bit True)) (allFalseButLast TS.Bit k) + , bench labelVector $ nf (U.elemIndex True) (allFalseButLast id k) ] - -bitIndexBit :: U.Vector Bit -> Maybe Int -bitIndexBit = bitIndex (Bit True) - -bitIndexBitTS :: U.Vector TS.Bit -> Maybe Int -bitIndexBitTS = TS.bitIndex (TS.Bit True) - -elemIndexVector :: U.Vector Bool -> Maybe Int -elemIndexVector = U.elemIndex True diff --git a/bench/Bench/Common.hs b/bench/Bench/Common.hs new file mode 100644 index 0000000..43ca1f4 --- /dev/null +++ b/bench/Bench/Common.hs @@ -0,0 +1,95 @@ +module Bench.Common + ( labelBit + , labelBitTS + , labelVector + , labelIntSet + , labelInteger + , randomBools + , randomBools2 + , randomVec + , randomVec2 + , randomSet + , randomSet2 + , randomInteger + , randomInteger2 + , randomIndices + , randomIndicesAndBools + ) where + +import Data.Bit +import Data.Bits +import qualified Data.IntSet as IS +import qualified Data.Vector.Unboxed as U +import qualified Data.Vector.Unboxed.Mutable as MU +import System.Random + +labelBit :: String +labelBit = "Vector Bit" + +labelBitTS :: String +labelBitTS = "Vector TS.Bit" + +labelVector :: String +labelVector = "Vector Bool" + +labelIntSet :: String +labelIntSet = "IntSet" + +labelInteger :: String +labelInteger = "Integer" + +seed1 :: Int +seed1 = 42 + +seed2 :: Int +seed2 = 123 + +mkRandomBools :: Int -> [Bool] +mkRandomBools seed = map (> (0 :: Int)) $ randoms $ mkStdGen seed + +randomBools :: [Bool] +randomBools = mkRandomBools seed1 + +randomBools2 :: [Bool] +randomBools2 = mkRandomBools seed2 + +mkRandomVec :: MU.Unbox a => Int -> (Bool -> a) -> Int -> U.Vector a +mkRandomVec seed f k = U.fromList $ map f $ take n $ mkRandomBools seed + where + n = 1 `shiftL` k + +randomVec :: MU.Unbox a => (Bool -> a) -> Int -> U.Vector a +randomVec = mkRandomVec seed1 + +randomVec2 :: MU.Unbox a => (Bool -> a) -> Int -> U.Vector a +randomVec2 = mkRandomVec seed2 + +mkRandomSet :: Int -> Int -> IS.IntSet +mkRandomSet seed k = IS.fromAscList (map fst (filter snd (zip [0..] (take n (mkRandomBools seed))))) + where + n = 1 `shiftL` k + +randomSet :: Int -> IS.IntSet +randomSet = mkRandomSet seed1 + +randomSet2 :: Int -> IS.IntSet +randomSet2 = mkRandomSet seed2 + +mkRandomInteger :: Int -> Int -> Integer +mkRandomInteger seed k = toInteger $ toF2Poly $ mkRandomVec seed Bit k + +randomInteger :: Int -> Integer +randomInteger = mkRandomInteger seed1 + +randomInteger2 :: Int -> Integer +randomInteger2 = mkRandomInteger seed2 + +randomIndices :: [Int] +randomIndices = map fst randomIndicesAndBools + +randomIndicesAndBools :: [(Int, Bool)] +randomIndicesAndBools + = map (\x -> if x > 0 then (x, True) else (x .&. maxBound, False)) + . randoms + . mkStdGen + $ 42 diff --git a/bench/Bench/GCD.hs b/bench/Bench/GCD.hs index 6fc7937..2a8c22b 100644 --- a/bench/Bench/GCD.hs +++ b/bench/Bench/GCD.hs @@ -5,26 +5,12 @@ module Bench.GCD import Data.Bit import qualified Data.Bit.ThreadSafe as TS import Data.Bits -import qualified Data.Vector.Unboxed as U -import qualified Data.Vector.Unboxed.Mutable as MU -import System.Random import Test.Tasty.Bench -randomBools :: [Bool] -randomBools = map (> (0 :: Int)) $ randoms $ mkStdGen 42 - -randomVec :: MU.Unbox a => (Bool -> a) -> Int -> U.Vector a -randomVec f k = U.fromList $ map f $ take n randomBools - where - n = 1 `shiftL` k - -randomVec' :: MU.Unbox a => (Bool -> a) -> Int -> U.Vector a -randomVec' f k = U.fromList $ map f $ take n $ drop n randomBools - where - n = 1 `shiftL` k +import Bench.Common benchGCD :: Int -> Benchmark benchGCD k = bgroup (show (1 `shiftL` k :: Int)) - [ bench "Bit" $ nf (uncurry gcdExt) ( toF2Poly $ randomVec Bit k, toF2Poly $ randomVec' Bit k) - , bench "BitTS" $ nf (uncurry TS.gcdExt) (TS.toF2Poly $ randomVec TS.Bit k, TS.toF2Poly $ randomVec' TS.Bit k) + [ bench labelBit $ nf (uncurry gcdExt) ( toF2Poly $ randomVec Bit k, toF2Poly $ randomVec2 Bit k) + , bench labelBitTS $ nf (uncurry TS.gcdExt) (TS.toF2Poly $ randomVec TS.Bit k, TS.toF2Poly $ randomVec2 TS.Bit k) ] diff --git a/bench/Bench/Intersection.hs b/bench/Bench/Intersection.hs index cdf3545..002084f 100644 --- a/bench/Bench/Intersection.hs +++ b/bench/Bench/Intersection.hs @@ -1,3 +1,6 @@ +{-# OPTIONS_GHC -Wno-unrecognised-pragmas #-} +{-# HLINT ignore "Avoid lambda" #-} + module Bench.Intersection ( benchIntersection ) where @@ -7,53 +10,14 @@ import qualified Data.Bit.ThreadSafe as TS import Data.Bits import qualified Data.IntSet as IS import qualified Data.Vector.Unboxed as U -import qualified Data.Vector.Unboxed.Mutable as MU -import System.Random import Test.Tasty.Bench -randomBools :: [Bool] -randomBools - = map (> (0 :: Int)) - . randoms - . mkStdGen - $ 42 - -randomVec :: MU.Unbox a => (Bool -> a) -> Int -> U.Vector a -randomVec f k = U.fromList (map f (take n randomBools)) - where - n = 1 `shiftL` k - -randomVec2 :: MU.Unbox a => (Bool -> a) -> Int -> U.Vector a -randomVec2 f k = U.fromList (map f (take n $ drop n randomBools)) - where - n = 1 `shiftL` k - -randomSet :: Int -> IS.IntSet -randomSet k = IS.fromAscList (map fst (filter snd (zip [0..] (take n randomBools)))) - where - n = 1 `shiftL` k - -randomSet2 :: Int -> IS.IntSet -randomSet2 k = IS.fromAscList (map fst (filter snd (zip [0..] (take n $ drop n randomBools)))) - where - n = 1 `shiftL` k +import Bench.Common benchIntersection :: Int -> Benchmark benchIntersection k = bgroup (show (1 `shiftL` k :: Int)) - [ bench "Bit" $ nf (\x -> intersectionBit (randomVec Bit k) x) (randomVec2 Bit k) - , bench "BitTS" $ nf (\x -> intersectionBitTS (randomVec TS.Bit k) x) (randomVec2 TS.Bit k) - , bench "Vector" $ nf (\x -> intersectionVector (randomVec id k) x) (randomVec2 id k) - , bench "IntSet" $ nf (intersectionIntSet (randomSet k)) (randomSet2 k) + [ bench labelBit $ nf (\x -> zipBits (.&.) (randomVec Bit k) x) (randomVec2 Bit k) + , bench labelBitTS $ nf (\x -> TS.zipBits (.&.) (randomVec TS.Bit k) x) (randomVec2 TS.Bit k) + , bench labelVector $ nf (\x -> U.zipWith (&&) (randomVec id k) x) (randomVec2 id k) + , bench labelIntSet $ nf (IS.union (randomSet k)) (randomSet2 k) ] - -intersectionBit :: U.Vector Bit -> U.Vector Bit -> U.Vector Bit -intersectionBit = zipBits (.&.) - -intersectionBitTS :: U.Vector TS.Bit -> U.Vector TS.Bit -> U.Vector TS.Bit -intersectionBitTS = TS.zipBits (.&.) - -intersectionVector :: U.Vector Bool -> U.Vector Bool -> U.Vector Bool -intersectionVector = U.zipWith (&&) - -intersectionIntSet :: IS.IntSet -> IS.IntSet -> IS.IntSet -intersectionIntSet = IS.union diff --git a/bench/Bench/Invert.hs b/bench/Bench/Invert.hs index 5b6a1e6..e9d5064 100644 --- a/bench/Bench/Invert.hs +++ b/bench/Bench/Invert.hs @@ -6,34 +6,13 @@ import Data.Bit import qualified Data.Bit.ThreadSafe as TS import Data.Bits import qualified Data.Vector.Unboxed as U -import qualified Data.Vector.Unboxed.Mutable as MU -import System.Random import Test.Tasty.Bench -randomBools :: [Bool] -randomBools - = map (> (0 :: Int)) - . randoms - . mkStdGen - $ 42 - -randomVec :: MU.Unbox a => (Bool -> a) -> Int -> U.Vector a -randomVec f k = U.fromList (map f (take n randomBools)) - where - n = 1 `shiftL` k +import Bench.Common benchInvert :: Int -> Benchmark benchInvert k = bgroup (show (1 `shiftL` k :: Int)) - [ bench "Bit" $ nf invertBit (randomVec Bit k) - , bench "BitTS" $ nf invertBitTS (randomVec TS.Bit k) - , bench "Vector" $ nf invertVector (randomVec id k) + [ bench labelBit $ nf invertBits (randomVec Bit k) + , bench labelBitTS $ nf TS.invertBits (randomVec TS.Bit k) + , bench labelVector $ nf (U.map not) (randomVec id k) ] - -invertBit :: U.Vector Bit -> U.Vector Bit -invertBit = invertBits - -invertBitTS :: U.Vector TS.Bit -> U.Vector TS.Bit -invertBitTS = TS.invertBits - -invertVector :: U.Vector Bool -> U.Vector Bool -invertVector = U.map not diff --git a/bench/Bench/Product.hs b/bench/Bench/Product.hs index d119f20..8ed3cc9 100644 --- a/bench/Bench/Product.hs +++ b/bench/Bench/Product.hs @@ -1,3 +1,6 @@ +{-# OPTIONS_GHC -Wno-unrecognised-pragmas #-} +{-# HLINT ignore "Avoid lambda" #-} + module Bench.Product ( benchProduct , benchProductShort @@ -8,52 +11,29 @@ import Data.Bit import qualified Data.Bit.ThreadSafe as TS import Data.Bits import qualified Data.Vector.Unboxed as U -import qualified Data.Vector.Unboxed.Mutable as MU -import System.Random import Test.Tasty.Bench -randomBools :: [Bool] -randomBools - = map (> (0 :: Int)) - . randoms - . mkStdGen - $ 42 - -randomVec :: MU.Unbox a => (Bool -> a) -> Int -> U.Vector a -randomVec f k = U.fromList (map f (take n randomBools)) - where - n = 1 `shiftL` k - -randomVec2 :: MU.Unbox a => (Bool -> a) -> Int -> U.Vector a -randomVec2 f k = U.fromList (map f (take n $ drop n randomBools)) - where - n = 1 `shiftL` k - -randomInteger :: Int -> Integer -randomInteger k = toInteger $ toF2Poly $ randomVec Bit k - -randomInteger2 :: Int -> Integer -randomInteger2 k = toInteger $ toF2Poly $ randomVec2 Bit k +import Bench.Common benchProduct :: Int -> Benchmark benchProduct k = bgroup (show (1 `shiftL` k :: Int)) - [ bench "Bit" $ nf (\x -> (*) (toF2Poly $ randomVec Bit k) x) (toF2Poly $ randomVec2 Bit k) - , bench "BitTS" $ nf (\x -> (*) (TS.toF2Poly $ randomVec TS.Bit k) x) (TS.toF2Poly $ randomVec2 TS.Bit k) - , bench "Integer" $ nf (\x -> binMul (randomInteger k) x) (randomInteger2 k) + [ bench labelBit $ nf (\x -> (*) (toF2Poly $ randomVec Bit k) x) (toF2Poly $ randomVec2 Bit k) + , bench labelBitTS $ nf (\x -> (*) (TS.toF2Poly $ randomVec TS.Bit k) x) (TS.toF2Poly $ randomVec2 TS.Bit k) + , bench labelInteger $ nf (\x -> binMul (randomInteger k) x) (randomInteger2 k) ] benchProductShort :: Int -> Benchmark benchProductShort k = bgroup (show (1 `shiftL` k :: Int)) - [ bench "Bit" $ nf (\x -> (*) (toF2Poly $ randomVec Bit k) x) (toF2Poly $ U.take 32 $ randomVec2 Bit k) - , bench "BitTS" $ nf (\x -> (*) (TS.toF2Poly $ randomVec TS.Bit k) x) (TS.toF2Poly $ U.take 32 $ randomVec2 TS.Bit k) - , bench "Integer" $ nf (\x -> binMul (randomInteger k) x) ((1 `shiftL` 32 - 1) .&. randomInteger2 k) + [ bench labelBit $ nf (\x -> (*) (toF2Poly $ randomVec Bit k) x) (toF2Poly $ U.take 32 $ randomVec2 Bit k) + , bench labelBitTS $ nf (\x -> (*) (TS.toF2Poly $ randomVec TS.Bit k) x) (TS.toF2Poly $ U.take 32 $ randomVec2 TS.Bit k) + , bench labelInteger $ nf (\x -> binMul (randomInteger k) x) ((1 `shiftL` 32 - 1) .&. randomInteger2 k) ] benchSquare :: Int -> Benchmark benchSquare k = bgroup (show (1 `shiftL` k :: Int)) - [ bench "Bit" $ nf (\x -> (*) (toF2Poly $ randomVec Bit k) x) (toF2Poly $ randomVec Bit k) - , bench "BitTS" $ nf (\x -> (*) (TS.toF2Poly $ randomVec TS.Bit k) x) (TS.toF2Poly $ randomVec TS.Bit k) - , bench "Integer" $ nf (\x -> binMul (randomInteger k) x) (randomInteger k) + [ bench labelBit $ nf (\x -> (*) (toF2Poly $ randomVec Bit k) x) (toF2Poly $ randomVec Bit k) + , bench labelBitTS $ nf (\x -> (*) (TS.toF2Poly $ randomVec TS.Bit k) x) (TS.toF2Poly $ randomVec TS.Bit k) + , bench labelInteger $ nf (\x -> binMul (randomInteger k) x) (randomInteger k) ] binMul :: Integer -> Integer -> Integer diff --git a/bench/Bench/RandomFlip.hs b/bench/Bench/RandomFlip.hs index bdf62af..97fe68a 100644 --- a/bench/Bench/RandomFlip.hs +++ b/bench/Bench/RandomFlip.hs @@ -10,29 +10,23 @@ import Data.Bits import Data.Foldable import qualified Data.IntSet as IS import qualified Data.Vector.Unboxed.Mutable as MU -import System.Random import Test.Tasty.Bench -randomFlips :: [Int] -randomFlips - = map abs - . randoms - . mkStdGen - $ 42 +import Bench.Common benchRandomFlip :: Int -> Benchmark benchRandomFlip k = bgroup (show (1 `shiftL` k :: Int)) - [ bench "Bit" $ nf randomFlipBit k - , bench "BitTS" $ nf randomFlipBitTS k - , bench "Vector" $ nf randomFlipVector k - , bench "IntSet" $ nf randomFlipIntSet k + [ bench labelBit $ nf randomFlipBit k + , bench labelBitTS $ nf randomFlipBitTS k + , bench labelVector $ nf randomFlipVector k + , bench labelIntSet $ nf randomFlipIntSet k ] randomFlipBit :: Int -> Int randomFlipBit k = runST $ do let n = 1 `shiftL` k vec <- MU.new n - forM_ (take (mult * n) randomFlips) $ + forM_ (take (mult * n) randomIndices) $ \i -> unsafeFlipBit vec (i .&. (1 `shiftL` k - 1)) Bit i <- MU.unsafeRead vec 0 pure $ if i then 1 else 0 @@ -41,7 +35,7 @@ randomFlipBitTS :: Int -> Int randomFlipBitTS k = runST $ do let n = 1 `shiftL` k vec <- MU.new n - forM_ (take (mult * n) randomFlips) $ + forM_ (take (mult * n) randomIndices) $ \i -> TS.unsafeFlipBit vec (i .&. (1 `shiftL` k - 1)) TS.Bit i <- MU.unsafeRead vec 0 pure $ if i then 1 else 0 @@ -50,7 +44,7 @@ randomFlipVector :: Int -> Int randomFlipVector k = runST $ do let n = 1 `shiftL` k vec <- MU.new n - forM_ (take (mult * n) randomFlips) $ + forM_ (take (mult * n) randomIndices) $ \i -> MU.unsafeModify vec complement (i .&. (1 `shiftL` k - 1)) i <- MU.unsafeRead vec 0 pure $ if i then 1 else 0 @@ -62,7 +56,7 @@ randomFlipIntSet k = if IS.member 0 vec then 1 else 0 vec = foldl' (\acc i -> let j = i .&. (1 `shiftL` k - 1) in (if IS.member j acc then IS.delete else IS.insert) j acc) mempty - (take (mult * n) randomFlips) + (take (mult * n) randomIndices) mult :: Int mult = 100 diff --git a/bench/Bench/RandomRead.hs b/bench/Bench/RandomRead.hs index 2c1d0dd..88df7c8 100644 --- a/bench/Bench/RandomRead.hs +++ b/bench/Bench/RandomRead.hs @@ -10,67 +10,54 @@ import Data.Bits -- import Data.List import qualified Data.Vector.Unboxed as U import qualified Data.Vector.Unboxed.Mutable as MU -import System.Random import Test.Tasty.Bench -randomVec :: [Bool] -randomVec - = map (> (0 :: Int)) - . randoms - . mkStdGen - $ 42 - -randomReads :: [Int] -randomReads - = map abs - . randoms - . mkStdGen - $ 42 +import Bench.Common benchRandomRead :: Int -> Benchmark benchRandomRead k = bgroup (show (1 `shiftL` k :: Int)) - [ bench "Bit" $ nf randomReadBit k - , bench "BitTS" $ nf randomReadBitTS k - , bench "Vector" $ nf randomReadVector k - -- , bench "IntSet" $ nf randomReadIntSet k + [ bench labelBit $ nf randomReadBit k + , bench labelBitTS $ nf randomReadBitTS k + , bench labelVector $ nf randomReadVector k + -- , bench labelIntSet $ nf randomReadIntSet k ] randomReadBit :: Int -> Int randomReadBit k = runST $ do let n = 1 `shiftL` k - vec <- U.unsafeThaw (U.fromList (map Bit $ take n randomVec)) + vec <- U.unsafeThaw (U.fromList (map Bit $ take n randomBools)) let go acc [] = pure acc go acc (i : is) = do Bit b <- MU.unsafeRead vec (i .&. (1 `shiftL` k - 1)) go (acc + if b then 1 else 0) is - go 0 (take (mult * n) randomReads) + go 0 (take (mult * n) randomIndices) randomReadBitTS :: Int -> Int randomReadBitTS k = runST $ do let n = 1 `shiftL` k - vec <- U.unsafeThaw (U.fromList (map TS.Bit $ take n randomVec)) + vec <- U.unsafeThaw (U.fromList (map TS.Bit $ take n randomBools)) let go acc [] = pure acc go acc (i : is) = do TS.Bit b <- MU.unsafeRead vec (i .&. (1 `shiftL` k - 1)) go (acc + if b then 1 else 0) is - go 0 (take (mult * n) randomReads) + go 0 (take (mult * n) randomIndices) randomReadVector :: Int -> Int randomReadVector k = runST $ do let n = 1 `shiftL` k - vec <- U.unsafeThaw (U.fromList (take n randomVec)) + vec <- U.unsafeThaw (U.fromList (take n randomBools)) let go acc [] = pure acc go acc (i : is) = do b <- MU.unsafeRead vec (i .&. (1 `shiftL` k - 1)) go (acc + if b then 1 else 0) is - go 0 (take (mult * n) randomReads) + go 0 (take (mult * n) randomIndices) -- randomReadIntSet :: Int -> Int --- randomReadIntSet k = foldl' (+) 0 [ doRead (c + i `shiftL` 1 - i - c) | c <- [0 .. mult - 1], i <- randomReads ] +-- randomReadIntSet k = foldl' (+) 0 [ doRead (c + i `shiftL` 1 - i - c) | c <- [0 .. mult - 1], i <- randomIndices ] -- where -- n = 1 `shiftL` k -- vec = IS.fromDistinctAscList $ map fst $ filter snd --- $ zip [0..] $ take n randomVec +-- $ zip [0..] $ take n randomBools -- doRead i = if IS.member (i .&. (1 `shiftL` k - 1)) vec then 1 else 0 mult :: Int diff --git a/bench/Bench/RandomWrite.hs b/bench/Bench/RandomWrite.hs index 171a1e9..4b3056a 100644 --- a/bench/Bench/RandomWrite.hs +++ b/bench/Bench/RandomWrite.hs @@ -10,29 +10,23 @@ import Data.Bits import Data.Foldable import qualified Data.IntSet as IS import qualified Data.Vector.Unboxed.Mutable as MU -import System.Random import Test.Tasty.Bench -randomWrites :: [(Int, Bool)] -randomWrites - = map (\x -> if x > 0 then (x, True) else (negate x, False)) - . randoms - . mkStdGen - $ 42 +import Bench.Common benchRandomWrite :: Int -> Benchmark benchRandomWrite k = bgroup (show (1 `shiftL` k :: Int)) - [ bench "Bit" $ nf randomWriteBit k - , bench "BitTS" $ nf randomWriteBitTS k - , bench "Vector" $ nf randomWriteVector k - , bench "IntSet" $ nf randomWriteIntSet k + [ bench labelBit $ nf randomWriteBit k + , bench labelBitTS $ nf randomWriteBitTS k + , bench labelVector $ nf randomWriteVector k + , bench labelIntSet $ nf randomWriteIntSet k ] randomWriteBit :: Int -> Int randomWriteBit k = runST $ do let n = 1 `shiftL` k vec <- MU.new n - forM_ (take (mult * n) randomWrites) $ + forM_ (take (mult * n) randomIndicesAndBools) $ \(i, b) -> MU.unsafeWrite vec (i .&. (1 `shiftL` k - 1)) (Bit b) Bit i <- MU.unsafeRead vec 0 pure $ if i then 1 else 0 @@ -41,7 +35,7 @@ randomWriteBitTS :: Int -> Int randomWriteBitTS k = runST $ do let n = 1 `shiftL` k vec <- MU.new n - forM_ (take (mult * n) randomWrites) $ + forM_ (take (mult * n) randomIndicesAndBools) $ \(i, b) -> MU.unsafeWrite vec (i .&. (1 `shiftL` k - 1)) (TS.Bit b) TS.Bit i <- MU.unsafeRead vec 0 pure $ if i then 1 else 0 @@ -50,7 +44,7 @@ randomWriteVector :: Int -> Int randomWriteVector k = runST $ do let n = 1 `shiftL` k vec <- MU.new n - forM_ (take (mult * n) randomWrites) $ + forM_ (take (mult * n) randomIndicesAndBools) $ \(i, b) -> MU.unsafeWrite vec (i .&. (1 `shiftL` k - 1)) b i <- MU.unsafeRead vec 0 pure $ if i then 1 else 0 @@ -62,7 +56,7 @@ randomWriteIntSet k = if IS.member 0 vec then 1 else 0 vec = foldl' (\acc (i, b) -> (if b then IS.insert else IS.delete) (i .&. (1 `shiftL` k - 1)) acc) mempty - (take (mult * n) randomWrites) + (take (mult * n) randomIndicesAndBools) mult :: Int mult = 100 diff --git a/bench/Bench/Remainder.hs b/bench/Bench/Remainder.hs index cc7d031..d67eece 100644 --- a/bench/Bench/Remainder.hs +++ b/bench/Bench/Remainder.hs @@ -1,5 +1,7 @@ {-# LANGUAGE CPP #-} {-# LANGUAGE MagicHash #-} +{-# OPTIONS_GHC -Wno-unrecognised-pragmas #-} +{-# HLINT ignore "Avoid lambda" #-} module Bench.Remainder ( benchRemainder @@ -8,45 +10,21 @@ module Bench.Remainder import Data.Bit import qualified Data.Bit.ThreadSafe as TS import Data.Bits -import qualified Data.Vector.Unboxed as U -import qualified Data.Vector.Unboxed.Mutable as MU import GHC.Exts #ifdef MIN_VERSION_ghc_bignum import GHC.Num.Integer #else import GHC.Integer.Logarithms #endif -import System.Random import Test.Tasty.Bench -randomBools :: [Bool] -randomBools - = map (> (0 :: Int)) - . randoms - . mkStdGen - $ 42 - -randomVec :: MU.Unbox a => (Bool -> a) -> Int -> U.Vector a -randomVec f k = U.fromList (map f (take (2 * n) randomBools)) - where - n = 1 `shiftL` k - -randomVec2 :: MU.Unbox a => (Bool -> a) -> Int -> U.Vector a -randomVec2 f k = U.fromList (map f (take n $ drop (2 * n) randomBools)) - where - n = 1 `shiftL` k - -randomInteger :: Int -> Integer -randomInteger k = toInteger $ toF2Poly $ randomVec Bit k - -randomInteger2 :: Int -> Integer -randomInteger2 k = toInteger $ toF2Poly $ randomVec2 Bit k +import Bench.Common benchRemainder :: Int -> Benchmark benchRemainder k = bgroup (show (1 `shiftL` k :: Int)) - [ bench "Bit" $ nf (\x -> rem (toF2Poly $ randomVec Bit k) x) (toF2Poly $ randomVec2 Bit k) - , bench "BitTS" $ nf (\x -> rem (TS.toF2Poly $ randomVec TS.Bit k) x) (TS.toF2Poly $ randomVec2 TS.Bit k) - , bench "Integer" $ nf (\x -> binRem (randomInteger k) x) (randomInteger2 k) + [ bench labelBit $ nf (\x -> rem (toF2Poly $ randomVec Bit (2 * k)) x) (toF2Poly $ randomVec2 Bit k) + , bench labelBitTS $ nf (\x -> rem (TS.toF2Poly $ randomVec TS.Bit (2 * k)) x) (TS.toF2Poly $ randomVec2 TS.Bit k) + , bench labelInteger $ nf (\x -> binRem (randomInteger (2 * k)) x) (randomInteger2 k) ] binRem :: Integer -> Integer -> Integer diff --git a/bench/Bench/Reverse.hs b/bench/Bench/Reverse.hs index e5d59a7..068905f 100644 --- a/bench/Bench/Reverse.hs +++ b/bench/Bench/Reverse.hs @@ -6,34 +6,13 @@ import Data.Bit import qualified Data.Bit.ThreadSafe as TS import Data.Bits import qualified Data.Vector.Unboxed as U -import qualified Data.Vector.Unboxed.Mutable as MU -import System.Random import Test.Tasty.Bench -randomBools :: [Bool] -randomBools - = map (> (0 :: Int)) - . randoms - . mkStdGen - $ 42 - -randomVec :: MU.Unbox a => (Bool -> a) -> Int -> U.Vector a -randomVec f k = U.fromList (map f (take n randomBools)) - where - n = 1 `shiftL` k +import Bench.Common benchReverse :: Int -> Benchmark benchReverse k = bgroup (show (1 `shiftL` k :: Int)) - [ bench "Bit" $ nf reverseBit (randomVec Bit k) - , bench "BitTS" $ nf reverseBitTS (randomVec TS.Bit k) - , bench "Vector" $ nf reverseVector (randomVec id k) + [ bench labelBit $ nf reverseBits (randomVec Bit k) + , bench labelBitTS $ nf TS.reverseBits (randomVec TS.Bit k) + , bench labelVector $ nf U.reverse (randomVec id k) ] - -reverseBit :: U.Vector Bit -> U.Vector Bit -reverseBit = reverseBits - -reverseBitTS :: U.Vector TS.Bit -> U.Vector TS.Bit -reverseBitTS = TS.reverseBits - -reverseVector :: U.Vector Bool -> U.Vector Bool -reverseVector = U.reverse diff --git a/bench/Bench/Sum.hs b/bench/Bench/Sum.hs index 27098a8..dcf934a 100644 --- a/bench/Bench/Sum.hs +++ b/bench/Bench/Sum.hs @@ -1,3 +1,6 @@ +{-# OPTIONS_GHC -Wno-unrecognised-pragmas #-} +{-# HLINT ignore "Avoid lambda" #-} + module Bench.Sum ( benchAdd , benchSum @@ -7,44 +10,20 @@ import Data.Bit import qualified Data.Bit.ThreadSafe as TS import Data.Bits import Data.Foldable -import qualified Data.Vector.Unboxed as U -import qualified Data.Vector.Unboxed.Mutable as MU -import System.Random import Test.Tasty.Bench -randomBools :: [Bool] -randomBools - = map (> (0 :: Int)) - . randoms - . mkStdGen - $ 42 - -randomVec :: MU.Unbox a => (Bool -> a) -> Int -> U.Vector a -randomVec f k = U.fromList (map f (take n randomBools)) - where - n = 1 `shiftL` k - -randomVec2 :: MU.Unbox a => (Bool -> a) -> Int -> U.Vector a -randomVec2 f k = U.fromList (map f (take n $ drop n randomBools)) - where - n = 1 `shiftL` k - -randomInteger :: Int -> Integer -randomInteger k = toInteger $ toF2Poly $ randomVec Bit k - -randomInteger2 :: Int -> Integer -randomInteger2 k = toInteger $ toF2Poly $ randomVec2 Bit k +import Bench.Common benchAdd :: Int -> Benchmark benchAdd k = bgroup (show (1 `shiftL` k :: Int)) - [ bench "Bit" $ nf (\x -> (+) (toF2Poly $ randomVec Bit k) x) (toF2Poly $ randomVec2 Bit k) - , bench "BitTS" $ nf (\x -> (+) (TS.toF2Poly $ randomVec TS.Bit k) x) (TS.toF2Poly $ randomVec2 TS.Bit k) - , bench "Integer" $ nf (\x -> xor (randomInteger k) x) (randomInteger2 k) + [ bench labelBit $ nf (\x -> (+) (toF2Poly $ randomVec Bit k) x) (toF2Poly $ randomVec2 Bit k) + , bench labelBitTS $ nf (\x -> (+) (TS.toF2Poly $ randomVec TS.Bit k) x) (TS.toF2Poly $ randomVec2 TS.Bit k) + , bench labelInteger $ nf (\x -> xor (randomInteger k) x) (randomInteger2 k) ] benchSum :: Int -> Benchmark benchSum k = bgroup (show (1 `shiftL` k :: Int)) - [ bench "Bit" $ nf (foldl' (+) 0) [(1 :: F2Poly) .. fromInteger (1 `shiftL` k)] - , bench "BitTS" $ nf (foldl' (+) 0) [(1 :: TS.F2Poly) .. fromInteger (1 `shiftL` k)] - , bench "Integer" $ nf (foldl' xor 0) [(1 :: Integer) .. fromInteger (1 `shiftL` k)] + [ bench labelBit $ nf (foldl' (+) 0) [(1 :: F2Poly) .. fromInteger (1 `shiftL` k)] + , bench labelBitTS $ nf (foldl' (+) 0) [(1 :: TS.F2Poly) .. fromInteger (1 `shiftL` k)] + , bench labelInteger $ nf (foldl' xor 0) [(1 :: Integer) .. fromInteger (1 `shiftL` k)] ] diff --git a/bench/Bench/Union.hs b/bench/Bench/Union.hs index 0b3c73c..6d29bb4 100644 --- a/bench/Bench/Union.hs +++ b/bench/Bench/Union.hs @@ -1,3 +1,6 @@ +{-# OPTIONS_GHC -Wno-unrecognised-pragmas #-} +{-# HLINT ignore "Avoid lambda" #-} + module Bench.Union ( benchUnion ) where @@ -7,53 +10,14 @@ import qualified Data.Bit.ThreadSafe as TS import Data.Bits import qualified Data.IntSet as IS import qualified Data.Vector.Unboxed as U -import qualified Data.Vector.Unboxed.Mutable as MU -import System.Random import Test.Tasty.Bench -randomBools :: [Bool] -randomBools - = map (> (0 :: Int)) - . randoms - . mkStdGen - $ 42 - -randomVec :: MU.Unbox a => (Bool -> a) -> Int -> U.Vector a -randomVec f k = U.fromList (map f (take n randomBools)) - where - n = 1 `shiftL` k - -randomVec2 :: MU.Unbox a => (Bool -> a) -> Int -> U.Vector a -randomVec2 f k = U.fromList (map f (take n $ drop n randomBools)) - where - n = 1 `shiftL` k - -randomSet :: Int -> IS.IntSet -randomSet k = IS.fromAscList (map fst (filter snd (zip [0..] (take n randomBools)))) - where - n = 1 `shiftL` k - -randomSet2 :: Int -> IS.IntSet -randomSet2 k = IS.fromAscList (map fst (filter snd (zip [0..] (take n $ drop n randomBools)))) - where - n = 1 `shiftL` k +import Bench.Common benchUnion :: Int -> Benchmark benchUnion k = bgroup (show (1 `shiftL` k :: Int)) - [ bench "Bit" $ nf (\x -> unionBit (randomVec Bit k) x) (randomVec2 Bit k) - , bench "BitTS" $ nf (\x -> unionBitTS (randomVec TS.Bit k) x) (randomVec2 TS.Bit k) - , bench "Vector" $ nf (\x -> unionVector (randomVec id k) x) (randomVec2 id k) - , bench "IntSet" $ nf (unionIntSet (randomSet k)) (randomSet2 k) + [ bench labelBit $ nf (\x -> zipBits (.|.) (randomVec Bit k) x) (randomVec2 Bit k) + , bench labelBitTS $ nf (\x -> TS.zipBits (.|.) (randomVec TS.Bit k) x) (randomVec2 TS.Bit k) + , bench labelVector $ nf (\x -> U.zipWith (||) (randomVec id k) x) (randomVec2 id k) + , bench labelIntSet $ nf (IS.union (randomSet k)) (randomSet2 k) ] - -unionBit :: U.Vector Bit -> U.Vector Bit -> U.Vector Bit -unionBit = zipBits (.|.) - -unionBitTS :: U.Vector TS.Bit -> U.Vector TS.Bit -> U.Vector TS.Bit -unionBitTS = TS.zipBits (.|.) - -unionVector :: U.Vector Bool -> U.Vector Bool -> U.Vector Bool -unionVector = U.zipWith (||) - -unionIntSet :: IS.IntSet -> IS.IntSet -> IS.IntSet -unionIntSet = IS.union diff --git a/bitvec.cabal b/bitvec.cabal index 5b57dfc..29fde86 100644 --- a/bitvec.cabal +++ b/bitvec.cabal @@ -151,6 +151,7 @@ benchmark bitvec-bench hs-source-dirs: bench other-modules: Bench.BitIndex + Bench.Common Bench.GCD Bench.Invert Bench.Intersection