Rishaskell Leistungsanomalie

8

Ich versuche eine Performance-Anomalie zu verstehen, die beobachtet wird, wenn ein Programm unter runhaskell ausgeführt wird.

Das fragliche Programm ist:

%Vor%

Wenn ich das mache, dauert es 1,18 Sekunden.

Allerdings, wenn ich isFactor wie folgt neu definiere:

%Vor%

dann dauert das Programm 17,7 Sekunden.

Das ist ein großer Unterschied in der Leistung und ich würde erwarten, dass die Programme gleichwertig sind. Weiß jemand, was ich hier vermisse?

Hinweis: Dies geschieht nicht, wenn Sie unter GHC kompiliert wurden.

    
Steve 17.02.2012, 08:40
quelle

2 Antworten

9

Obwohl die Funktionen identisch sein sollten, unterscheiden sie sich in ihrer Anwendung. Mit der ersten Definition wird isFactor vollständig auf die Aufruf-Site isFactor x angewendet. In der zweiten Definition ist dies nicht der Fall, denn isFactor benötigt jetzt explizit zwei Argumente.

Selbst minimale Optimierungen reichen aus, damit GHC dies durchschaut und identischen Code für beide erzeugt. Wenn Sie jedoch mit -O0 -ddump-simpl kompilieren, können Sie feststellen, dass dies ohne Optimierungen einen Unterschied macht (zumindest bei ghc-7.2. 1, YMMV mit anderen Versionen).

Mit dem ersten isFactor erstellt GHC eine einzelne Funktion, die als Prädikat an "GHC.List.Filter" übergeben wird, wobei die Aufrufe von mod 10000000 und (==) inlined sind. Für die zweite Definition ist es stattdessen so, dass die meisten Aufrufe innerhalb von isFactor gebundene Referenzen auf Klassenfunktionen sind und nicht zwischen mehreren Aufrufen von isFactor geteilt werden. Es gibt also eine Menge unnötiger Dictionary-Overhead.

Das ist fast nie ein Problem, denn selbst die Standardeinstellungen des Compilers werden es optimieren, aber runhaskell macht anscheinend nicht einmal so viel. Trotzdem habe ich gelegentlich Code als someFun x y = \z -> strukturiert, weil ich weiß, dass someFun teilweise angewendet wird und dies die einzige Möglichkeit war, die gemeinsame Nutzung zwischen Anrufen zu erhalten (d. H. GHCs Optimierer war nicht clever genug).

    
John L 17.02.2012, 12:48
quelle
5

Wie ich es verstehe, macht runhaskell wenig bis gar keine Optimierung. Es wurde entwickelt, um Code schnell zu laden und auszuführen. Wenn es mehr Optimierung gab, würde es länger dauern, bis der Code gestartet wurde. Natürlich läuft der Code in diesem Fall schneller mit Optimierungen.

Wenn ich weiß, dass eine kompilierte Version des Codes vorhanden ist, wird runhaskell sie verwenden. Wenn Leistung für Sie wichtig ist, stellen Sie sicher, dass Sie mit optimierten Optimierungen zuerst kompilieren. (Ich denke, Sie könnten sogar Schalter an runhaskell übergeben, um Optimierungen zu aktivieren - Sie müssten die Dokumentation überprüfen ...)

    
MathematicalOrchid 17.02.2012 09:23
quelle

Tags und Links