it-swarm.com.de

Moderne Programmiersprache mit intuitiven gleichzeitigen Programmierabstraktionen

Ich interessiere mich für das Erlernen der gleichzeitigen Programmierung, wobei ich mich auf die Anwendungs-/Benutzerebene konzentriere (nicht auf die Systemprogrammierung). Ich suche eine moderne Programmiersprache auf hoher Ebene, die intuitive Abstraktionen zum Schreiben gleichzeitiger Anwendungen bietet. Ich möchte mich auf Sprachen konzentrieren, die die Produktivität steigern und die Komplexität der gleichzeitigen Programmierung verbergen.

Um einige Beispiele zu nennen, halte ich es nicht für eine gute Option, Multithread-Code in C, C++ oder Java] zu schreiben, da meiner Meinung nach meine Produktivität verringert ist und das Programmiermodell nicht intuitiv ist Sprachen, die die Produktivität steigern und intuitivere Abstraktionen bieten, wie Python und das Multiprozessor-Modul, Erlang, Clojure, Scala usw.), sind gute Optionen.

Was würden Sie aufgrund Ihrer Erfahrung empfehlen und warum?

EDIT: Vielen Dank an alle für Ihre interessanten Antworten. Es ist schwer, eine Schlussfolgerung zu ziehen, ohne es tatsächlich zu versuchen, da es viele gute Kandidaten gibt: Erlang, Clojure, Scala, Groovy und vielleicht Haskell. Ich habe die Antwort mit den überzeugendsten Argumenten bewertet, aber ich werde alle guten Kandidaten ausprobieren, bevor ich mich für einen entscheide :)

41
sakisk

Sie sollten sich mit ziemlicher Sicherheit Clojure ansehen - meiner Meinung nach ist es die beste moderne Sprache für Multi-Core-Programmierung und äußerst produktiv.

Hauptmerkmale:

  • Es ist eine funktionale Sprache , die sowohl für die Parallelität als auch für Ihre Fähigkeit, sich mit höheren Abstraktionen zu entwickeln, von Vorteil ist. Es verfügt über vollständig unveränderliche persistente Datenstrukturen und verzögerte Sequenzen, die jedem bekannt sind, der Erfahrung mit funktionalen Sprachen wie Haskell hat.
  • Es verfügt über ein sehr neuartiges Software-Transaktionsspeichersystem für den gleichzeitigen sperrenfreien Zugriff auf den veränderlichen Zustand. Das gleichzeitige Sicherstellen von Code ist oft so einfach wie das Einschließen in einen (dosync ....) Block.
  • Es ist ein [~ # ~] lisp [~ # ~] - was es extrem leistungsfähig für die makrobasierte Metaprogrammierung und Codegenerierung macht. Dies kann signifikante Produktivitätsvorteile bringen (Aufsatz von Paul Graham - "Beating The Averages")
  • Es ist eine JVM-Sprache - so erhalten Sie nicht nur Zugriff auf die große Auswahl an Bibliotheken und Tools in Java Ökosystem profitieren Sie auch von dem enormen technischen Aufwand, der dazu beigetragen hat, die JVM zu einer effektiven Plattform für gleichzeitige serverseitige Anwendungen zu machen. Aus praktischen Gründen bietet dies einen großen Vorteil gegenüber Sprachen, die nicht über diese Grundlage verfügen auf.
  • Es ist dynamisch - was zu sehr präzisem Code und viel Produktivität führt. Beachten Sie jedoch, dass Sie bei Bedarf optionale statische Typhinweise für die Leistung verwenden können.
  • Die Sprache basiert auf Abstraktionen , was etwas schwer zu erklären ist, aber der Nettoeffekt besteht darin, dass Sie eine Reihe relativ orthogonaler Merkmale erhalten, die Sie kombinieren können, um sie zu lösen deine Probleme. Ein Beispiel wäre die Sequenzabstraktion, mit der Sie Code schreiben können, der sich mit jedem "sequentiellen" Objekttyp befasst (der alles aus Listen, Zeichenfolgen, Java Arrays, unendlich faulen Sequenzen, Zeilen) enthält aus einer Datei gelesen werden etc.)
  • Es gibt eine großartige Community - hilfreich, aufschlussreich, aber vor allem sehr pragmatisch - der Fokus in Clojure liegt im Allgemeinen auf "Dinge erledigen".

Einige Mini-Codebeispiele mit einer Nebenläufigkeit:

