为什么严格会使Haskell的性能变差

为什么严格会使Haskell的性能变差,haskell,lazy-evaluation,Haskell,Lazy Evaluation,我玩了严格的计算,向量和矩阵,得到了一个相当奇怪的结果。有以下代码: module Test where import qualified Data.Vector as V import qualified Data.Matrix as M import Control.DeepSeq matrixCtor :: Int -> Int -> Int -> M.Matrix Int matrixCtor x y size = M.matrix size size $ \(i

我玩了严格的计算,向量和矩阵,得到了一个相当奇怪的结果。有以下代码:

module Test where

import qualified Data.Vector as V
import qualified Data.Matrix as M

import Control.DeepSeq

matrixCtor :: Int -> Int -> Int -> M.Matrix Int
matrixCtor x y size = M.matrix size size $ \(i,j) -> x*i+y*j

f :: M.Matrix Int -> M.Matrix Int
f b = c
  where
    n = M.nrows b
    bt' = V.generate n $ \j -> M.getCol (j+1) b
    c = M.matrix n n $ \(i,j) -> V.sum  (V.unsafeIndex bt' (j-1))
我将其加载到ghci并执行以下操作:

*Main Test> :set +s
*Main Test> a = matrixCtor 1 2 800
(0.02 secs, 0 bytes)
*Main Test> f a `deepseq` 1
1
(6.69 secs, 8,684,393,584 bytes)
然后我试着这样做:

*Main Test> a = matrixCtor 1 2 800
(0.00 secs, 0 bytes)
*Main Test> a `deepseq` 1
1
(0.35 secs, 220,646,904 bytes)
*Main Test> f a `deepseq` 1
1
(9.72 secs, 8,484,723,352 bytes)
*Main Test>

在第二个版本中,我提前计算了矩阵,在我看来,函数
f
的执行应该加快,但这没有发生。我不明白为什么。

如果您真的想努力提高GHCi的性能,那么我建议您这样做,但GHCi中的基准测试并不能用来解释基本上在任何其他设置中代码的性能。您看到的性能数字仅在您的一个狭义上下文中有意义

例如,当您将代码转换为标准基准并进行优化时,您将看到严格版本的性能更好,而不是更差:

benchmarking first
time                 5.808 s    (4.995 s .. 6.718 s)
                     0.996 R²   (0.995 R² .. 1.000 R²)
mean                 5.237 s    (4.931 s .. 5.452 s)
std dev              325.5 ms   (0.0 s .. 374.0 ms)
variance introduced by outliers: 19% (moderately inflated)

benchmarking second
time                 5.276 s    (4.576 s .. 6.089 s)
                     0.997 R²   (0.990 R² .. 1.000 R²)
mean                 5.070 s    (4.817 s .. 5.212 s)
std dev              224.0 ms   (0.0 s .. 244.9 ms)
variance introduced by outliers: 19% (moderately inflated)

如果您真的想提高GHCi的性能,那么我建议您这样做,但是GHCi中的基准测试并不能用来解释基本上在任何其他设置中代码的性能。您看到的性能数字仅在您的一个狭义上下文中有意义

例如,当您将代码转换为标准基准并进行优化时,您将看到严格版本的性能更好,而不是更差:

benchmarking first
time                 5.808 s    (4.995 s .. 6.718 s)
                     0.996 R²   (0.995 R² .. 1.000 R²)
mean                 5.237 s    (4.931 s .. 5.452 s)
std dev              325.5 ms   (0.0 s .. 374.0 ms)
variance introduced by outliers: 19% (moderately inflated)

benchmarking second
time                 5.276 s    (4.576 s .. 6.089 s)
                     0.997 R²   (0.990 R² .. 1.000 R²)
mean                 5.070 s    (4.817 s .. 5.212 s)
std dev              224.0 ms   (0.0 s .. 244.9 ms)
variance introduced by outliers: 19% (moderately inflated)

当您对其进行基准测试时,应使用至少使用
-O1
的编译代码。其他任何事情,特别是使用ghci,都是毫无意义的。@ThomasM.DuBuisson我同意。但我更感兴趣的是这些时间的比例。为什么严格版本在这里如此缓慢?这不是唯一的测试。我经常了解这个比率。当您对它进行基准测试时,应该使用至少使用
-O1
的编译代码。其他任何事情,特别是使用ghci,都是毫无意义的。@ThomasM.DuBuisson我同意。但我更感兴趣的是这些时间的比例。为什么严格版本在这里如此缓慢?这不是唯一的测试。我经常了解这个比率。