Unterschied zwischen paralleler und gleichzeitiger Programmierung?

44

Bei der gleichzeitigen Programmierung werden üblicherweise zwei Begriffe verwendet, nämlich gleichzeitig und parallel.

Einige Programmiersprachen wie Java fordern Unterstützung für parallele Programmierung .

Bedeutet dies, dass parallele und gleichzeitige Programmierung tatsächlich unterschiedlich sind?

nish1013
quelle
10
Ja, gleichzeitige und parallele Programmierung sind unterschiedlich. Beispielsweise können zwei Threads (oder Prozesse) durch Kontextwechsel gleichzeitig auf demselben Core ausgeführt werden. Wenn die beiden Threads (oder Prozesse) auf zwei verschiedenen Kernen (oder Prozessoren) ausgeführt werden, besteht Parallelität. Im ersten Fall (Parallelität) ist die Parallelität also nur "virtuell", während Sie im zweiten Fall eine echte Parallelität haben. Daher ist jedes parallele Programm gleichzeitig, aber das Gegenteil ist nicht unbedingt der Fall.
Massimo Cafaro
1
Sei hier vorsichtig. Sie können das gleiche Ergebnis entweder durch Sprachunterstützung (dh Erweiterung einer Sprache mit neuen Konstrukten) oder durch Verwendung eines einfachen Ansatzes (z. B. durch Verwendung einer Bibliothek, wie im Fall von MPI und OpenMP) erzielen. Auf jeden Fall kann bei aktuellen Mehrkernprozessoren und Betriebssystemen mit SMP-Unterstützung ein Programm, das auf alten Einkernprozessoren gleichzeitig ausgeführt wird, parallel ausgeführt werden, wenn das Betriebssystem die Ausführungsthreads des Programms auf verschiedenen Kernen plant. Daher ist der Unterschied heutzutage ein wenig "verschwommen".
Massimo Cafaro
3
Was Sie für eine Lichtgeschwindigkeits-Latenzzeitkonstante verwenden. In der Parallelität geben Sie vor, die Lichtlatenz beträgt einen Taktzyklus. Parallel dazu nehmen Sie an, dass sich ein Server nebenan befindet. Bei Distributed nehmen Sie an, dass sich ein Server auf dem Mars befindet.
1
Robert Harper erörtert das Problem in zwei Blog-Posts: "Parallelität ist keine Parallelität" und "Parallelität und Parallelität, erneut besucht" , die Sie möglicherweise überprüfen möchten.
Basil

Antworten:

26

Unterscheiden Sie Parallelität (Verwenden zusätzlicher Recheneinheiten, um mehr Arbeit pro Zeiteinheit zu erledigen) von Parallelität (Verwalten des Zugriffs auf gemeinsam genutzte Ressourcen). Unterrichten Sie zunächst Parallelität, da dies einfacher ist und dazu beiträgt, eine nicht sequenzielle Denkweise zu entwickeln.

Aus "Sophomoric - Einführung in die Parallelität und Parallelität von gemeinsamem Speicher" von Dan Grossman (Version vom 16. November 2013)

Raphael
quelle
21

Lassen Sie mich zusätzlich zu Nishs Antwort Simon Marlows Buch über parallele und gleichzeitige Programmierung in Haskell oder sein kürzeres Tutorial empfehlen . Sie beantworten Ihre erste Frage aus der Sicht von Haskell, sodass sie für theoretisch geneigte Leser besser geeignet sind (Haskell ist eine rein funktionale, faule Programmiersprache, die der Mathematik viel näher steht als andere Sprachen).

Zitat von dort:

In vielen Bereichen sind die Wörter parallel und gleichzeitig Synonyme; Nicht so in der Programmierung, wo sie verwendet werden, um grundlegend unterschiedliche Konzepte zu beschreiben.

Ein paralleles Programm verwendet eine Vielzahl von Computerhardware (z. B. mehrere Prozessorkerne), um die Berechnung schneller durchzuführen. Verschiedene Teile der Berechnung werden an verschiedene Prozessoren delegiert, die gleichzeitig (parallel) ausgeführt werden, sodass die Ergebnisse möglicherweise früher geliefert werden, als wenn die Berechnung nacheinander durchgeführt worden wäre.

