【问题标题】:Does F# do automatic memoisation?F# 做自动记忆吗?
【发布时间】:2010-06-29 21:15:12
【问题描述】:

我有这个代码:

for i in 1 .. 10 do
    let (tree, interval) = time (fun () -> insert [12.; 6. + 1.0] exampletree 128.)
    printfn "insertion time: %A" interval.TotalMilliseconds
    ()

时间函数定义为

let time f =
    let start = DateTime.Now
    let res = f ()
    let finish = DateTime.Now
    (res, finish - start)

函数 insert 在这里无关紧要,除了它不使用突变并因此每次都返回相同的值。

我得到了结果:

insertion time: 218.75
insertion time: 0.0
insertion time: 0.0
insertion time: 0.0
insertion time: 0.0
insertion time: 0.0
insertion time: 0.0
insertion time: 0.0
insertion time: 0.0
insertion time: 0.0

问题是为什么代码只计算一次结果(从插入时间来看,结果总是正确且相等)?另外,如何强制程序进行多次计算(我需要它来进行分析)?

编辑:Jared 提供了正确的答案。现在我知道要查找什么了,我可以从a timeit function for F# 获取秒表代码

我得到了以下结果:

insertion time: 243.4247
insertion time: 0.0768
insertion time: 0.0636
insertion time: 0.0617
insertion time: 0.065
insertion time: 0.0564
insertion time: 0.062
insertion time: 0.069
insertion time: 0.0656
insertion time: 0.0553

【问题讨论】:

    标签: f# profiling


    【解决方案1】:

    F# 不会自动记忆您的函数。在这种情况下,记忆化将是不正确的。即使您不直接改变项目,您也正在从您的函数中访问一个可变值 (DateTime.Now)。记住它或访问它的函数将是一个错误,因为它可能会随着调用而改变。

    您在这里看到的是 .Net JIT 的效果。第一次运行时,函数 f() 是 JIT 并产生明显的延迟。其他时候它已经是 JIT 并执行的时间小于 DateTime 的粒度

    证明这一点的一种方法是使用更细粒度的测量类,例如StopWatch。这将显示该函数执行了多次。

    【讨论】:

    • +1。需要说明的是:本机代码(例如用 C 编写)的第一次调用也较慢,因为它必须加载到内存中,从那里加载到缓存中;分支预测可能会在第一次等时做得更差。
    • +1 for System.Diagnostics.Stopwatch,它是你分析的好朋友
    • 谢谢。它有效,我已经相应地编辑/关闭了问题。
    【解决方案2】:

    第一次计时可能是由于 JIT 编译。您正在计时的实际代码的运行时间可能比 DateTime 能够测量的时间短。

    编辑:被击败 18 秒...我很高兴我有正确的想法 :)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-04-25
      • 1970-01-01
      • 1970-01-01
      • 2011-06-25
      • 2018-01-18
      • 2014-01-29
      • 1970-01-01
      相关资源
      最近更新 更多