Разница в скорости исполнения F # между visual studio и генерацией командной строки - PullRequest
1 голос
/ 03 ноября 2019

Существует значительная разница во времени выполнения между программой, созданной с помощью F # visual studio (сообщество 2019) и командной строкой F # (обе с использованием F # 4.7). Мой вопрос: почему существует эта разница?

Я использую домашнюю версию Windows 10 1809 (недавнюю). Программа в основном использует bigintegers в алгоритме факторизации Полларда (программа ниже). Для 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

Обновление от 04.11.2009:

Из командной строки я создал проект, используя ядро ​​.Net (инструкции по адресу 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 секунд.

1 Ответ

2 голосов
/ 04 ноября 2019

Я взял ваш пример кода и провел его через различные конфигурации:

.NET Core from VS Release x64 - 37214 ms with (9171, 3, 0) CC
.NET Core from VS Release x86 - 69903 ms with (7673, 6, 0) CC
.NET Core from VS Release Any - 35694 ms with (9171, 3, 0) CC

.NET Core using EXE Release x64 - 37995 ms with (9171, 3, 0) CC
.NET Core using EXE Release x86 - 72489 ms with (7673, 7, 0) CC
.NET Core using EXE Release Any - 36106 ms with (9171, 3, 0) CC

.NET Framework 4.7.2 from VS Release x64 - 49697 ms with (5935, 4, 0) CC
.NET Framework 4.7.2 from VS Release x86 - 81324 ms with (4945, 8, 0) CC
.NET Framework 4.7.2 from VS Release Any - 80521 ms with (4945, 8, 0) CC

.NET Framework 4.7.2 using EXE Release x64 - 49450 ms with (5935, 4, 0) CC
.NET Framework 4.7.2 using EXE Release x86 - 80418 ms with (4945, 8, 0) CC
.NET Framework 4.7.2 using EXE Release Any - 80458 ms with (4945, 8, 0) CC

.NET Core using dotnet run x64 - 37614 ms with (9171, 3, 0) CC
.NET Core using dotnet run no tiered compilation x64 - 37186 ms with (9171, 3, 0) CC

Из этого казалось, что между x86 и x64 существует довольно большая разница. Вы пробовали форсировать режим x64 как в VS, так и из командной строки. Dlls могут быть скомпилированы в Any, но все еще имеют предпочтение для x86.

Кроме того;Судя по моим тестам, .NET Core работал лучше, чем .NET Framework 4.72.

Я пытался отключить многоуровневую компиляцию в .NET Core, а иногда это могло привести к проблемам с производительностью, но не выявило реальной разницы. .

Я понимаю, что это не одобряется в StackOverflow, но так как конфигурации проекта могут быть сложными для размещения в посте, я решил добавить пример кода, который использовал здесь: https://github.com/mrange/CodeStack/tree/master/q58675873/FsPerfSo

OP может видетьесли возможно воспроизвести мои цифры на машине OP.

Так что с моей точки зрения .NET Core выглядит лучше, чем .NET Framework, но почему?

Глядя на код через dnSpy Я могу 'Рассказать о существенных различиях между кодом OP для .NET Core или .NET Framework. Однако, глядя на зависимости System.Numerics, я могу заметить довольно существенные различия между .NET Core и .NET Framework версией System.Numerics.

. Эта версия новее в .NET Core для System.Numerics, но онане уверен, что они следуют одному и тому же версионированию (4.1.2.0 для .NET Core и 4.0.0.0 для .NET Framework).

Так что, с моей точки зрения, обязательно используйте x64 и .NET Core.

...