- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在使用 benchpress
库运行一些相当简单的基准测试。我一直在使用 bench::Int -> IO a -> IO ()
接口(interface)。但是,似乎如果我运行给定函数 n
次,第一次之后的所有运行都非常快。
举个简单的例子,bench 1 (seq (sum [1..100000]) (return ()))
可能需要 10 秒左右。但是,bench 5 (seq (sum [1..100000]) (return ()))
将生成如下报告:
Times (ms)
min mean +/-sd median max
0.001 2.657 5.937 0.001 13.277
Percentiles (ms)
50% 0.001
66% 0.002
75% 0.002
80% 0.002
90% 13.277
95% 13.277
98% 13.277
99% 13.277
100% 13.277
因为平均值是 2.6,我可以推断出第一次运行用了 13 秒,而其他 4 次非常快。
为什么会这样?我如何确保基准测试的所有运行都具有代表性?该库还有一个更细粒度的接口(interface):benchmark::Int -> IO a -> (a -> IO b) -> (a -> IO c) -> IO (Stats, Stats)
。这将使我能够提供设置和拆卸功能——我可以使用这个界面来获得更有意义的结果吗?
最佳答案
我建议使用 criterion
。它经过精心设计,具有用于计算纯计算时间的工具(正如您所发现的,这可能很棘手)。我不熟悉 benchpress
,但它似乎没有开箱即用的相同功能,而且似乎主要旨在对 IO 操作进行基准测试。
在 criterion
中对您的示例进行基准测试看起来像这样:
import Criterion.Main
main = defaultMain
[ bench "my summation" $ whnf sum [1..100000] ]
从没有优化标志的 GHCi 和 ghc
运行的基准测试在很大程度上是没有意义的,因此使用 ghc -O2
编译它很重要。运行它将产生输出:
benchmarking my summation
time 9.393 ms (9.271 ms .. 9.498 ms)
0.998 R² (0.997 R² .. 0.999 R²)
mean 9.385 ms (9.292 ms .. 9.483 ms)
std dev 268.7 μs (208.4 μs .. 334.0 μs)
您可以在此处看到时间从最小值 9.3 毫秒到 9.5 毫秒不等,因此没有大的异常值。但是,Criterion 会自动放弃初始运行,以确保仅在第一次运行代码时产生的成本(GHC 代码经常发生)不会包含在计时中。
whnf
函数是一个神奇的函数,它确保即使它的两个参数可能在第一次运行后被完全求值并因此在内存中完全形成,它的第一个参数应用到它的第二个将真正重复每次运行,并且评估将进行得足够远以将结果置于“弱头正常形式”中。一个数的弱头范式(比如一堆整数的和)就是这个数本身,所以对于这个基准测试,时机是对实际数值和的评估。
重要的是要了解此计算的哪些部分没有被基准化。表达式 [1..100000]
构造一个列表。如果列表没有被优化掉(在这个基准测试中它没有),列表的构造,作为一个完全保存在内存中的装箱 Integer
的单链表,执行第一个被丢弃的迭代,这里的基准时间是遍历构造列表以求和其元素。您可以对列表的构造和求和进行计时:
bench "construct and sum" $ whnf (\n -> sum [1..n]) 100000
但这会产生出乎意料的更快的结果:
benchmarking construct and sum
time 1.299 ms (1.288 ms .. 1.314 ms)
0.999 R² (0.999 R² .. 1.000 R²)
mean 1.290 ms (1.285 ms .. 1.297 ms)
std dev 20.77 μs (14.74 μs .. 27.59 μs)
因为列表通过列表融合进行了优化,您现在正在对一个紧密的求和循环进行基准测试。
如果你真的想计时一个显式列表的构造和求和,你可以用一个不内联的 sum
的副本来防止列表融合:
sum' :: (Num a) => [a] -> a
{-# NOINLINE sum' #-}
sum' = sum
...bench "construct and sum w/o fusion" $ whnf (\n -> sum' [1..n]) 100000...
也就是说,对 GHC 代码进行基准测试很棘手,但使用 criterion
几乎是强制性的。
一个完整的例子:
import Criterion.Main
{-# NOINLINE sum' #-}
sum' :: (Num a) => [a] -> a
sum' = sum
main = defaultMain
[ bench "sum an in-memory list" $ whnf sum [1..100000]
, bench "construct and sum w/ fusion" $ whnf (\n -> sum [1..n]) 100000
, bench "construct and sum w/o fusion" $ whnf (\n -> sum' [1..n]) 100000
, bench "Int (vs. Integer) and fusion" $ whnf (\n -> sum[(1::Int)..n]) 100000
]
我使用 ghc -O2
得到的时间大致是 9ms、1ms、14ms 和 47μs。请注意,与 Integer
相比,Int
非常快,如果您没有使用显式类型签名并且无意中默认为 Integer
.
在这里,差异与数据类型本身关系不大,而与拆箱和融合的组合关系更大。最终基准被编译成一个相当紧凑的汇编循环,将寄存器中的数字从 1 添加到 100000。
实际上, native 代码生成器在这里做得不好。 LLVM 后端 (
ghc -O2 -fllvm
) 将 Int
版本缩短到 100 纳秒。当你得到这么小的时间时,最好扩大问题的规模,以确保你实际上在测量你认为你在测量的东西。如果我将列表长度扩大 10 倍,则所有时间都扩大 10 倍,因此我可以有理由相信我正在按预期对实际求和进行计时。
关于haskell - 如何从多次运行的 haskell 基准测试中获取更有意义的统计数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65742862/
我正在阅读一些基准测试技巧,并在此站点上发现了一条提示“重新启动 MySQL 服务器以消除任何不需要的缓存因素”:http://blog.monitor.us/2012/09/the-gold-sta
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 7 年前。
我在linux上测量cpu时间和排序算法的时间。我使用getrusage来测量cpu时间,并使用clock_gettime CLOCK_MONOTONIC来获取墙时间。尽管我注意到cpu时间大于墙上时
我可以阅读很多关于 OpenCL 的文章,它似乎是最有前途的(唯一的?)多架构库。 OpenCL应该是第一个并行架构编程标准,它最终会被大部分程序员采用。这很好,但是从 native 编程库迁移到 O
我想在不使用外部依赖项的情况下对一些 Lua 进行基准测试。我目前正在使用 os.clock: local function dummy() end local start = os.clock()
我对此很好奇。 我想检查哪个函数更快,所以我编写了一些代码并执行了很多次。 public static void main(String[] args) { long ts;
有没有办法在项目的开发阶段对 SQL 查询进行基准测试? 有问题的表中只有几个示例行,但我想在行数达到数千、数百万、数十亿、数万亿、数亿等等之前对一些查询进行基准测试 用数千行样本数据填充表格是唯一的
我正在尝试测量使用 rdtsc 执行函数“check()”所需的时间,如下所示: a = rdtsc(); check(pw); b = rdtsc(); return (b-a); 但是,我收到的时
我想在我的 Hadoop 集群上执行基准测试和性能测试。我知道 hadoop-mapreduce*test*.jar 和 hadoop-mapreduce-examples*.jar 有很多用于基准测
按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
这个现在非常常见的算法问题是在白板考试期间由监考人员提出的。我的工作是观察、倾听和客观判断给出的答案,但我无法控制这个问题,也无法与回答者互动。 给了五分钟的时间分析问题,考生可以写项目符号,伪代码(
我把代码从 http://www.bonto.ch/blog/2011/12/08/json-libraries-for-ios-comparison-updated/并在我的本地机器上进行了测试。
我正在尝试使用 MySQL 基准测试来测试一些查询。但是,我遇到了一个错误。 SELECT benchmark (10000, (select title from user)); 作为返回,我得到了
我很好奇这个。 我想检查哪个函数更快,所以我创建了一些代码并执行了很多次。 public static void main(String[] args) { long ts;
关闭。这个问题需要更多focused .它目前不接受答案。 想改进这个问题吗? 更新问题,使其只关注一个问题 editing this post . 关闭 9 年前。 Improve this qu
我经常想比较同一函数的多个实现的运行时性能。对于个人输入,标准是一个很好的工具。 但是有什么简单的方法可以在不同的输入大小上绘制代码的性能,例如看算法复杂度? 理想情况下,我向库传递一个类型为 Ben
我有一系列旨在完成相同功能的功能。相同的输入产生相同的输出,但是执行这些输出所需的时间因功能而异。我想确定哪个是“最快”的,我想对自己的测量结果具有“统计学意义”有一定的信心。 细读Wikipedia
我想编写一个加载基准测试,它以编译时已知的步幅跨过给定的内存区域,并在该区域的末尾(2 的幂)使用尽可能少的非加载指令进行包装有可能。 例如,给定步长 4099,rdi 中的迭代计数以及 rsi 中指
我有多个组件与 RabbitMQ 相连。有些是生产者和消费者。我需要对我的系统进行基准测试/负载测试。我需要确保消费者每秒可以处理 N 条消息。我在互联网上做了一些搜索,但还没有真正找到任何东西。有没
是否有任何基准或研究来比较这两个 IDE --稳定性-- 开发人员生产力 - 特征 - 表现-- 等等 最佳答案 我是 Eclipse 用户(不是自愿的)。不确定稳定性,但性能方面 NetBeans
我是一名优秀的程序员,十分优秀!