Gmp*_*Gmp 4 benchmarking haskell lazy-evaluation
我有:
main :: IO ()
main = do
iniciofibonaccimap <- getCPUTime
let fibonaccimap = map fib listaVintesete
fimfibonaccimap <- getCPUTime
let difffibonaccimap = (fromIntegral (fimfibonaccimap - iniciofibonaccimap)) / (10^12)
printf "Computation time fibonaccimap: %0.3f sec\n" (difffibonaccimap :: Double)
listaVintesete :: [Integer]
listaVintesete = replicate 100 27
fib :: Integer -> Integer
fib 0 = 0
fib 1 = 1
fib n = fib (n-1) + fib (n-2)
Run Code Online (Sandbox Code Playgroud)
但
*Main> main
Computation time fibonaccimap: 0.000 sec
Run Code Online (Sandbox Code Playgroud)
我不明白为什么会这样.帮帮我谢谢.
哈斯克尔很懒.您在行中请求的计算
let fibonaccimap = map fib listaVintesete
Run Code Online (Sandbox Code Playgroud)
直到你以某种方式使用的价值才真正发生fibonaccimap
.因此,要测量使用的时间,您需要引入一些会强制程序执行实际计算的东西.
ETA:我最初建议打印最后一个元素来强制评估.正如TomMD所指出的那样,这远不够好 - 我强烈建议在这里阅读他的回答,以实际处理这一特定代码的方式.
正如其他人所说,这是由于懒惰的评价.要强制评估,您应该使用deepseq包并BangPatterns
:
{-# LANGUAGE BangPatterns #-}
import Control.DeepSeq
import Text.Printf
import System.CPUTime
main :: IO ()
main = do
iniciofibonaccimap <- getCPUTime
let !fibonaccimap = rnf $ map fib listaVintesete
fimfibonaccimap <- getCPUTime
let difffibonaccimap = (fromIntegral (fimfibonaccimap - iniciofibonaccimap)) / (10^12)
printf "Computation time fibonaccimap: %0.3f sec\n" (difffibonaccimap :: Double)
...
Run Code Online (Sandbox Code Playgroud)
在上面的代码中你应该注意三件事:
...
您在上面定义的函数).当您发布问题代码时,请确保它运行(哇,您应该包含导入)rnf
来自deepseq
.这会强制评估列表中的每个元素.!fibonaccimap
,意思是"现在就做,不要等待".这会强制列表被评估为弱头正常形式(whnf,基本上只是第一个构造函数(:)
).如果没有这个,这个rnf
功能本身就会没有评估.导致:
$ ghc --make ds.hs
$ ./ds
Computation time fibonaccimap: 6.603 sec
Run Code Online (Sandbox Code Playgroud)
如果您打算进行基准测试,您还应该使用optimization(-O2
)和Criterion包而不是getCPUTime
.