【发布时间】:2019-11-02 22:32:34
【问题描述】:
使用 F# Visual Studio(社区 2019)和 F# 命令行(均使用 F# 4.7)构建的程序在执行时间上存在显着差异。我的问题:为什么会有这种差异?
我使用的是 Windows 10 家庭版 1809(最新)。该程序主要在 Pollard rho 因式分解算法中使用大整数(下面的程序)。对于 Visual Studio,我使用了一个控制台项目。
Visual Studio 的运行时间为 28 秒,命令行运行时间为 39 秒。
我在两者上都使用了 x64 目标的发布二进制文件。我尝试了许多 fsc 编译命令行选项(--debug- --optimize+ --standalone),没有任何明显的区别。
命令行编译输出为
7168 Nov 2 16:14 rho.exe
命令行
fsc rho.fs
如上所述,添加命令行选项并没有太大区别。
Visual Studio 的输出是
10752 Nov 2 09:12 rho0.dll*
159744 Nov 2 09:12 rho0.exe*
所以输出是非常不同的。 rho 和 rho0 是同一个源。
两个版本产生相同的答案,但经过的时间差异很大。为什么?
程序是:
open System
open System.Diagnostics
open System.Numerics
type Z = System.Numerics.BigInteger
let rho n maxIter c1 =
let mutable iter = 1
let mutable prod = 1I
let mutable x = 2I
let mutable y = 11I
let mutable gcd = 0I
let mutable solution = false
let stopWatch = Stopwatch();
stopWatch.Start()
while not solution do
x <- (x * x + c1) % n;
y <- (y * y + c1) % n;
y <- (y * y + c1) % n;
prod <- ((y - x) * prod) % n;
if (iter % 150 = 0)
then
gcd <- Z.GreatestCommonDivisor (n, prod)
if (gcd <> 1I) then
stopWatch.Stop()
printfn "rho c1 = %A" c1
printfn "factor, iterations = %A, %A" gcd iter
printfn "elpased time = %A" stopWatch.ElapsedMilliseconds
solution <- true
else
prod <- 1I
iter <- iter+1
else
iter <- iter+1
if (not solution) then
printfn "no solution, iterations = %A" iter
else printfn "solution"
let n = Z.Pow(2I,257) - 1I
let maxIter = 30000000
printfn "calling rho"
let result = rho n maxIter 7I
2019 年 11 月 4 日更新:
我在命令行中使用 .Net core 构建了一个项目(https://docs.microsoft.com/en-us/dotnet/fsharp/get-started/get-started-command-line 的说明)
应用程序在 28 秒内运行。所以看起来,当你在命令行上使用 fsc 时,它使用的是 .NET Framework,但如果你用 .NET Core 制作命令行项目,运行时间会显着减少。 Visual Studio 控制台应用程序的默认设置是使用 .Net Core。
在 VS 中,如果我将框架从 .NET Core 更改为 .NET Framework,运行时间会增加到 39 秒。
【问题讨论】:
-
在 F# 中有很多值得喜欢的地方,但 bigintegers 很慢。 Windows 10 和 linux 上的 Ocaml 运行时间为 10 秒,而 F# 上的运行时间为 28 秒
-
在我看来,VS 在这里使用 dotnet 核心是因为 dll。我会使用像 dnspy 这样的工具来检查生成的输出。例如,它使用的是同一个大整数吗?
-
您实际上并没有提出问题。我的猜测是差异可能是目标框架。如果 VS 项目以 .NET Core 为目标,而 fsc 命令以 .NET Framework 为目标,那么这可能会导致差异。您是否尝试过 dotnet build 或 dotnet run?另外,请显示您运行的命令行。而且,您可以将 VS 和 fsc 设置为返回详细输出以获取更多详细信息。
-
您能分享一个重现性能差异的独立示例吗?这样我就可以在本地构建它,看看会发生什么。
-
F# 控制台应用程序的默认框架是 .NET Core 3.0(运行时间 28 秒)。如果我将 VS 项目更改为 .NET Framewok 4.5.1,则运行时间为 39 秒。这是为什么呢??
标签: .net visual-studio .net-core f#