Wie funktioniert shared memory vs. message-passing-Handhabung von großen Daten-Strukturen?
In der Suche bei Go und Erlang-Ansatz, um die Parallelität bemerkte ich, dass Sie beide verlassen sich auf message-passing.
Dieser Ansatz offensichtlich verringert die Notwendigkeit für komplexe sperren, da es keinen gemeinsamen Staat.
Jedoch den Fall betrachten, viele Kunden wollen parallel nur-lese-Zugriff auf eine große Datenstruktur im Speicher, wie ein suffix-array.
Meine Fragen:
-
Wird die Verwendung von shared state schneller sein und weniger Speicher als message passing, Schlösser meist unnötig, da die Daten nur gelesen werden, Sie muss nur vorhanden in einer einzigen location?
-
Wie würde dieses problem angegangen werden in ein message-passing-Kontext? Wäre es ein einzelner Prozess mit Zugriff auf die Datenstruktur und die Kunden würden einfach brauchen, um nacheinander Anfrage Daten von ihm? Oder, wenn möglich, würde die Daten werden chunked zu erstellen, die mehrere Prozesse, die halten Brocken?
-
Gegeben, die Architektur moderner CPUs & Speicher, ist es viel Unterschied zwischen den beiden Lösungen, D. H., kann shared memory parallel Lesen durch mehrere Kerne, d.h. es ist keine hardware-Engpass, sonst machen beide Implementierungen etwa führen die gleiche?
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ja, freigegebenen Zustand könnte schneller sein in diesem Fall. Aber nur, wenn Sie können, verzichten die Schleusen, und dies ist nur machbar, wenn es unbedingt Lesen-nur. wenn es 'meist gelesen-nur" dann müssen Sie eine Sperre (es sei denn, Sie verwalten, schreiben, lock-freien Strukturen, seien Sie gewarnt, dass Sie sogar schwieriger, als sperren), und dann würde man sein hart gedrückt, um es auszuführen so schnell wie eine gute message-passing-Architektur.
Ja, könnten Sie schreiben, eine "server-Prozess" zu teilen. Mit wirklich einfache Prozesse, ist es nicht mehr schwer, als schreiben Sie eine kleine API für den Zugriff auf die Daten. Denken Sie wie ein Objekt (im OOP-Sinn), die 'Eigentümer' der Daten. Die Aufteilung der Daten in Segmente zu verbessern Parallelität (genannt 'Splitter' in DB-Kreisen) hilft bei großen Fällen (oder wenn die Daten auf langsamen Speicher).
Selbst wenn NUMA ist die erste mainstream -, haben Sie immer noch mehr und mehr Kerne pro NUMA-Zelle. Und ein großer Unterschied ist, dass eine Nachricht übergeben werden kann zwischen nur zwei Kerne, während eine Sperre muss gespült werden, aus dem cache auf den ALLE Kerne, die Begrenzung auf die inter-cell bus-Latenz (noch langsamer als der RAM-Zugriff). Wenn überhaupt, shared-state - /Schleusen immer mehr und mehr untragbar.
kurz.... Holen Sie verwendet, um message-passing-und server-Prozesse, es ist in aller Munde.
Bearbeiten: Wiederaufgreifen dieser Antwort möchte ich noch hinzufügen über einen Satz gefunden, auf Geht ' s-Dokumentation:
die Idee ist: wenn Sie einen block von Speicher zwischen threads gemeinsam genutzt werden, die auf typische Weise vermeiden Sie gleichzeitigen Zugriff ist die Verwendung eines lock zu vermitteln. Die Go-Stil ist, eine Botschaft mit dem Hinweis, ein thread greift nur auf den Speicher beim Empfang der Nachricht. Es beruht auf einem Maß der Programmierer Disziplin; aber sehr sauber aussehende code, die leicht redigiert, so ist es relativ einfach zu Debuggen.
der Vorteil ist, dass Sie nicht haben, zu kopieren, große Blöcke von Daten auf jede Nachricht, und nicht, um effektiv zu flush down-caches auf einige lock-Implementierungen. Es ist noch etwas früh zu sagen, ob der Stil führt zu höherer Leistung-designs oder nicht. (speziell da die aktuellen Go-Laufzeit ist etwas naiv auf thread-scheduling)
CAS
für x86 und Derivate)Einer Sache zu erkennen ist, dass die Erlang-concurrency Modell ist NICHT wirklich festlegen, dass die Daten in Nachrichten kopiert werden muss zwischen Verfahren, es besagt, dass das senden von Nachrichten ist der einzige Weg, um zu kommunizieren, und dass es keinen gemeinsamen Staat. Alle Daten unveränderlich ist, die ist fundamental sind, eine Implementierung kann sehr gut nicht kopieren Sie die Daten aber senden Sie einfach eine Referenz darauf. Oder kann eine Kombination beider Methoden. Wie immer, es gibt keine besten Lösung und es gibt trade-offs vorgenommen werden, wenn die Wahl, wie es zu tun.
Den STRAHL verwendet kopieren, außer für große Binärdateien, wo es sendet einen Verweis.
Erlang, alle Werte sind unveränderlich, es gibt also keine Notwendigkeit, um eine Nachricht zu kopieren, wenn es geschickt zwischen Prozessen, da es nicht geändert werden kann sowieso.
In Gehen, message passing, ist per Konvention - es gibt nichts, um zu verhindern, dass Sie senden jemand einen Zeiger über einen Kanal, dann das ändern der Daten zeigte auf, nur Konvention, also nochmals, es gibt keine Notwendigkeit, kopieren Sie die Nachricht.
Meisten modernen Prozessoren verwenden Varianten des MESI-Protokoll. Weil der gemeinsame Staat, Vorbei nur-lese-Daten zwischen verschiedenen threads ist sehr Billig. Geändert auf freigegebene Daten ist sehr teuer, weil alle anderen caches zu speichern, dass diese cache-Zeile muss es ungültig ist.
Also, wenn Sie nur-lese-Daten, es ist sehr Billig, Sie zu teilen zwischen threads nicht kopiert, sondern mit Nachrichten. Wenn Sie gelesen haben-vor allem Daten, kann es teuer werden, zu teilen zwischen den threads, teilweise, weil die Notwendigkeit zur Synchronisation des Zugriffs, und teilweise, weil die schreibt den cache gelöscht freundliches Verhalten der gemeinsam genutzten Daten.
Unveränderliche Datenstrukturen kann hier sinnvoll sein. Anstelle der änderung der tatsächlichen Datenstruktur, Sie machen einfach eine neue, Aktien die meisten der alten Daten, aber mit den Dingen, die geändert wurden, müssen Sie geändert werden. Mit einer gemeinsamen version von es ist Billig, da alle Daten, die unveränderlich ist, aber man kann immer noch updaten auf eine neue version effizient.
Beachten Sie, dass Ihre Fragen sind technisch nicht-sensical, weil message-passing können freigegebene Zustand, also muss ich davon ausgehen, dass du meine message passing mit tiefem kopieren zu vermeiden freigegebenen Zustand (wie Erlang derzeit tut).
Mithilfe gemeinsamer Staat wird eine viel schneller.
Entweder Ansatz kann verwendet werden.
Kopieren der cache-unfreundlich und daher zerstört Skalierbarkeit auf multicores, weil es sich verschlechtert Streit für die freigegebene Ressource wird Arbeitsspeicher.
Letztendlich Erlang-Stil message passing ist ausgelegt für die gleichzeitige Programmierung in der Erwägung, dass Ihre Fragen über Durchsatz-Leistung sind wirklich hat bei der parallelen Programmierung. Dies sind zwei ganz unterschiedliche Themen, und die überschneidungen zwischen Ihnen, winzig in der Praxis. Speziell, Latenz ist in der Regel genauso wichtig wie der Durchsatz in den Kontext der gleichzeitigen Programmierung und Erlang-Stil message passing ist eine großartige Möglichkeit, um die gewünschte Latenz-profile (d.h. konsistent niedrigen Latenzen). Das problem bei shared memory ist dann nicht so viel Synchronisation zwischen Leser und Schreiber, aber low-latency-memory-management.
Was ist ein großen Datenstruktur?
Eine Person, die groß ist, andere Personen zu klein.
Letzte Woche Sprach ich mit zwei Personen - eine person machte embedded-Geräte, die er benutzt das Wort
"groß" - ich fragte ihn, was es bedeutete - er sagen, über 256 KByte - später in der gleichen Woche ein
Mann redete über die Verteilung von Medien - er verwendet das Wort "großen", fragte ich ihn, was er
meinte - er dachte ein wenig und sagte "passt nicht auf eine Maschine" sagen 20-100 TBytes
In Erlang Begriffe "groß" gemeint sein könnte "passt nicht in den RAM" - also mit 4 GByte RAM
Datenstrukturen > 100 MByte sein könnte als groß - kopieren einer 500-MByte-Daten-Struktur
könnte ein problem sein. Das kopieren kleiner Daten-Strukturen (sagen < 10 MByte) ist nie ein problem in Erlang.
Wirklich großen Datenstrukturen (d.h. diejenigen, die nicht passen, auf einer Maschine) werden
kopiert und "gestreift" über mehrere Maschinen.
Also ich vermute du hast die folgenden:
Kleinen Daten-Strukturen sind kein problem, da Sie in kleinen Daten-Verarbeitung-Zeiten
schnell, das kopieren ist schnell und so weiter (nur weil Sie klein sind)
Big-data-Strukturen sind ein problem - weil Sie nicht passen auf eine Maschine - also das kopieren ist wichtig.
One-Lösung, die nicht vorgelegen hat, ist hier master-slave-Replikation. Wenn Sie eine große Daten-Struktur, Sie können replizieren von änderungen, die Sie an alle slaves, führen Sie das update auf Ihrer Kopie.
Dies ist vor allem interessant, wenn man will, zu skalieren, um mehrere Maschinen, die nicht selbst die Möglichkeit haben, Speicher freigeben, ohne sehr künstliche setups (mmap auf ein block-Gerät, das Lesen/schreiben von einem remote-computer das Gedächtnis?)
Einer Variante ist ein Transaktions-manager, dass man nett Fragen zur Aktualisierung der replizierten Daten-Struktur, und es wird sicherstellen, dass es erfüllt einen und nur update-Anfrage ausgefš Uhrt werden. Dies ist mehr der mnesia-Modell für master-master-Replikation der mnesia-Tabelle-Daten, die sich als "große Daten-Struktur".
Im moment das problem ist ja, dass die Verriegelung und die cache-Zeile, die Kohärenz könnte so teuer sein wie das kopieren einer einfacheren Datenstruktur (z.B. ein paar hundert bytes).
Meisten der Zeit eine clever geschrieben, neue Multithread-Algorithmus, der versucht zu beseitigen, die meisten sperren werden immer schneller - und viel schneller mit modernen lock-free data structures. Vor allem, wenn Sie gut gestaltet-cache-Systeme wie Suns Niagara-chip-level-multi-threading.
Wenn Ihr system/problem ist nicht leicht gebrochen nach unten in wenige und einfache Daten zugreift, dann haben Sie ein problem. Und nicht alle Probleme können gelöst werden durch message-passing. Das ist, warum gibt es immer noch einige Itanium-basierten super-Computer verkauft, weil Sie terabyte shared RAM und bis zu 128 CPU ' s arbeiten, auf die gleichen gemeinsam genutzten Speicher. Sie sind eine Größenordnung teurer als ein mainstream-x86-cluster mit der gleichen CPU-Leistung, aber Sie brauchen nicht zu brechen-down Ihrer Daten.
Anderen nicht erwähnten Grund so weit ist, dass Programme viel einfacher zu schreiben und zu pflegen, wenn Sie die Verwendung von multi-threading. Message-passing-und shared-nothing-Ansatz macht es noch mehr wartbar.
Als ein Beispiel, Erlang wurde nie entwickelt, um die Dinge schneller, sondern stattdessen eine große Anzahl von threads, um die Struktur komplexer Daten und Ereignis fließt.
Ich denke, das war einer der wichtigsten Punkte in das design. In der web-Welt von google, die Sie in der Regel kümmern sich nicht um die Leistung - solange er parallel in der cloud. Und mit dem message-passing, die Sie im Idealfall können Sie einfach weitere Computer hinzufügen, ohne den Quellcode ändern zu müssen.
In der Regel message-passing-Sprachen (dies ist besonders gut in erlang, da es unveränderliche Variablen) optimieren entfernt, die eigentlichen Daten kopieren zwischen den Prozessen (natürlich lokale Prozesse, nur: Sie wollen zu denken, dass Ihre Netzwerk-Verteilungs-Muster mit bedacht), also, das ist nicht viel ein Problem.
Den anderen gleichzeitigen Paradigma is STM, der software transactional memory. Clojure die ref ' s sind immer eine Menge Aufmerksamkeit. Tim Bray hat eine gute Serie erforschen erlang und clojure gleichzeitige Mechanismen
http://www.tbray.org/ongoing/When/200x/2009/09/27/Concur-dot-next
http://www.tbray.org/ongoing/When/200x/2009/12/01/Clojure-Theses