Nehmen wir an, ich übergebe eine kleine Funktion f
an map
. Kann Haskell inline f
mit map
eine kleine Imperativ-Schleife erzeugen? Wenn ja, wie verfolgt Haskell, welche Funktion f
wirklich ist? Kann man das mit Arrow-Kombinatoren machen?Kann Haskell Inline-Funktionen als Argument übergeben werden?
Antwort
Wenn f
als Argument übergeben wird, dann nein, wahrscheinlich nicht. Wenn f
der Name einer Top-Level-Funktion oder einer lokalen Funktion ist, dann wahrscheinlich ja.
foobar f = ... map f ...
-- Probably not inlined.
foobar = ... map (\ x -> ...) ...
-- Probably inlined.
Das heißt, entnehme ich, dass die meisten der Performance-Unterschied zwischen Inline- und aus der Linie nicht von der tatsächlichen inlining kommt selbst, sondern von irgendwelchen zusätzlichen nachfolgenden Optimierungen dies ermöglichen könnten.
Die einzige Möglichkeit, über diese Dinge "sicher" zu sein, besteht darin, den Code tatsächlich zu schreiben, ihn tatsächlich zu kompilieren und sich den Core anzusehen, der generiert wird. Und der einzige Weg zu wissen, ob es einen Unterschied macht (positiv oder negativ), ist das Benchmarking der Sache.
Im ersten Fall könnte 'foobar' selbst leicht inline sein, so dass' f' auch inline sein kann. –
Hängt davon ab, wie viel Zeug 'foobar' zusätzlich zum Aufruf' f' — tut, aber ja, es ist sicherlich möglich, dass es inline wird. Der einzige Weg, es wirklich zu wissen, ist zu schauen. – MathematicalOrchid
Die Definition der Haskell-Sprache schreibt keine Haskell-Implementierung für Inline-Code vor, oder irgendeine Art von Optimierung durchzuführen. Jede Implementierung ist frei, jede Optimierung anzuwenden, die sie für angemessen hält.
Haskell wird heutzutage oft mit GHC ausgeführt, was den Haskell-Code optimiert. Beim Inlining verwendet GHC einige Heuristiken, um zu entscheiden, ob etwas inline sein soll oder nicht. Der allgemeine Hinweis lautet, die Optimierung mit -O2
einzuschalten und die Ausgabe des Compilers zu überprüfen. Sie können den produzierten Core mit -ddump-simpl
oder den Assembly-Code mit -ddump-asm
sehen. Einige andere flags können auch nützlich sein.
Wenn Sie dann sehen, dass GHC keine Dinge inliniert, die Sie gerne hätten, können Sie dem Compiler einen Hinweis mit {-# INLINE foo #-}
und related pragmas geben.
Seien Sie vorsichtig, wenn Sie gedankenlos Optimierungen anwenden. Häufig verbringen Programmierer ihre Zeit damit, Teile des Programms zu optimieren, die einen geringen Einfluss auf die Gesamtleistung haben. Um dies zu vermeiden, wird dringend empfohlen, zuerst den Code profile einzugeben, damit Sie wissen, wo Ihr Programm viel Zeit verbringt. Hier
Dies ist ein nützlicher Rat, der jedoch die Frage nicht wirklich beantwortet. –
Das Tolle an der Arbeit mit Bibliotheken ist, dass ich normalerweise keine Möglichkeit habe, zu wissen, welche Funktionen meine Benutzer an leistungssensiblen Orten verwenden, so dass ich sicher Zeit damit verbringen kann, (fast) alles zu optimieren. – dfeuer
ist ein Beispiel, in dem GHC tut Inline eine Funktion als Argument übergeben:
import qualified Data.Vector.Unboxed as U
import qualified Data.Vector as V
plus :: Int -> Int -> Int
plus = (+)
sumVect :: V.Vector Int -> Int
sumVect = V.foldl1 plus
plus
wird als Argument foldl1
übergeben, die in Summieren einen Vektor von ganzen Zahlen ergibt.
letrec {
$s$wfoldlM_loop_s759
:: GHC.Prim.Int# -> GHC.Prim.Int# -> GHC.Prim.Int#
$s$wfoldlM_loop_s759 =
\ (sc_s758 :: GHC.Prim.Int#) (sc1_s757 :: GHC.Prim.Int#) ->
case GHC.Prim.tagToEnum# @ Bool (GHC.Prim.>=# sc_s758 ww1_s748)
of _ {
False ->
case GHC.Prim.indexArray#
@ Int ww2_s749 (GHC.Prim.+# ww_s747 sc_s758)
of _ { (# ipv1_X72o #) ->
case ipv1_X72o of _ { GHC.Types.I# y_a5Kg ->
$s$wfoldlM_loop_s759
(GHC.Prim.+# sc_s758 1#) (GHC.Prim.+# sc1_s757 y_a5Kg)
}
};
True -> sc1_s757
}; }
Das ist die GHC.Prim.+# sc1_s757 y_a5Kg
: Im Kern ist plus
zum unboxed GHC.Prim.+# :: Int# -> Int# -> Int#
inlined und optimiert. Sie können einfache artihmetic Inside-Funktion plus
hinzufügen und diesen Core-Ausdruck erweitern.
- 1. $ (this) als Argument übergeben?
- 2. Funktion als Klasse Argument übergeben
- 3. C# übergeben Funktion als Argument
- 4. Ein Array als Argument übergeben
- 5. Eine Methode als Argument übergeben
- 6. Haskell - Übergabe einer Funktion als Argument Kompilierungsfehler
- 7. übergeben Sie einen Typ als Attribut Argument
- 8. Übergeben eines statischen Arrays als Argument
- 9. Warum kann ich UIImageView nicht als Argument übergeben?
- 10. Die Größe eines Arrays als Argument übergeben
- 11. Warum kann ich "window.location.reload" nicht als Argument an setTimeout übergeben?
- 12. Haskell: hSetFileSize: ungültiges Argument (ungültiges Argument)
- 13. Warum Haskell ein Argument nimmt
- 14. Nicht einen Dynamikbereich als Argument übergeben können
- 15. Typ in Scala übergeben als Argument
- 16. subprocess.Popen: wie eine Liste als Argument übergeben
- 17. jede Kontrolle als Argument der Funktion übergeben
- 18. Können Sie einen "Typ" als Argument übergeben?
- 19. Wie kann moq verwendet werden, um zu überprüfen, ob ein ähnliches Objekt als Argument übergeben wurde?
- 20. PHP-Schnittstelle so implementieren, dass Objektinstanz als Array-Typ-Argument übergeben werden kann?
- 21. Ergebnis der Funktion kann nicht als Referenz übergeben werden
- 22. Pythonic Argument übergeben
- 23. Wie werden Funktionen ausgewertet, wenn sie als Argumente übergeben werden
- 24. erstes Argument EqualTo() übergeben kann kein Objekt
- 25. Übergeben Sie ATTR {idVendor} als Argument in udev-Skript
- 26. JSON-Objekt an MVC-Controller als Argument übergeben
- 27. Übergeben Sie ein Array als Funktion Argument aus einer Funktion, die es als Argument in C
- 28. Wie man na.rm als Argument an tapply übergeben?
- 29. Welche Datei muss ich als Argument Pfadname von ftok() übergeben
- 30. Übergeben von "*()" als Argument an ein Programm in Bash
Inlining ist ein wirklich einfacher syntaktischer Mechanismus (iterative Ersetzung von linken Seiten durch rechte Seiten von Funktionen), es gibt kein "Bleib 'was" f "ist. Sicher, wenn Sie irgendwo in Ihrem Code "map f" haben, dann kann 'map' an dieser Callsite inline sein, an welcher Stelle auch' f' sein könnte. – jberryman