4

我正在使用 F# Interactive Console 并比较一些数字操作的运行时间。在这段代码中,总运行时间似乎翻了一番,只是重复了一个变量的声明。

在 VS 2010 中,我这样做:

open System.Diagnostics
let mutable a=1

然后我在下面选择它并使用 Alt+Enter 运行它

let stopWatch = Stopwatch.StartNew()
for i=1 to 200100100 do
    a <- a + 1
stopWatch.Stop()
printfn "stopWatch.Elapsed: %f" stopWatch.Elapsed.TotalMilliseconds

它需要或多或少:320 ms

现在我选择它并按 Alt+Enter:

let mutable a=1
let stopWatch = Stopwatch.StartNew()
for i=1 to 200100100 do
    a <- a + 1
stopWatch.Stop()
printfn "stopWatch.Elapsed: %f" stopWatch.Elapsed.TotalMilliseconds

几乎翻倍:620 毫秒

相同的块,但包括顶部的声明几乎需要两倍。因为我在 Stopwatch.StartNew() 之前声明了变量,所以不应该是一样的吗?这与交互式控制台有关吗?我使用#time 指令得到了相同的结果。

4

2 回答 2

4

我不相信任何答案都是正确的。我认为a在这两种情况下都是相同的。我的意思是动态地发出一个单独的类型来包装该可变值(当然是在堆上!)。它需要这样做,因为在这两种情况下,a它都是一个可以被后续交互访问的顶级绑定。

综上所述,我的理论是:在第一种情况下,FSI 发出的动态类型在交互结束时加载,以便输出其默认值。然而,在第二种情况下,类型包装a直到第一次被访问时才加载,在循环中,在StopWatch启动之后。

于 2012-07-20T21:30:44.600 回答
3

Daniel 是对的 - 如果您在单独的 FSI 交互中定义一个变量,那么它的表示方式会有所不同。

要获得正确的比较,您需要在两种情况下都将变量声明为本地变量。最简单的方法是将代码嵌套在下面do(这会将下面的所有内容do转换为本地范围),然后立即评估整个do块。请参阅以下两个示例的结果:

// A version with variable declaration excluded
do
  let mutable a=1 
  let stopWatch = Stopwatch.StartNew() 
  for i=1 to 200100100 do 
    a <- a + 1 
  stopWatch.Stop() 
  printfn "stopWatch.Elapsed: %f" stopWatch.Elapsed.TotalMilliseconds 

// A version with variable declaration included
do
  let stopWatch = Stopwatch.StartNew() 
  let mutable a=1 
  for i=1 to 200100100 do 
    a <- a + 1 
  stopWatch.Stop() 
  printfn "stopWatch.Elapsed: %f" stopWatch.Elapsed.TotalMilliseconds 

当我运行它们时,我得到的差异是不可测量的。

于 2012-07-20T21:18:45.363 回答