gpt4 book ai didi

haskell - 如何为 Criterion 基准创建数据?

转载 作者:行者123 更新时间:2023-12-02 04:01:34 24 4
gpt4 key购买 nike

我正在使用criterion对我的 Haskell 代码进行基准测试。我正在进行一些繁重的计算,需要随机数据。我已经编写了这样的主要基准文件:

main :: IO ()
main = newStdGen >>= defaultMain . benchmarks

benchmarks :: RandomGen g => g -> [Benchmark]
benchmarks gen =
[
bgroup "Group"
[
bench "MyFun" $ nf benchFun (dataFun gen)
]
]

我在不同的模块中为它们保留基准测试和数据生成器:

benchFun :: ([Double], [Double]) -> [Double]
benchFun (ls, sig) = fun ls sig

dataFun :: RandomGen g => g -> ([Double], [Double])
dataFun gen = (take 5 $ randoms gen, take 1024 $ randoms gen)

这可行,但我有两个问题。首先,生成随机数据所需的时间是否包含在基准测试中?我发现a question that touches on that subject但老实说我无法将其应用到我的代码中。为了检查是否会发生这种情况,我编写了包含在 IO monad 中的数据生成器的替代版本。我将基准列表放在 main 中,称为生成器,用 <- 提取结果,然后将其传递给基准测试函数。我发现性能没有任何差异。

我的第二个问题与生成随机数据有关。现在,生成器一旦创建就不会更新,这导致在单次运行中生成相同的数据。这不是一个大问题,但无论如何,正确地解决它会很好。有没有一种巧妙的方法可以在每个 data* 函数中生成不同的随机数据? “Neat”是指“不让数据函数在 IO 内获取 StdGen”?

编辑:正如下面的评论所述,我并不真正关心数据随机性。对我来说重要的是生成数据所需的时间不包含在基准测试中。

最佳答案

This works, but I have two concerns. First, is the time needed to generate random data included in the benchmark?

是的,会的。所有随机生成都应该延迟发生。

To check whether this happens I wrote an alternative version of my data generator enclosed within IO monad. I placed benchmarks list with main, called the generator, extracted the result with <- and then passed it to the benchmarked function. I saw no difference in performance.

这是预期的(如果我明白你的意思的话); randoms gen 中的随机值只有在需要时才会生成(即在基准循环内)。

Is there a neat way to generate different random data within each data* function? "Neat" means "without making data functions acquiring StdGen within IO"?

您需要处于 IO 中,或者使用您提供的整数种子(使用 mkStdGen)创建一个 StdGen

回复。您的主要问题是如何从基准中获取 pRNG 内容,您应该能够在 defaultMain(基准 g) 内容之前完全评估随机输入, 评估强制如下:

import Control.DeepSeq(force)
import Control.Exception(evaluate)
myBench g = do randInputEvaled <- evaluate $ force $ dataFun g
defaultMain [
bench "MyFun" $ nf benchFun randInputEvaled
...

其中 force 将其参数计算为正常形式,但这仍然会延迟发生。因此,为了让它在 bench 之外进行评估,我们使用 evaluate 来利用单子(monad)排序。如果您想避免导入,您还可以执行诸如在元组中每个列表的尾部调用 seq 等操作。

这种事情应该可以正常工作,除非您需要在内存中保存大量的测试数据。

编辑:如果您想从 IO 获取数据(例如从磁盘读取),并且不希望将其混合到基准测试中,则此方法也是一个好主意。

关于haskell - 如何为 Criterion 基准创建数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12896235/

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