F#Interactive应该比编译慢得多吗?

时间:2016-02-10 11:05:08

标签: f#

我已经使用F#将近六个月并且非常确定F#Interactive应该具有与编译相同的性能,当我打扰它进行基准测试时,我确信它是某种编译器错误。虽然现在我发现在打开问题之前我应该​​先在这里查看。

对我而言,它大约慢了3倍,优化开关似乎根本没有做任何事情。

这应该是标准行为吗?如果是这样,我真的受#time指令的拖累。我知道在Reddit thread上总计100M元素需要多长时间。

更新

感谢FuleSnabel,我发现了一些事情。

我尝试从fsianycpu.exe(这是默认的F#Interactive)和fsi.exe运行示例脚本,我得到两次运行的不同时间。第一个为134毫秒,后者为78毫秒。这两个时序也分别对应于来自未经优化和优化的二进制文件的时序。

让事情变得更加混乱的是,我用来编译事物的第一个项目是我正在制作的游戏库的一部分(以脚本形式)并且它拒绝编译优化的二进制文件,而是切换到未优化的一个没有通知我。我必须开始一个新项目才能正确编译。另一个测试编译正确是一个奇迹。

所以基本上,这里有一些时髦的东西,我应该考虑将fsianycpu.exe切换为fsi.exe作为默认解释器。

1 个答案:

答案 0 :(得分:2)

我在pastebin中尝试了示例代码我没有看到您描述的行为。这是我的表现运行的结果:

.\bin\Release\ConsoleApplication3.exe
Total iterations: 300000000, Outer: 10000, Inner: 30000
reduce sequence of list, result 450015000, time 2836 ms
reduce array, result 450015000, time 594 ms
for loop array, result 450015000, time 180 ms
reduce list, result 450015000, time 593 ms
fsi -O --exec .\Interactive.fsx
Total iterations: 300000000, Outer: 10000, Inner: 30000
reduce sequence of list, result 450015000, time 2617 ms
reduce array, result 450015000, time 589 ms
for loop array, result 450015000, time 168 ms
reduce list, result 450015000, time 603 ms

预计Seq.reduce会是最慢的,for循环最快,而list / array上的reduce大致相似(这假设列表元素的位置无法保证)。

我重写了您的代码,以允许更长时间的运行而不会耗尽内存并改善数据的缓存局部性。短期运行时,测量的不确定性使得难以比较数据。

Program.fs:

module fs

let stopWatch = 
  let sw = new System.Diagnostics.Stopwatch()
  sw.Start ()
  sw

let total = 300000000
let outer = 10000
let inner = total / outer

let timeIt (name : string) (a : unit -> 'T) : unit =
  let t = stopWatch.ElapsedMilliseconds
  let v = a ()
  for i = 2 to outer do
    a () |> ignore
  let d = stopWatch.ElapsedMilliseconds - t
  printfn "%s, result %A, time %d ms" name v d

[<EntryPoint>]
let sumTest(args) = 
  let numsList = [1..inner]
  let numsArray = [|1..inner|]

  printfn "Total iterations: %d, Outer: %d, Inner: %d" total outer inner

  let sumsSeqReduce () = Seq.reduce (+) numsList
  timeIt "reduce sequence of list" sumsSeqReduce

  let sumsArray () = Array.reduce (+) numsArray
  timeIt "reduce array" sumsArray

  let sumsLoop () =
    let mutable total = 0
    for i in 0 .. inner - 1 do
      total <- total + numsArray.[i]
    total

  timeIt "for loop array" sumsLoop

  let sumsListReduce () = List.reduce (+) numsList

  timeIt "reduce list" sumsListReduce

  0

Interactive.fsx:

#load "Program.fs"
fs.sumTest [||]

PS。我在Windows上使用Visual Studio 2015运行.32位或64位似乎只有微不足道的差异