{-# LANGUAGE BangPatterns #-} {-# LANGUAGE ScopedTypeVariables #-} module Main where import Control.Monad import Criterion.Main import Data.List import Data.Word import HaskellWorks.Data.Bits.PopCount.PopCount1 import HaskellWorks.Data.FromForeignRegion import HaskellWorks.Data.Positioning import HaskellWorks.Data.RankSelect.Base.Select1 import HaskellWorks.Data.RankSelect.CsPoppy import HaskellWorks.Data.RankSelect.CsPoppy.Internal import HaskellWorks.Data.RankSelect.Poppy512 import System.Directory import System.Environment import qualified Data.Vector.Storable as DVS import qualified HaskellWorks.Data.RankSelect.CsPoppy as CS import qualified HaskellWorks.Data.RankSelect.Poppy512 as P512 {-# ANN module ("HLint: ignore Redundant do" :: String) #-} {-# ANN module ("HLint: ignore Reduce duplication" :: String) #-} selectStep :: Count selectStep = 1000 benchCsPoppyBuild :: IO [Benchmark] benchCsPoppyBuild = do entries <- listDirectory "data" let files = ("data/" ++) <$> (".ib" `isSuffixOf`) `filter` entries return (mkBenchmark <$> files) where mkBenchmark filename = env (mmapFromForeignRegion filename) $ \bitString -> bgroup filename [ bench "CsPoppy Build" (whnf CS.makeCsPoppy bitString) ] benchCsPoppyRank1 :: IO [Benchmark] benchCsPoppyRank1 = do entries <- listDirectory "data" let files = ("data/" ++) <$> (".ib" `isSuffixOf`) `filter` entries return (mkBenchmark <$> files) where mkBenchmark filename = env (mmapFromForeignRegion filename) $ \(v :: CsPoppy) -> bgroup filename [ bench "CsPoppy Rank1" (whnf (CS.rank1 v) 100) ] benchCsPoppySelect1 :: IO [Benchmark] benchCsPoppySelect1 = do entries <- listDirectory "data" let files = ("data/" ++) <$> (".ib" `isSuffixOf`) `filter` entries return (mkBenchmark <$> files) where mkBenchmark filename = env (mmapFromForeignRegion filename) $ \(rsbs :: CsPoppy) -> bgroup filename [ bench "CsPoppy Select1" (whnf (go rsbs 1 (popCount1 rsbs) ((popCount1 rsbs `div` 100) + 1)) 0) ] go rsbs a z step acc | a <= z = go rsbs (a + step) z step (select1 rsbs a + acc) go _ _ _ _ acc = acc {-# INLINE go #-} benchPoppy512Build :: IO [Benchmark] benchPoppy512Build = do entries <- listDirectory "data" let files = ("data/" ++) <$> (".ib" `isSuffixOf`) `filter` entries return (mkBenchmark <$> files) where mkBenchmark filename = env (mmapFromForeignRegion filename) $ \bitString -> bgroup filename [ bench "Poppy512 Build" (whnf P512.makePoppy512 bitString) ] benchPoppy512Rank1 :: IO [Benchmark] benchPoppy512Rank1 = do entries <- listDirectory "data" let files = ("data/" ++) <$> (".ib" `isSuffixOf`) `filter` entries return (mkBenchmark <$> files) where mkBenchmark filename = env (mmapFromForeignRegion filename) $ \(rsbs :: Poppy512) -> bgroup filename [ bench "Poppy512 Rank1" (whnf (CS.rank1 rsbs) 100) ] benchPoppy512Select1 :: IO [Benchmark] benchPoppy512Select1 = do entries <- listDirectory "data" let files = ("data/" ++) <$> (".ib" `isSuffixOf`) `filter` entries return (mkBenchmark <$> files) where mkBenchmark filename = env (mmapFromForeignRegion filename) $ \(rsbs :: Poppy512) -> bgroup filename [ bench "Poppy512 Select1" (whnf (go rsbs 1 (popCount1 rsbs) ((popCount1 rsbs `div` 100) + 1)) 0) ] go rsbs a z step acc | a <= z = go rsbs (a + step) z step (select1 rsbs a + acc) go _ _ _ _ acc = acc {-# INLINE go #-} runCsPoppyBuild :: IO () runCsPoppyBuild = do entries <- listDirectory "data" let files = ("data/" ++) <$> (".ib" `isSuffixOf`) `filter` entries forM_ files $ \file -> do msbs :: CsPoppy <- mmapFromForeignRegion file let !_ = select1 msbs 1 return () benchMakeCsPoppyBlocks1 :: IO [Benchmark] benchMakeCsPoppyBlocks1 = do entries <- listDirectory "data" let files = ("data/" ++) <$> (".ib" `isSuffixOf`) `filter` entries return (mkBenchmark <$> files) where mkBenchmark filename = env (mmapFromForeignRegion filename) $ \(v :: DVS.Vector Word64) -> bgroup filename [ bench "makeCsPoppyBlocks1" (whnf makeCsPoppyBlocks1 v) ] benchMakeCsPoppyBlocks2 :: IO [Benchmark] benchMakeCsPoppyBlocks2 = do entries <- listDirectory "data" let files = ("data/" ++) <$> (".ib" `isSuffixOf`) `filter` entries return (mkBenchmark <$> files) where mkBenchmark filename = env (mmapFromForeignRegion filename) $ \(v :: DVS.Vector Word64) -> bgroup filename [ bench "makeCsPoppyBlocks2" (whnf makeCsPoppyBlocks2 v) ] benchMakeCsPoppyLayerM :: IO [Benchmark] benchMakeCsPoppyLayerM = do entries <- listDirectory "data" let files = ("data/" ++) <$> (".ib" `isSuffixOf`) `filter` entries return (mkBenchmark <$> files) where mkBenchmark filename = env (mkEnv filename) $ \(v :: DVS.Vector Word64) -> bgroup filename [ bench "makeCsPoppyLayerM" (whnf makeCsPoppyLayerM v) , bench "makeCsPoppyLayerM2" (whnf makeCsPoppyLayerM2 v) ] mkEnv filename = do !v <- mmapFromForeignRegion filename return (makeCsPoppyBlocks2 v) benchGenCsSamples :: IO [Benchmark] benchGenCsSamples = do entries <- listDirectory "data" let files = ("data/" ++) <$> (".ib" `isSuffixOf`) `filter` entries return (mkBenchmark <$> files) where mkBenchmark filename = env (mkEnv filename) $ \ ~(pc, v :: DVS.Vector Word64) -> bgroup filename [ bench "benchGenCsSamples" (whnf (genCsSamples pc) v) ] mkEnv filename = do !v <- mmapFromForeignRegion filename let !blocks = makeCsPoppyBlocks2 v let !layerM = makeCsPoppyLayerM blocks return (getCsiTotal (CsInterleaved (lastOrZero layerM)), v) runBenchmarks :: IO () runBenchmarks = do benchmarks <- (concat <$>) $ sequence $ [] <> [benchCsPoppyBuild] <> [benchCsPoppyRank1] <> [benchCsPoppySelect1] <> [benchPoppy512Build] <> [benchPoppy512Rank1] <> [benchPoppy512Select1] <> [benchMakeCsPoppyBlocks1] <> [benchMakeCsPoppyBlocks2] <> [benchMakeCsPoppyLayerM] <> [benchGenCsSamples] when (null benchmarks) $ putStrLn "Warning: No benchmarks found" defaultMain benchmarks main :: IO () main = do args <- getArgs case args of [] -> runBenchmarks ["load-cspoppy"] -> runCsPoppyBuild _ -> putStrLn "Invalid arguments"