{-# LANGUAGE CPP #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE OverloadedLists #-} {-# LANGUAGE RankNTypes #-} module Main (main) where #ifdef SIMD # include "config.h" #endif import Control.Monad.ST (ST) #ifdef SIMD import Data.Bits ((.&.), shiftL) import Data.Maybe (catMaybes) #endif import Data.Word (Word8) #ifdef SIMD import Foreign.C (CSize(..)) #endif #ifdef SIMD import System.Cpuid (cpuid) # if RS_HAVE_AVX2 import System.Cpuid (cpuidWithIndex) # endif #endif import Criterion.Main import qualified Data.Vector.Generic as V import qualified Data.Vector.Generic.Mutable as MV import qualified Data.Vector.Storable as SV #ifdef SIMD import qualified Data.Vector.Generic.Sized as S #endif import qualified Data.ReedSolomon.Galois.NoAsm as NoAsm #ifdef SIMD import qualified Data.ReedSolomon.Galois.Amd64 as Amd64 #endif main :: IO () #ifdef SIMD main = do (_, _, ecx1, edx1) <- cpuid 1 let avx = ecx1 .&. (1 `shiftL` 28) /= 0 ssse3 = ecx1 .&. (1 `shiftL` 9) /= 0 sse2 = edx1 .&. (1 `shiftL` 26) /= 0 dependOn b c = if b then Just c else Nothing # if RS_HAVE_AVX2 (_, ebx7, _, _) <- cpuidWithIndex 7 0 let avx2 = ebx7 .&. (1 `shiftL` 5) /= 0 # endif #else main = #endif defaultMain [ bgroup "Galois/galMulSlice/1048576" [ bench "NoAsm" $ whnf (benchGalMulSlice NoAsm.galMulSlice 177) v1048576 #ifdef SIMD , bench "Native" $ whnf (benchGalMulSlice Amd64.galMulSlice 177) v1048576 #endif ] #ifdef SIMD , bgroup "reedsolomon_gal_mul" $ catMaybes [ Just $ bench "Native" $ whnf (benchRGM c_reedsolomon_gal_mul) v1048576 #if RS_HAVE_AVX2 , dependOn avx2 $ bench "AVX2" $ whnf (benchRGM c_reedsolomon_gal_mul_avx2) v1048576 #endif , dependOn avx $ bench "AVX" $ whnf (benchRGM c_reedsolomon_gal_mul_avx) v1048576 , dependOn ssse3 $ bench "SSSE3" $ whnf (benchRGM c_reedsolomon_gal_mul_ssse3) v1048576 , dependOn sse2 $ bench "SSE2" $ whnf (benchRGM c_reedsolomon_gal_mul_sse2) v1048576 , Just $ bench "Generic" $ whnf (benchRGM c_reedsolomon_gal_mul_generic) v1048576 ] #endif ] where v1048576 = V.fromListN 1048576 $ cycle [minBound .. maxBound] benchGalMulSlice :: (forall s. Word8 -> SV.Vector Word8 -> SV.MVector s Word8 -> ST s ()) -> Word8 -> SV.Vector Word8 -> SV.Vector Word8 benchGalMulSlice f c in_ = V.create $ do out <- MV.new (V.length in_) f c in_ out return out #ifdef SIMD benchRGM :: Amd64.CProto -> SV.Vector Word8 -> SV.Vector Word8 benchRGM f in_ = V.create $ do out <- MV.new (V.length in_) _ <- f' v16 v16 in_ out return out where f' :: forall s. S.SVector 16 Word8 -> S.SVector 16 Word8 -> SV.Vector Word8 -> SV.MVector s Word8 -> ST s CSize f' = Amd64.cProtoToPrim f v16 = [0 .. 15] #endif #ifdef SIMD type CProto = Amd64.CProto foreign import ccall unsafe "reedsolomon_gal_mul" c_reedsolomon_gal_mul :: CProto #if RS_HAVE_AVX2 foreign import ccall unsafe "reedsolomon_gal_mul_avx2" c_reedsolomon_gal_mul_avx2 :: CProto #endif foreign import ccall unsafe "reedsolomon_gal_mul_avx" c_reedsolomon_gal_mul_avx :: CProto foreign import ccall unsafe "reedsolomon_gal_mul_ssse3" c_reedsolomon_gal_mul_ssse3 :: CProto foreign import ccall unsafe "reedsolomon_gal_mul_sse2" c_reedsolomon_gal_mul_sse2 :: CProto foreign import ccall unsafe "reedsolomon_gal_mul_generic" c_reedsolomon_gal_mul_generic :: CProto #endif