Im Gegensatz dazu ist Parallelität eine Programmstrukturierungstechnik, bei der es mehrere Steuerungsthreads gibt. Die Threads der Steuerung werden normalerweise "zur gleichen Zeit" ausgeführt. Das heißt, der Benutzer sieht ihre Effekte ineinander verschachtelt. Ob sie tatsächlich zur gleichen Zeit ausgeführt werden oder nicht, ist ein Implementierungsdetail. Ein gleichzeitiges Programm kann auf einem einzelnen Prozessor durch verschachtelte Ausführung oder auf mehreren physischen Prozessoren ausgeführt werden.

Ich empfehle, den Rest des Tutorials zu lesen (S. 4), aber lassen Sie mich den Rest dieses Abschnitts zitieren, da er beide Programmierparadigmen mit quantitativen und qualitativen Merkmalen von Programmen wie Effizienz, Modularität und Determinismus verbindet.

Während bei der parallelen Programmierung nur die Effizienz im Vordergrund steht, geht es bei der gleichzeitigen Programmierung um die Strukturierung eines Programms, das mit mehreren unabhängigen externen Agenten (z. B. dem Benutzer, einem Datenbankserver und einigen externen Clients) interagieren muss. Parallelität ermöglicht, dass solche Programme modular sind; Der Thread, der mit dem Benutzer interagiert, unterscheidet sich von dem Thread, der mit der Datenbank kommuniziert. In Abwesenheit von Parallelität müssen solche Programme mit Ereignisschleifen und Rückrufen geschrieben werden. In der Tat werden Ereignisschleifen und Rückrufe häufig auch dann verwendet, wenn Parallelität verfügbar ist, da die Parallelität in vielen Sprachen entweder zu teuer oder zu schwierig ist verwenden.

Der Begriff "Threads of Control" ist in einem rein funktionalen Programm nicht sinnvoll, da keine Effekte zu beobachten sind und die Auswertungsreihenfolge keine Rolle spielt. Parallelität ist also eine Strukturierungstechnik für effektiven Code. In Haskell bedeutet dies Code in der E / A-Monade.

Eine verwandte Unterscheidung besteht zwischen deterministischen und nicht deterministischen Programmiermodellen. Ein deterministisches Programmiermodell ist eines, bei dem jedes Programm nur ein Ergebnis liefern kann, wohingegen ein nicht deterministisches Programmiermodell Programme zulässt, die je nach Aspekt der Ausführung unterschiedliche Ergebnisse haben können. Gleichzeitige Programmiermodelle sind notwendigerweise nicht deterministisch, da sie mit externen Agenten interagieren müssen, die zu unvorhersehbaren Zeiten Ereignisse verursachen. Der Nichtdeterminismus hat jedoch einige bemerkenswerte Nachteile: Programme werden erheblich schwieriger zu testen und zu begründen.

Für die parallele Programmierung möchten wir möglichst deterministische Programmiermodelle verwenden. Da es nur darum geht, die Antwort schneller zu finden, möchten wir unser Programm nicht schwieriger machen, in diesem Prozess Fehler zu beheben. Deterministische Parallelprogrammierung ist das Beste aus zwei Welten: Das sequentielle Programm kann getestet, getestet und begründet werden, aber das Programm wird schneller ausgeführt, wenn Prozessoren hinzugefügt werden. In der Tat implementieren die meisten Computerprozessoren selbst deterministische Parallelität in Form von Pipelining und mehreren Ausführungseinheiten.

Es ist zwar möglich, parallele Programme unter Verwendung von Parallelität zu programmieren, dies ist jedoch häufig eine schlechte Wahl, da Parallelität den Determinismus beeinträchtigt. In Haskell sind die parallelen Programmiermodelle deterministisch. Es ist jedoch zu beachten, dass deterministische Programmiermodelle nicht ausreichen, um alle Arten von parallelen Algorithmen auszudrücken. Es gibt Algorithmen, die vom internen Nichtdeterminismus abhängen, insbesondere Probleme, bei denen ein Lösungsraum durchsucht wird. In Haskell kann diese Klasse von Algorithmen nur unter Verwendung von Parallelität ausgedrückt werden.