;; define and launch a future to execute do-something in another thread
(def a (future (do-something)))

;; wait for the future to finish and print its return value
(println @a)

;; call two functions protected in a single STM transaction
(dosync
  (function-one)
  (function-two))

Insbesondere lohnt es sich, eines oder mehrere dieser Videos anzusehen:

33
mikera

Sie könnten versuchen, D. Es bietet drei Modelle. Ich empfehle entweder die erste oder die zweite.

  1. std.concurrency . Wenn Sie dieses Modul für alle Ihre Anforderungen an die Parallelität verwenden, erzwingt eine Kombination aus Sprache und Standardbibliothek die Isolation zwischen Threads. Threads kommunizieren hauptsächlich über die Nachrichtenübermittlung, wobei der gemeinsam genutzte Speicher nur eingeschränkt unterstützt wird, sodass "Sicherheit an erster Stelle" steht und Datenrennen auf niedriger Ebene nicht zulässig sind. Leider muss die Dokumentation von std.concurrency verbessert werden, aber das Modell ist in einem kostenlosen Kapitel von Andrei Alexandrescus Buch "The D Programming Language" dokumentiert.

  2. std.parallelism . Dieses Modul wurde speziell für Multicore-Parallelität und nicht für allgemeine Parallelität entwickelt. ( Parallelität und Parallelität sind nicht dasselbe, obwohl Parallelität erforderlich ist, um Parallelität zu implementieren. ) Da der springende Punkt der Parallelität die Leistung ist, funktioniert std.parallelism nicht Machen Sie keine Isolationsgarantien, da sie das Schreiben von effizientem Parallelcode erschweren würden. Es werden jedoch viele fehleranfällige Details auf niedriger Ebene entfernt, sodass es sehr schwierig ist, Fehler zu machen, wenn Sie manuell überprüfte Workloads parallelisieren, die voneinander unabhängig sind.

  3. core.thread ist ein Wrapper auf niedriger Ebene über betriebssystemspezifische Threading-APIs. Sowohl std.concurrency als auch std.parallelism verwenden es unter der Haube, aber ich würde es nur empfehlen, wenn Sie Ihre eigene Parallelitätsbibliothek schreiben oder einen lächerlichen Eckfall finden, der weder in std.parallelism noch in std gut funktioniert .concurrency. Niemand sollte etwas so Niedriges für die tägliche Arbeit verwenden.

27
dsimcha

Schauen Sie sich Microsoft Parallel Programming für .net an. Es ist sehr intuitiv.

Viele PCs und Workstations verfügen über zwei oder vier Kerne (dh CPUs), mit denen mehrere Threads gleichzeitig ausgeführt werden können. Computer werden in naher Zukunft voraussichtlich deutlich mehr Kerne haben. Um die Hardware von heute und morgen zu nutzen, können Sie Ihren Code parallelisieren, um die Arbeit auf mehrere Prozessoren zu verteilen. In der Vergangenheit erforderte die Parallelisierung eine Manipulation von Threads und Sperren auf niedriger Ebene. Visual Studio 2010 und .NET Framework 4 verbessern die Unterstützung für die parallele Programmierung, indem sie eine neue Laufzeit, neue Klassenbibliothekstypen und neue Diagnosetools bereitstellen. Diese Funktionen vereinfachen die parallele Entwicklung, sodass Sie effizienten, feinkörnigen und skalierbaren parallelen Code in einer natürlichen Sprache schreiben können, ohne direkt mit Threads oder dem Thread-Pool arbeiten zu müssen. Die folgende Abbildung bietet einen allgemeinen Überblick über die parallele Programmierarchitektur in .NET Framework 4 ... http://i.msdn.Microsoft.com/dynimg/IC292903.png

23
Otávio Décio

Erlang ist definitiv eine großartige Option, aber etwas Praktischeres könnte Go sein, Googles neue Sprache.

Es ist nicht so weit von anderen gängigen Sprachen entfernt, daher ist es normalerweise leicht zu bekommen, wenn Sie bereits andere 'einfache' Sprachen kennen. Viele Leute vergleichen es mit Python oder sogar Lua, wenn es darum geht, wie 'bequem' es ist, zu programmieren.

23
Javier

Sowohl Erlang als auch Scala haben akteursbasierte Parallelität , was ich sehr intuitiv und leicht zu erlernen fand.

