我正在测量此question中的haskell程序以生成带有运行时和加速总结的下表,以便我可以在图中绘图。
#Cores Runtimes Speedups
Absolute Relative
Seq ? .. ..
1 3.712 .. ..
2 1.646 .. ..
第一个问题
虽然通过编译带有-threaded
标志的程序(下面的[3]和[4])来获取1和2核上的运行时,但我不确定顺序的那个时间( [1]或[2]以下):
-threaded
标志或-Nx
编译时没有-threaded
标记
$ ghc --make -O2 test.hs
[1] $ time ./test ## number of core = 1
102334155
real 0m4.194s
user 0m0.015s
sys 0m0.046s
使用-threaded
标记
$ ghc --make -O2 test.hs -threaded -rtsopts
[2] $ time ./test ## number of core = not sure?
102334155
real 0m3.547s
user 0m0.000s
sys 0m0.078s
[3] $ time ./test +RTS -N1 ## number of core = 1
102334155
real 0m3.712s
user 0m0.016s
sys 0m0.046s
[4] $ time ./test +RTS -N2 ## number of core = 2
102334155
real 0m1.646s
user 0m0.016s
sys 0m0.046s
第二个问题
从上面可以看出,我使用time
命令来测量运行时。我正在接受“真正的”时间。但是如果我运行带有-sstderr
标志的程序,我会得到更详细的信息:
$ ghc --make -O2 test.hs -rtsopts
$ ./test +RTS -sstderr
102334155
862,804 bytes allocated in the heap
2,432 bytes copied during GC
26,204 bytes maximum residency (1 sample(s))
19,716 bytes maximum slop
1 MB total memory in use (0 MB lost due to fragmentation)
Generation 0: 1 collections, 0 parallel, 0.00s, 0.00s elapsed
Generation 1: 1 collections, 0 parallel, 0.00s, 0.00s elapsed
INIT time 0.00s ( 0.00s elapsed)
MUT time 3.57s ( 3.62s elapsed)
GC time 0.00s ( 0.00s elapsed)
EXIT time 0.00s ( 0.00s elapsed)
Total time 3.57s ( 3.62s elapsed)
%GC time 0.0% (0.0% elapsed)
Alloc rate 241,517 bytes per MUT second
Productivity 100.0% of total user, 98.6% of total elapsed
我相信-sstderr
提供了一个更准确的时间我应该使用而不是time
命令。我对么?另外,我应该使用哪个“总时间”(3.57s或3.62s)?
最后,在进行这样的测量时,任何一般建议/良好做法?我知道有一些软件包允许我们对我们的程序进行基准测试,但我主要对手动测量(或使用脚本为我这样做)感兴趣。
另外:运行时间是运行程序3次的中位数。
答案 0 :(得分:4)
我会将-N1
用于单核时间。我认为这也限制GC使用一个核心(我觉得这似乎适合基准测试?),但其他人可能知道更多。
至于你的第二个问题,Haskell中基准测试的答案几乎总是使用criterion。 Criterion将允许您对程序的一次运行进行计时,然后您可以将其包装在运行程序-N1
,-N2
等的脚本中。取3次运行的中位数是可以的非常快速和粗略的指标,但如果你想依靠结果,那么你将需要更多的运行。 Criterion运行您的代码并执行适当的统计数据,为您提供合理的平均时间,以及置信区间和标准偏差(并尝试纠正您的机器的繁忙程度)。我知道你问过自己做的最佳实践,但Criterion已经体现了很多:使用时钟时间,基准测试很多,并且你意识到,不要仅仅采用简单的结果。
如果您想对整个事情进行基准测试,那么Criterion对您的程序只需要很少的更改。加上这个:
import Criterion.Main
main :: IO ()
main = defaultMain [bench "My program" oldMain]
其中oldMain
是您以前的主要功能。