Nickie
quelle
20

Parallelität und Parallelität unterscheiden sich in den von ihnen gelösten und verursachten Problemen, sind jedoch nicht unabhängig voneinander.

Parallelität

Zwei Tasks gleichzeitig ausführen bedeutet, dass einzelne Schritte beider Tasks verschachtelt ausgeführt werden. Wenn Sie die Parallelität ignorieren, können Sie davon ausgehen, dass zu jedem Zeitpunkt nur eine Anweisung ausgeführt wird, Sie haben jedoch (a priori) keine Garantie, welche Task zum Ausführen des nächsten Schritts berechtigt ist.

Dies ist in gewisser Hinsicht nützlich:

  • Übersichtliche Programmierung unabhängiger Aufgaben in einem Programm.
  • Ermöglicht den Umgang mit IO während des Rechnens (zB in der GUI).
  • Ermöglicht die gleichzeitige Ausführung von mehr als einem Programm (Parallelität auf Betriebssystemebene).

Einige der wichtigsten Herausforderungen sind:

  • Datenkonsistenz aufrechterhalten.
  • Vermeiden Sie Deadlocks und Livelocks .
  • Bestimmen Sie die genaue Semantik von gleichzeitigen Prozessen.
  • Bestimmen Sie statische Eigenschaften, die die Richtigkeit sicherstellen.

Parallelität

Ausführen von zwei Aufgaben parallel bedeutet , dass Anweisungen ausgeführt werden zur gleichen Zeit . Dies ist hauptsächlich nützlich für:

  • Verbessern Sie den Systemdurchsatz, indem Sie Programme parallel ausführen (z. B. auf Mehrkernsystemen).
  • Verbessern Sie die Laufzeit einzelner Programme, indem Sie mehrere CPUs gleichzeitig verwenden.
  • Nutzen Sie IO auf vielen Rechnern (zB verteilten Datenbanken).

Zu den wichtigsten Herausforderungen gehören:

  • Partitionsprobleme, die Algorithmen ermöglichen und entwickeln, die Parallelität anwenden können.
  • Minimieren Sie Abhängigkeiten und Kommunikation zwischen den Recheneinheiten.
  • Alle Probleme, die durch die Parallelität entstehen: Zumindest aus Sicht des Speichers sehen parallele Programme aufgrund der Serialisierung der Speicherzugriffe wie parallele aus.
  • Beschäftige dich mit suboptimaler Hardware-Unterstützung.

Siehe auch diese Frage zur Unterscheidung von parallelem und verteiltem Computing.

Raphael
quelle
4

Eine etwas idealisierte Antwort, vielleicht ...

  • Parallelität ist eine Eigenschaft, wie ein Programm geschrieben wird . Wenn ein Programm mit Konstruktionen wie Forks / Joins, Sperren, Transaktionen, atomaren Compare-and-Swap-Operationen usw. geschrieben wird, erfolgt dies gleichzeitig.

  • Parallelismus ist eine Eigenschaft , wie ein Programm ausführt . Wenn ein Programm auf mehr als einer Recheneinheit gleichzeitig ausgeführt wird, wird es parallel ausgeführt.

John Wickerson
quelle
1

Es gibt viele Antworten darauf, aber es kann verwirrend sein. Ich mag es so zu denken, und vielleicht hilft es ?:

