Haskell:无法使用 getCPUTime

发布于 2024-09-28 07:29:25 字数 630 浏览 1 评论 0原文

我有:

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)

*Main> main
Computation time fibonaccimap: 0.000 sec

我不明白为什么会发生这种情况。 帮帮我谢谢。

I have:

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)

But

*Main> main
Computation time fibonaccimap: 0.000 sec

I do not understand why this happens.
Help-me thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

把人绕傻吧 2024-10-05 07:29:25

正如其他人所说,这是由于惰性评估造成的。要强制评估,您应该使用 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)
...

:在上面的代码中,您应该注意到三件事:

  1. 它可以编译(对您上面定义的函数的 ... 取模)。当您发布问题代码时,请确保它运行(iow,您应该包含导入)
  2. 使用来自 deepseqrnf。这会强制评估列表中的每个元素。
  3. !fibonaccimap 上的爆炸图案,意思是“现在就做,不要等待”。这迫使列表被评估为弱头范式(whnf,基本上只是第一个构造函数(:))。如果没有这个,rnf 函数本身将保持未计算状态。

结果是:

$ ghc --make ds.hs
$ ./ds
Computation time fibonaccimap: 6.603 sec

如果您打算进行基准测试,您还应该使用优化 (-O2) 和 Criterion 包而不是 getCPUTime

As others have said, this is due to lazy evaluation. To force evaluation you should use the deepseq package and 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)
...

In the above code you should notice three things:

  1. It compiles (modulo the ... of functions you defined above). When you post code for questions please make sure it runs (iow, you should include imports)
  2. The use of rnf from deepseq. This forces the evaluation of each element in the list.
  3. The bang pattern on !fibonaccimap, meaning "do this now, don't wait". This forces the list to be evaluated to weak-head normal form (whnf, basically just the first constructor (:)). Without this the rnf function would itself remain unevaluated.

Resulting in:

$ ghc --make ds.hs
$ ./ds
Computation time fibonaccimap: 6.603 sec

If you're intending to do benchmarking you should also use optimization (-O2) and the Criterion package instead of getCPUTime.

星軌x 2024-10-05 07:29:25

哈斯克尔很懒。 您在该行中请求的计算

let fibonaccimap = map fib listaVintesete

在您以某种方式使用 Fibonaccimap 的值之前, 实际上不会发生。因此,为了测量所用的时间,您需要引入一些东西来强制程序执行实际的计算。

预计到达时间:我最初建议打印最后一个元素来强制评估。正如 TomMD 指出的那样,这还远远不够——我强烈建议阅读他的回复,了解处理这段特定代码的实际可行方法。

Haskell is lazy. The computation you request in the line

let fibonaccimap = map fib listaVintesete

doesn't actually happen until you somehow use the value of fibonaccimap. Thus to measure the time used, you'll need to introduce something that will force the program to perform the actual computation.

ETA: I originally suggested printing the last element to force evaluation. As TomMD points out, this is nowhere near good enough -- I strongly recommend reading his response here for an actually working way to deal with this particular piece of code.

话少心凉 2024-10-05 07:29:25

我怀疑您是惰性评估的“受害者”。没有什么会强制在计时调用之间评估斐波那契图,因此不会计算它。

编辑
我怀疑您正在尝试对您的代码进行基准测试,在这种情况下应该指出有 更好的方法 更可靠地执行此操作

I suspect you are a "victim" of lazy evaluation. Nothing forces the evaluation of fibonaccimap between the timing calls, so it's not computed.

Edit
I suspect you're trying to benchmark your code, and in that case it should be pointed out that there are better ways to do this more reliably.

萌无敌 2024-10-05 07:29:25

10^12 是一个整数,它强制 fromIntegral 的值是一个整数,这意味着 difffibonaccimap 被分配了一个四舍五入的值,所以它是如果时间少于半秒,则为 0。 (无论如何,这是我的猜测。我没有时间去研究它。)

10^12 is an integer, which forces the value of fromIntegral to be an integer, which means difffibonaccimap is assigned a rounded value, so it's 0 if the time is less than half a second. (That's my guess, anyway. I don't have time to look into it.)

新人笑 2024-10-05 07:29:25

正如其他答案所说,惰性评估实际上已经咬了你一口。具体来说,“let”不会强制计算表达式,它只是限定变量的范围。在某些东西需要它的值之前,计算实际上不会发生,而在实际的 IO 操作需要它的值之前,这可能不会发生。因此,您需要将 print 语句放在 getCPUTime 评估之间。当然,这也会得到那里 print 使用的 CPU 时间,但是 print 的大部分时间都在等待 IO。 (终端速度很慢。)

Lazy evaluation has in fact bitten you, as the other answers have said. Specifically, 'let' doesn't force the evaluation of an expression, it just scopes a variable. The computation won't actually happen until its value is demanded by something, which probably won't happen until an actual IO action needs its value. So you need to put your print statement between your getCPUTime evaluations. Of course, this will also get the CPU time used by print in there, but most of print's time is waiting on IO. (Terminals are slow.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文