Inspiriert von einer Frage von SO: /programming/6623391/how-to-gain-control-of-a-5gb-heap-in-haskell
Es kann eine lange Debatte über die zahlreichen Vor- und Nachteile von FP sein, aber im Moment möchte ich den Anwendungsbereich auf die Haupteffizienz von FP für moderne Hardware beschränken.
These:
Das Funktionsparadigma impliziert Unveränderlichkeit und Zustandslosigkeit (?), Aber die Hardware, auf der wir Funktionsprogramme ausführen, sind zustandsbehaftete endliche Automaten. Die Übersetzung von 'rein funktionalem' Programm in eine 'zustandsbehaftete Hardware'-Darstellung überlässt dem Programmierer wenig Kontrolle, bringt Overhead (?) Und schränkt die Verwendung von Hardware-Funktionen (?) Ein.
Habe ich in den fraglichen Aussagen Recht oder Unrecht?
Kann nachgewiesen werden, dass FP für die moderne Allzweck-Computerarchitektur wesentliche Leistungseinbußen mit sich bringt / nicht mit sich?
EDIT: Wie ich bereits zu einigen Kommentaren ausgeführt habe, geht es bei der Frage nicht um die Implementierungsleistung und Details. Es geht um das Vorhandensein oder Nichtvorhandensein von Hauptaufwand , den das Ausführen von FP auf statusbehafteten Automaten mit sich bringen kann.
running FP on stateful automata
.Antworten:
Unveränderlichkeit ist ein großes Missverständnis.
Die Unveränderlichkeit ist ein Merkmal der Semantik, impliziert jedoch keine Unveränderlichkeit bei der Implementierung.
Ein einfaches Beispiel ist die Implementierung von Faulheit.
Wenn Berechnungen verzögert sind, ist das Ergebnis eines Ausdrucks konzeptionell ein Wert, aber die zugrunde liegende Implementierung ist ein Thunk, der die auszuwertenden Argumente und eine Funktion zum Erstellen des Werts sowie einen Steckplatz zum Speichern des Werts enthält.
Wenn Sie zum ersten Mal (in der Sprache) nach dem Wert fragen, wird die Berechnung tatsächlich durchgeführt, das Ergebnis ausgewertet und der Wert an Sie zurückgegeben (oder ein Handle).
Dies ist in der Sprachsemantik transparent, und Sie wissen nur, dass diese Variable an einen Wert (oder einen zukünftigen Wert) gebunden wurde und dass Sie den zurückgegebenen Wert danach nicht mehr ändern können. Die zugrunde liegende Speicherdarstellung ändert sich, aber Sie wissen nichts davon.
Der gleiche Unterschied zwischen Semantik und Implementierung besteht in nahezu jeder Sprache und steht im Mittelpunkt der Optimierung . Unabhängig von der Sprache garantiert die Semantik einige Dinge, während andere nicht spezifiziert sind, um Optimierungsspielraum zu lassen.
Nun ist es wahr, dass praktisch funktionale Sprachen nicht so schnell sind wie beispielsweise C ++. Allerdings
Go
(was immer noch ein ziemlicher Hype ist) ist langsamer als Haskell oder Lisp, ebenso wie C # Mono ( Quelle ).Wenn Sie sehen, wie unzuverlässig C ++ oder C sein kann, um diese Leistungen zu erzielen, möchten Sie vielleicht ein wenig loslassen.
Wenn Sie feststellen, dass Haskell heute schnell wächst und noch viel Optimierungsspielraum für den Compiler / die Laufzeit besteht (GHC hat kürzlich auf LLVM umgestellt, z. B. finanziert Microsoft Research die Laufzeitverbesserungen aktiv), sind Sie möglicherweise bereit, darauf zu wetten es wird sich bald verbessern.
Spaß: Ein Spiel mit regulären Ausdrücken oder wie ein Haskell-Team einen Matcher für reguläre Ausdrücke erstellt hat
re2
, der in einer Reihe von Szenarien die C-Bibliothek von Google übertrifft .quelle
Funktionsparadigma ist nützlich, um Dinge in einem engen Rahmen aufzuteilen. Dies ist eine wirklich gute Sache, wenn man bedenkt, wie sich der Computer entwickelt.
Multicore-CPUs haben große Probleme beim Umgang mit gemeinsam genutzten Ressourcen, und die Synchronisationskosten sind sehr hoch. Das Funktionsparadigma ermöglicht es auf natürliche Weise, Programme auszudrücken, die diese Probleme nicht haben. Das ist wirklich gut für die Parallelität.
Darüber hinaus verwenden wir zunehmend Serverfarmen mit SaaS und Cloud Computing. Daher muss dieselbe Anwendung auf mehreren Computern ausgeführt werden. In dieser Position sind die Synchronisationskosten noch teurer. Google hat einige Arbeiten durchgeführt und einige Forschungsarbeiten über funktionale Programmierung und Algorithmen veröffentlicht, die Sie einschreiben können. Dies ist für sie von entscheidender Bedeutung, da sie ein Problem mit der Skallierbarkeit haben.
Darüber hinaus können Sie mithilfe von verknüpften Listen problemlos einen Stapel im Haufen des Computers und sogar einen nicht kontinuierlichen Stapel erstellen. Dies wird bereits getan, um Stack-Trace in vielen Programmiersprachen zu generieren. Das ist also kein Problem.
OK, die funktionale Programmierung beinhaltet einige Einschränkungen. Es bringt aber auch eine natürliche Art und Weise, Probleme auszudrücken, die wir im modernen Computer haben und die in Paradigmen, an die wir gewöhnt sind, extrem schwer zu handhaben sind. Skalierbarkeit ist eine davon und wird zu einem echten Geschäft.
Jeder, der sich bereits mit einem komplexen Parallelsystem beschäftigt, weiß wovon ich spreche.
Also würde ich die Antwort nuancieren. Ja, funktionale Probleme gibt es mit moderner Hardware, aber auch mit einfacher alter Programmierung. Wie immer gibt es Vor- und Nachteile. Der Punkt ist, zu wissen, was sie sind, damit Sie die richtige Wahl treffen können, wenn Sie müssen.
quelle
Ich habe keine wirkliche Antwort, da ich den aktuellen Status nicht kenne oder auch nicht weiß, wie schwierig er sein würde, aber nur, weil der Compiler diese Dinge von der Eingabe sicherstellen würde, heißt das nicht unbedingt, dass die Ausgabe sie haben würde . Theoretisch könnte ein hinreichend intelligenter Compiler all diese Probleme umgehen, aber in der Praxis wird es sie wahrscheinlich immer geben.
Eine andere Sichtweise ist jedoch die Betrachtung der Geschichte der Lisp-Maschine. Wenn ich mich recht entsinne, waren sie ursprünglich dazu gedacht, die gleichen Probleme zu überwinden, die Lisp mit dem Unterschied zu den Maschinen zu der Zeit hatte. Die Entwicklung dieser Maschinen wurde schließlich gestoppt, da der Desktop schnell genug wurde, um die Ineffizienzen billiger zu machen, als eine andere Maschine zu unterstützen.
Mit Ausnahme der leistungskritischsten Anwendung sind FP-Sprachen im Allgemeinen immer noch schnell genug. Wenn Sie eine höhere Sprache wählen, sind Sie bereit, die Priorität für die Feinabstimmung der Steuerung und Leistung zu verringern, um eine sicherere, einfachere, wartbarere oder eine andere Priorität zu erreichen.
Letztendlich dreht sich bei der Programmierung alles um Kompromisse, daher muss man nur auswählen, was für das vorliegende Projekt wichtiger ist.
quelle
Das funktionale Paradigma impliziert zwar Unveränderlichkeit und Staatenlosigkeit, aber wir haben keine vollständig reinen Programmiersprachen. Selbst das reinste, Haskell, lässt Nebenwirkungen zu.
Zur Beantwortung Ihrer Frage zur Effizienz habe ich jedoch sowohl Haskell als auch Clojure verwendet und bei beiden keine Leistungsprobleme festgestellt.
quelle