Das Akteurmodell in der Informatik ist ein mathematisches Modell der gleichzeitigen Berechnung, das "Akteure" als universelle Grundelemente der gleichzeitigen digitalen Berechnung behandelt: Als Reaktion auf eine empfangene Nachricht kann ein Akteur lokale Entscheidungen treffen, mehr Akteure erstellen und mehr Nachrichten senden und bestimmen, wie auf die nächste empfangene Nachricht reagiert werden soll ... Sie wurde sowohl als Rahmen für ein theoretisches Verständnis der Berechnung als auch als theoretische Grundlage für mehrere praktische Implementierungen gleichzeitiger Systeme verwendet.

21
TMN

Ich lerne gerade etwas über Haskell und das Lesen von dieses Papier hat mich überzeugt, dass Haskell eine gute Option für die gleichzeitige Programmierung ist. Da es rein funktional ist (das Typsystem weiß, ob eine Funktion Eingaben, Ausgaben oder das Lesen/Ändern des globalen Status vornimmt), kann es beispielsweise Software-Transaktionsspeicher (im obigen Dokument sehr gut zusammengefasst) ausführen, der sich ähnlich wie Transaktionen verhält in Datenbanken - Sie erhalten eine Reihe von schönen Dingen wie Atomizität mit nur wenig zusätzlichem Zucker. AFAIK, Haskell-Fäden sind auch sehr leicht. Darüber hinaus können durch die Tatsache, dass Haskell rein funktional ist, auch einfache Aufgaben parallel mit nur einem einzigen Schlüsselwort (par) ausgeführt werden. Quelle

19
user41310

Die GO-Sprache von Google bietet einige interessante Tools für die Parallelität - das wäre eine weitere unterhaltsame Sache. Siehe: http://golang.org/doc/effective_go.html#concurrency und lesen Sie einige Beispiele durch.

Die gleichzeitige Programmierung ist ein großes Thema und es gibt hier nur Platz für einige Go-spezifische Highlights.

Die gleichzeitige Programmierung in vielen Umgebungen wird durch die Feinheiten erschwert, die erforderlich sind, um den korrekten Zugriff auf gemeinsam genutzte Variablen zu implementieren. Go befürwortet einen anderen Ansatz, bei dem gemeinsame Werte auf Kanälen weitergegeben und in der Tat niemals von separaten Ausführungsthreads aktiv geteilt werden. Es kann immer nur eine Goroutine auf den Wert zugreifen. Datenrennen können nicht von Natur aus stattfinden. Um diese Denkweise zu fördern, haben wir sie auf einen Slogan reduziert:

Kommunizieren Sie nicht, indem Sie den Speicher gemeinsam nutzen. Teilen Sie stattdessen den Speicher durch Kommunikation.

Dieser Ansatz kann zu weit gehen. Referenzzählungen können am besten durchgeführt werden, indem beispielsweise ein Mutex um eine ganzzahlige Variable gesetzt wird. Als Ansatz auf hoher Ebene erleichtert die Verwendung von Kanälen zur Zugriffssteuerung das Schreiben klarer, korrekter Programme.

Eine Möglichkeit, über dieses Modell nachzudenken, besteht darin, ein typisches Single-Thread-Programm zu betrachten, das auf einer CPU ausgeführt wird. Es sind keine Synchronisationsprimitive erforderlich. Führen Sie nun eine andere solche Instanz aus. es braucht auch keine Synchronisation. Lassen Sie nun diese beiden kommunizieren; Wenn es sich bei der Kommunikation um den Synchronisierer handelt, ist keine weitere Synchronisierung erforderlich. Unix-Pipelines zum Beispiel passen perfekt zu diesem Modell. Obwohl Go's Ansatz zur Parallelität aus Hoares Communicating Sequential Processes (CSP) stammt, kann er auch als typsichere Verallgemeinerung von Unix-Pipes angesehen werden ...

7
Aerik

In der nächsten Version macht C # es noch einfacher als das Diagramm zeigt. Es gibt zwei neue Schlüsselwörter: Async und Await.

Async wird als Funktionsmodifikator verwendet und sagt: "Diese Operation führt ihre Arbeit an einem anderen Thread aus.

Warten wird in einer Async-Funktion verwendet, und hier geschieht die Magie. Grundsätzlich weist Await den Compiler an, die Operation nach dem Schlüsselwort in einem separaten Thread auszuführen und auf die Ergebnisse zu warten. Jeder Code nach dem Aufruf zum Warten wird nach der Operation ausgeführt.

