Arten der Aufgabenteilung

Man unterscheidet primär zwischen Aufteilung der einzelnen Arbeitsschritte oder der Aufgaben.
Beim Kochen kann beispielsweise nach Zubereitung der einzelnen Gerichten aufgeteilt werden, oder nach den einzelnen Aufgaben in der Erstellung eines Gerichts.
4 Köche sollen 100 Burger zubereiten. Anhand dieses Beispiels wird der Unterschied anschaulich erklärt.

Datenparallelismus

Jeder Koch bereitet 25 Burger zu.

Eventuell kann es hier zu Wartezeiten bei den geteilten Ressourcen kommen.
Diese Aufteilung ist robuster, da Ausfälle kompensiert werden können. Jeder Koch ist in der Lage die Aufgabe alleine zu beenden und kann eventuell die Arbeit eines anderen zu vervollständigen.

Aufgabenparallelismus


Jeder Koch hat eine spezielle Aufgabe die er für alle 100 Burger ausführt. Beispielsweise die Brötchen oder das Fleisch vorzubereiten.
Diese Art der Aufteilung bietet sich an, wenn es für die einzelnen Aufgaben Optimierungsstrategien gibt, bzw. Vorteile entstehen mehrere auf einmal zu bearbeiten. Eventuell können Rechenergebnisse wiederverwendet werden.
Allerdings können Fehler in einem Produktionsschritt nicht ausgeglichen werden.

Prozess

Jeder Prozess besitzt:

  • Programm
  • Heap-Speicher
  • Stack-Speicher
  • Prozessregister / Stackpointer / Program Counter
  • Liste verwendeter Ressourcen

Mehrere Prozesse können gleichzeitig ausgeführt werden (Multitasking)

Fork

Forken ist das Erstellen eines neuen Prozess, wobei ein aktiver Prozess eine vollständige Kopie von sich selbst anfertigt.
Man spricht auch von einem “Kindprozess”.
Die Erstellung ist sehr Zeitintensiv (~20ms), da direkt mit dem Betriebssystem kommuniziert werden muss.
Dies ist bei längeren Aufgaben sinnvoll, wenn nicht jeder zwischenschritt direkt von dem vorherigen abhängt.
Das Ergebnis des Kindprozesses muss übertragen werden.

Parallel vs Nebenläufig

Gleichzeitige Ausführung mehrerer Prozesse macht sie nebenläufig.
Man spricht nur von Parallelität wenn sie völlig isoliert von einander arbeiten und sich keine Ressourcen teilen müssen.

Ressourcen

  • RAM
  • ROM
  • Maus
  • Tastatur
  • Dateien
    Zugriff auf diese wird vom Betriebssystem verwaltet.

Pipes

Sind eine Möglichkeit um mit laufenden Programmen zu kommunizieren. Eine Pipe hat ein schreibendes und ein lesendes Ende.
Beide Enden sind gepuffert und werden blockierend verwaltet, sodass keine Daten verloren gehen. Wenn kein Platz im Puffer verfügbar ist wird der Eingang blockiert.
Man spricht von einer “Broken Pipe” wenn nicht beide Enden verwendet werden, also Daten in einer Pipe landen die nie gelesen werden.

Scheduler

Ist Teil des Betriebssystems und kümmert sich um die Verwaltung von Prozessen. Dabei sind einige Informationen über die Prozesse relevant:

  • OS-Syscalls die beschreiben, ob der Prozess in seinem aktuellen Zustand unterbrechbar ist.
  • Ressourcen:
    Eine Liste an verwendeter Dateien
  • Programm-Counter:
    Aktuelle Stelle der Ausführung (Lesezeichen in der .exe)
  • Register
  • RAM:
    Verwendete Bereiche im Speicher
  • Stackpointer
  • User priviliges

Threads

Auch “Lighweight-Processes” genannt haben sehr ähnliche Eigenschaften wie ein Prozess.
Größter Unterschied ist, dass Threads sich Heap-Speicher Teilen, während jeder Prozess seinen eigenen Heap besitzt.
Sie sind leichter zu erstellen und haben die Möglichkeit in dedizierte Wartezustände überzugehen. Wenn ein Thread nicht weiter rechnen kann, da eine benötigte Ressource belegt ist oder er von einer Kontrollstruktur geblockt wird, erhält er die Markierung “Waiting”. So kann der Scheduler schneller prüfen ob es sinnvoll ist dem Thread Rechenzeit zuzuteilen.

Synchronisation

Der Einsatz mehrerer Threads sollte möglichst wenig Überschneidung in den verwendeten Ressourcen haben. Um Race-Conditions zu vermeiden gibt es viele Möglichkeiten Threads zu synchronisieren.
Dabei wird eine Markierung verwendet die die aktuelle Verwendung signalisieren und Andere einschränken oder bis zur erneuten Freigabe aussperren.
Unterschiedliche Kontrollstrukturen bieten hier Möglichkeiten verschiedenste Verhaltensweisen zu implementieren.

Mutex

Kurz für ”mutual exclusion” beschreibt mehrere Instanzen die sich gegenseitig vom Zugriff auf Ressourcen ausschließen können. Die Implementierung kann mittels unterschiedlicher Kontrollstrukturen erfolgen.

Tests

Automatisierte Tests von Nebenläufigkeit ist quasi nicht-existent/unmöglich

Optimierung

Bei der Parallelisierung von Teilen des Systems ist der maximal erzielbare Speedup vom Anteil der parallelisierbaren Operationen begrenzt. Amdahls Law beschreibt diesen Zusammenhang genauer.
Amdahl