Ich habe sehr einfache C # - und F # -Testprogramme erstellt.
%Vor%c # 71 ms f # 1797 ms
Ich habe eine zweite Version von F # erstellt, die ähnlich funktioniert wie c #
%Vor%aber das Ergebnis nicht signifikant verändert (1650ms)
Ich verstehe den großen Unterschied in der Geschwindigkeit zwischen den zwei Sprachen nicht.
Die beiden Programme haben einen sehr ähnlichen IL-Code, beide verwenden IEnumerable, außerdem ersetzt F # den Funktionsaufruf durch Operation.
Ich habe c # -Code basierend auf f # IL-Code umgeschrieben.
%Vor%Der IL-Code von zwei Programmen ist gleich, aber die Geschwindigkeit ist immer noch sehr unterschiedlich. Ich fand den IL-Unterschied dank Foggy Finder
Der langsame Code
%Vor%Der schnelle Code
%Vor% Der Hauptgrund, warum OP einen Leistungsunterschied sieht, ist, weil Seq.init
in F # langsam ist. Der Grund dafür ist, dass in jeder Iteration Seq.upto
(welche Seq.init
verwendet) ein neues Lazy<_>
-Objekt zuweist. Sie können dies in Seq
Quelle sehen.
Wenn Sie eine Low-Overhead-Funktion wie fun n -> n % 2
haben, kostet die Berechnung eines neuen Lazy<_>
-Objekts sowie dessen Auswertung (Mutex-Sperre und -Entsperrung) viel Zeit.
Der zweite Grund, warum OP einen Leistungsunterschied sieht, ist, dass Seq
in F # im Allgemeinen langsam ist. Dies wird in diesem PR
Mit dem PR-Inplace wird F # Seq
im Vergleich zu den vorhandenen Alternativen sehr gut funktionieren (einige Details hier )
Mit all dem Gesagten habe ich einige Vergleiche von verschiedenen Möglichkeiten vorbereitet, um die Berechnung durch den Benutzer zu tun (abgesehen von der offensichtlichen total / 2
).
Der passende C # -Code:
%Vor%Die Leistungszahlen, die auf meinem Rechner (Intel Core I5) unter .NET 4.6.1 64bit angezeigt werden:
%Vor% Seq
macht das Schlimmste und verbraucht auch Speicher. Wenn sowohl F # als auch C # -Code LINQ verwendet, gibt es keinen wirklichen Unterschied wie erwartet. Nessos ist eine leistungsstarke Datenpipeline für F # (und C #), die wesentlich besser funktioniert.
"Hard-Coding" eine for-Schleife ist noch besser und die schnellste Lösung ist die Verwendung von SSE bis System.Numerics.Vectors
. Leider unterstützt System.Numerics.Vectors
%
nicht, was den Vergleich etwas unfair macht.
Der Unterschied ist also nicht so sehr ein Sprachproblem, sondern ein Bibliotheksproblem.
Tags und Links c# linq f# performance