AUCH die Operation wird mit dem aufrufenden Thread synchronisiert (wenn Sie also als Reaktion auf einen Klick auf eine Schaltfläche eine asynchrone Operation ausführen, müssen Sie nicht manuell zum UI-Thread zurückkehren). Zwei kleine Schlüsselwörter und Sie erhalten viel Parallelitätsleistung. Lesen Sie mehr hier

6
Michael Brown

Hier wird ein Plug für Ada benötigt, da er alle Abstraktionen der obersten Ebene für Parallelität und Parallelität enthält. sonst bekannt als Tasking . Auch als OP nach intuitiven (subjektiven Kriterien!) Fragte, denke ich, dass ein anderer Ansatz für die Java-zentrierte Welt geschätzt werden könnte.

6
NWS

Ich würde immer noch C++ empfehlen. Es ist mehr als fähig, die notwendigen Abstraktionen zu erstellen, um anständigen gleichzeitigen Code zu schreiben. Die überwältigende Wahrscheinlichkeit ist, dass Sie einfach eine schlechte Bibliothek für die Ausführung des Jobs haben, da gut Bibliotheken für die Ausführung des Jobs relativ neu sind und das Wissen für die gute Verwendung von C++ nicht gerade üblich ist. Intels TBB gibt es erst seit einigen Jahren, und Microsofts PPL wurde erst seit letztem Jahr ausgeliefert.

Wenn Sie so etwas wie TBB oder PPL verwenden, ist gleichzeitiger Code nicht genau trivial zu schreiben, sofern Parallelität niemals trivial, aber alles andere als mühsam ist. Wenn Sie pthreads oder Win32-Threads direkt verwenden, ist es kein Wunder, dass Sie es nicht mögen - Sie schreiben praktisch in Assembler mit solchen Funktionen. Aber mit der PPL sprechen Sie von Standard-Funktionsalgorithmen, die für Sie parallelisiert sind, generischen Datenstrukturen für den gleichzeitigen Zugriff und solchen guten Dingen.

6
DeadMG

Ich würde Groovy /Java/ GPars vorschlagen, wenn Sie JVM-basiert sein können, da dies Akteure, Datenfluss, Kommunikation sequentieller Prozesse (CSP), Datenparallelität, Software-Transaktionsspeicher ( STM), Agenten, ... Der Punkt hier ist, dass es viele hochrangige Parallelitäts- und Parallelitätsmodelle gibt, von denen jedes unterschiedliche "Sweet Spots" aufweist. Sie möchten kein Modell verwenden, das nicht mit der Lösung eines Problems übereinstimmt, das Sie erstellen möchten. Sprachen und Frameworks mit nur einem Modell zwingen Sie zum Algorithmus-Hacking.

Natürlich könnte ich als voreingenommen angesehen werden, da ich zu Groovy und GPars beitrage. Andererseits arbeite ich mit CSP und Python, vgl. Python-CSP.

Ein weiterer Punkt ist, dass die ursprüngliche Frage das Lernen betrifft, nicht das Schreiben eines Produktionssystems. Die Groovy/Java/GPars-Kombination ist also eine gute Möglichkeit zu lernen, selbst wenn die eventuelle Produktionsarbeit in C++ mit Just :: Thread Pro oder TBB ausgeführt wird, anstatt JVM-basiert zu sein.

(Einige völlig vernünftige URL-Links mussten entfernt werden, da die Host-Site in Panik über Spam geriet.)

5
Russel Winder

Was ist mit Clojure? Sie können beispielsweise Swing verwenden, aber gleichzeitig Clojure programmieren? Clojure hat eine ziemlich gute Java Integration.

Haben Sie auch Java 7 Fork/Join Framework in Betracht gezogen?

4
Chiron

Vielleicht möchten Sie sich auch Groovy und die GPars Bibliothek ansehen. GPars BTW ähnelt in gewisser Weise der in einer anderen Antwort erwähnten .NET Parallel Extension, aber die flexible Syntax von Groovys macht es unter bestimmten Umständen besser lesbar.

2

Scala wurde mehrmals in den Fragen und Antworten erwähnt, aber ich habe keinen Hinweis auf Akka gesehen, eine Schauspielerimplementierung, die sowohl mit Scala als auch mit Java.

0
Giorgio