gpt4 book ai didi

haskell - 如何使用 Criterion 来衡量 Haskell 程序的性能?

转载 作者:行者123 更新时间:2023-12-03 20:52:52 24 4
gpt4 key购买 nike

我正在尝试使用 Criterion 框架来衡量一个简单的 Haar DWT 程序的性能。 (这是错误的慢,但我会把它留给另一个问题)。不幸的是,我在网上找不到任何好的文档。我的两个主要问题是

  • 如何将数据从一个基准传递到另一个基准?我想为程序的每个阶段计时。
  • 采样如何工作,并避免重复使用之前的计算的惰性评估?

  • 这个来源相对减少;第一个函数 getRandList生成随机数列表; haarStep将输入信号转换为差和和, haarDWT调用前者并对总和进行递归。我正在尝试通过 getRandListhaarDWT通过惰性评估,但也许我的用法不正确/不受支持。时间安排似乎没有意义。
    {-# LANGUAGE ViewPatterns #-}

    import Control.Arrow
    import qualified Data.Vector.Unboxed as V
    import System.Random
    import Criterion.Main

    invSqrt2 = 0.70710678118654752440

    getRandList :: RandomGen g => g -> Int -> [Float]
    getRandList gen 0 = []
    getRandList gen n = v:rest where
    (v, gen') = random gen
    rest = getRandList gen' (n - 1)

    haarStep :: V.Vector Float -> (V.Vector Float, V.Vector Float)
    haarStep = (alternatingOp (-) &&& alternatingOp (+)) where
    alternatingOp op x = V.generate (V.length x `div` 2) (\i ->
    ((x V.! (2 * i)) `op` (x V.! (2 * i + 1))) * invSqrt2)

    haarDWT :: V.Vector Float -> V.Vector Float
    haarDWT xl@(V.length -> 1) = xl
    haarDWT (haarStep -> (d, s)) = haarDWT s V.++ d

    main = do
    gen <- getStdGen
    inData <- return $ getRandList gen 2097152
    outData <- return $ haarDWT (V.fromList inData)

    defaultMain [
    bench "get input" $ nf id inData,
    bench "transform" $ nf V.toList outData
    ]
    writeFile "input.dat" (unlines $ map show inData)
    writeFile "output.dat" (unlines $ map show $ V.toList outData)

    最后,当我尝试使用 -s 1 调用它时出现错误。 ;也许这只是一个标准错误。
    Main: ./Data/Vector/Generic.hs:237 ((!)): index out of bounds (1,1)

    提前致谢!

    最佳答案

    发布的基准错误地慢...或者是

    你确定这是错误的?您正在触摸(嗯,“nf”调用正在触摸)200 万个盒装元素 - 那是 400 万个指针。如果你愿意,你可以称之为错误,但问题只是你认为你所衡量的与你真正衡量的相比。

    在基准之间共享数据

    数据共享可以通过部分应用来实现。在我的基准测试中,我通常有

    let var = somethingCommon in
    defaultMain [ bench "one" (nf (func1 somethingCommon) input1)
    , bench "two" (nf (func2 somethingCommon) input2)]

    在存在惰性求值时避免重用

    Criterion 通过分离你的函数和你的输入来避免共享。您有以下签名:
    funcToBenchmark :: (NFData b) => a -> b
    inputForFunc :: a

    每次在 Haskell 中申请 funcToBenchmark inputForFunc它将创建一个需要评估的thunk。除非您使用与先前计算相同的变量名称,否则没有共享。没有自动内存——这似乎是一个常见的误解。

    请注意未共享内容的细微差别。我们不共享最终结果,但共享输入。如果输入的生成是您想要进行基准测试的(即 getRandList,在这种情况下),则对其进行基准测试,而不仅仅是 identity + nf 函数:
    main = do
    gen <- getStdGen
    let inData = getRandList gen size
    inVec = V.fromList inData
    size = 2097152
    defaultMain
    [ bench "get input for real" $ nf (getRandList gen) size
    , bench "get input for real and run harrDWT and listify a vector" $ nf (V.toList . haarDWT . V.fromList . getRandList gen) size
    , bench "screw generation, how fast is haarDWT" $ whnf haarDWT inVec] -- for unboxed vectors whnf is sufficient

    解读数据

    第三个基准相当有指导意义。让我们看看打印出什么标准:
    benchmarking screw generation, how fast is haarDWT
    collecting 100 samples, 1 iterations each, in estimated 137.3525 s
    bootstrapping with 100000 resamples
    mean: 134.7204 ms, lb 134.5117 ms, ub 135.0135 ms, ci 0.950

    基于单次运行,Criterion 认为执行 100 个样本需要 137 秒。大约十秒钟后,它完成了——发生了什么?好吧,第一次运行强制所有输入( inVec),这很昂贵。随后的运行找到了一个值而不是一个 thunk,因此我们真正对 haarDWT 进行了基准测试。而不是 StdGen RNG(已知速度非常慢)。

    关于haskell - 如何使用 Criterion 来衡量 Haskell 程序的性能?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6637968/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com