Gleichzeitige Programmierung ist Code, der sich nicht um die Ausführungsreihenfolge kümmert. Java ist eine schlechte Sprache für die gleichzeitige Programmierung, aber es gibt Bibliotheken und Frameworks, die helfen. JavaScript ist eine hervorragende Sprache für die gleichzeitige Programmierung, und es ist oft schwierig, wenn Sie etwas schreiben möchten, das nicht gleichzeitig abläuft (z. B. wenn Sie die Ausführungsreihenfolge erzwingen möchten). Die gleichzeitige Programmierung eignet sich hervorragend für die ereignisgesteuerte Programmierung (wobei die Ausführungsreihenfolge von Ereignis-Listenern bestimmt wird, z. B. von Code, der in Ihrem Browser ausgeführt wird, wenn Sie auf eine Schaltfläche klicken oder in ein Feld eingeben).

Ein Beispiel wäre das Erstellen von hundert HTTP-Anforderungen. In NodeJS besteht die einfachste Lösung darin, alle 100 Anforderungen gleichzeitig mit einer Rückrufmethode zu öffnen. Wenn die Antworten zurückkommen, wird jedes Mal eine Methode ausgeführt. Das ist gleichzeitige Programmierung. In Ruby besteht die einfachste (häufigste) Lösung darin, eine Anfrage zu öffnen und die Antwort zu verarbeiten, die nächste Anfrage zu öffnen und die Antwort zu verarbeiten usw. Bei vielen Anfragen ist NodeJS schneller zu erledigen, obwohl dies erforderlich ist Vermeiden Sie es, den Server zu hämmern oder Ihre ausgehenden Verbindungen zu maximieren (aus Versehen einfach). Sie können den Ruby gleichzeitig schreiben, aber es ist nicht so, wie der meiste Ruby-Code geschrieben ist, und es tut ein wenig weh, es zu tun.

Parallele Programmierungist Code, der gleichzeitig in mehreren Threads oder Prozessen ausgeführt werden kann. Auf diese Weise können Sie die Leistung optimieren, indem Sie den Code auf mehreren CPUs ausführen (häufig auch auf mehreren Computern, wie Sie es bei Akka tun könnten). Da NodeJS nicht mit mehreren Threads arbeitet und keine parallele Ausführung stattfindet, müssen Sie sich keine Gedanken über das Schreiben von threadsicherem Code machen (und der meiste JavaScript-Code, den ich gesehen habe, ist nicht threadsicher). In Java ist die parallele Programmierung sehr stark integriert, auch wenn die Sprache die gleichzeitige Programmierung nicht zum normalen Muster macht, und Sie müssen sich häufig um die Thread-Sicherheit kümmern. Wenn Sie eine Website in Java schreiben, wird diese normalerweise in einem Container ausgeführt, der jede Anforderung in einem separaten Thread im selben Speicher ausführt.


Einige der oben genannten Punkte hängen vom Umfang und den Grenzen ab, über die Sie sprechen. Ich arbeite an Websites. Der meiste Java-Code, den ich sehe, ist keine gleichzeitige Programmierung. Sicher, wenn Sie ausreichend verkleinern, ist die Reihenfolge, in der die Kundenanforderungen eingehen, nicht wichtig. Wenn Sie jedoch weiter hineinzoomen, wird die Reihenfolge, in der die Dinge ausgeführt werden, durch den Code vorgegeben. Der Code ist jedoch so geschrieben, dass die Anforderungen parallel mit vielen gemeinsam genutzten Objekten ausgeführt werden können, die threadsicher sein müssen.

In der Zwischenzeit ist der meiste JavaScript-Code, den ich sehe, gleichzeitig: Er ist so geschrieben, dass die Ausführungsreihenfolge auf vielen Ebenen unwichtig ist. Es wurde jedoch nicht geschrieben, um die parallele Ausführung im gemeinsam genutzten Speicher zu unterstützen. Natürlich können Sie denselben Code über mehrere Prozesse hinweg parallel ausführen, aber die Objekte werden nicht gemeinsam genutzt, sodass es sich nicht um eine sinnvolle Parallelprogrammierung handelt.

Zum besseren Verständnis gefallen mir die Abbildungen in der oberen Antwort auf diese Frage hier: https://www.quora.com/Was- sind- die- Unterschiede- zwischen- paralleler- gleichzeitiger- und- asynchroner- Programmierung?

Jun-Dai Bates-Kobashigawa
quelle