packages feed

linear-massiv-0.1.0.0: bench/Bench/BLAS.hs

{-# LANGUAGE AllowAmbiguousTypes #-}

module Bench.BLAS (blasBenchmarks) where

import Criterion.Main
import qualified Data.Massiv.Array as M
import Data.Massiv.Array (Comp(..))
import Control.DeepSeq ()
import GHC.TypeNats (KnownNat)

import Numeric.LinearAlgebra.Massiv.Types
import Numeric.LinearAlgebra.Massiv.Internal
import Numeric.LinearAlgebra.Massiv.BLAS.Level1 (dotP)
import Numeric.LinearAlgebra.Massiv.BLAS.Level2 (matvecP)
import Numeric.LinearAlgebra.Massiv.BLAS.Level3 (matMulP, matMulComp)

-- linear library imports for comparison
import Linear.V4 (V4(..))
import Linear.Matrix ((!*!), (!*))
import qualified Linear.Metric as LM
import Linear.V4 ()

-- Massiv matrix generators
mkMatP :: forall m n. (KnownNat m, KnownNat n) => Matrix m n M.P Double
mkMatP = makeMatrix @m @n @M.P $ \i j -> fromIntegral (i * 7 + j * 3 + 1) / 100.0

mkVecP :: forall n. KnownNat n => Vector n M.P Double
mkVecP = makeVector @n @M.P $ \i -> fromIntegral (i + 1) / 10.0

-- linear library 4x4 matrices for comparison
linearM44 :: V4 (V4 Double)
linearM44 = V4 (V4 1 2 3 4)
                (V4 5 6 7 8)
                (V4 9 10 11 12)
                (V4 13 14 15 16)

linearM44b :: V4 (V4 Double)
linearM44b = V4 (V4 17 18 19 20)
                 (V4 21 22 23 24)
                 (V4 25 26 27 28)
                 (V4 29 30 31 32)

linearV4 :: V4 Double
linearV4 = V4 1 2 3 4

linearV4b :: V4 Double
linearV4b = V4 5 6 7 8

blasBenchmarks :: [Benchmark]
blasBenchmarks =
  [ bgroup "gemm"
    [ -- Small sizes: compare linear vs massiv
      bgroup "4x4"
        [ bench "linear-V4" $ nf (linearM44 !*!) linearM44b
        , bench "massiv-P"  $ nf (uncurry (matMulP @4 @4 @4)) (mkMatP @4 @4, mkMatP @4 @4)
        ]
    , bgroup "10x10"
        [ bench "P/Seq" $ nf (uncurry (matMulP @10 @10 @10)) (mkMatP @10 @10, mkMatP @10 @10)
        ]
    , bgroup "50x50"
        [ bench "P/Seq" $ nf (uncurry (matMulP @50 @50 @50)) (mkMatP @50 @50, mkMatP @50 @50)
        , bench "P/Par" $ nf (uncurry (matMulComp @50 @50 @50 Par)) (mkMatP @50 @50, mkMatP @50 @50)
        ]
    , bgroup "100x100"
        [ bench "P/Seq" $ nf (uncurry (matMulP @100 @100 @100)) (mkMatP @100 @100, mkMatP @100 @100)
        , bench "P/Par" $ nf (uncurry (matMulComp @100 @100 @100 Par)) (mkMatP @100 @100, mkMatP @100 @100)
        ]
    , bgroup "200x200"
        [ bench "P/Seq" $ nf (uncurry (matMulP @200 @200 @200)) (mkMatP @200 @200, mkMatP @200 @200)
        , bench "P/Par" $ nf (uncurry (matMulComp @200 @200 @200 Par)) (mkMatP @200 @200, mkMatP @200 @200)
        ]
    -- Representation comparison at 100x100
    , bgroup "repr-100x100"
        [ bench "P" $ nf (uncurry (matMulP @100 @100 @100)) (mkMatP @100 @100, mkMatP @100 @100)
        ]
    ]
  , bgroup "dot"
    [ bgroup "4"
        [ bench "linear-V4" $ nf (LM.dot linearV4) linearV4b
        , bench "massiv-P"  $ nf (uncurry (dotP @4)) (mkVecP @4, mkVecP @4)
        ]
    , bgroup "100"
        [ bench "P" $ nf (uncurry (dotP @100)) (mkVecP @100, mkVecP @100)
        ]
    , bgroup "1000"
        [ bench "P" $ nf (uncurry (dotP @1000)) (mkVecP @1000, mkVecP @1000)
        ]
    , bgroup "10000"
        [ bench "P" $ nf (uncurry (dotP @10000)) (mkVecP @10000, mkVecP @10000)
        ]
    ]
  , bgroup "matvec"
    [ bgroup "4"
        [ bench "linear-V4" $ nf (linearM44 !*) linearV4
        , bench "massiv-P"  $ nf (uncurry (matvecP @4 @4)) (mkMatP @4 @4, mkVecP @4)
        ]
    , bgroup "50"
        [ bench "P" $ nf (uncurry (matvecP @50 @50)) (mkMatP @50 @50, mkVecP @50)
        ]
    , bgroup "100"
        [ bench "P" $ nf (uncurry (matvecP @100 @100)) (mkMatP @100 @100, mkVecP @100)
        ]
    ]
  ]