Create your own awesome maps

Even on the go

with our free apps for iPhone, iPad and Android

Get Started

Already have an account?
Log In

Parallel .NET by Mind Map: Parallel .NET
0.0 stars - reviews range from 0 to 5

Parallel .NET

Ausgangslage

Geschichte

im Schnitt alle 2 Jahre höhere CPU-Leistung

von neuer Hardware profitierte auch die Software

Grenze bei 3-4 Ghz erreicht, Kühlung wird schwierig, nach Entwicklungskurve müsste die Leistung heute bei ca. 50Ghz liegen

Wandel

Multi Core, Multi Processing (OS), Multi-Threading

Mehrere CPUs auf einem Chip

Anpassungen an den Programmen, wenn man von der Leistung profitieren will

Parallel Programmierung wird wichtiger

selbst programmieren

Multi-Threading

bedeutet mehrere Prozessoren oder Kerne arbeiten gleichzeitig

Einführung

Amdahl's Gesetz

Programm was parallel auf N Prozessoren läut, ist nicht automatisch N mal so schnell., das gesamte Programm kann nicht parallel laufen, ein Teil läuft nach wie vor sequentiell ab, Textdateien, Variablen initialisieren, Sp = T* / Tp, Sp Speedup, T* Optimale seq. Ausführungszeit, Tp Optimale parallele Ausführungszeit, Erhöhung der Anzahl Proz. bringt nicht unbedingt viel, weil die seq. Abhängigkeit es nicht zulässt, Abhängigkeit zum OS, Threaderzeugung kostet Zeit, werden seq. erzeugt, Zerstörungszeit der Threads, Kontext-Switch, Abgleich Cache-Inhalte, Verlangsamung des OS Schedulers durch andere Threads, Granularität (Performance) der parallelen Teileinheiten, Synchronisierung, Best Practices, ThreadPool, zu lösendes Problem lässt paralleles Arbeiten nicht zu

Wenn die Zeit, die ein Thread arbeitet sehr viel länger ist, als die Erzeugungszeit des Threads, dann ist alles in Ordnung

Ausführungszeit nach Amdahl, T = T* + Tp / p (Formel ohne Zeit für Threaderzeugung)

Wenn der Thread nur sehr wenig zu tun hat, dann kann die Parallel-Ausführungszeit langsamer werden, als die sequentielle Ausführungszeit

Dead Locks

entsteht wenn ein Thread ein Objekt in Benutzung hat und nicht mehr frei gibt, welches ein andere Thread benutzen will, wichtig:, Sperr-Reihenfolge einhalten, Backoff-Strategie

Synchronisierung beinhaltet immer die Gefahr eines "Deadlocks"

Laufzeiterscheinung, es kann den statischen Code nicht unbedingt angesehen werden

Unterschiedliche Rechner, erzeugen unterschiedliches Deadlock-Verhalten, Abhängig von Anzahl CPU-Kerne und Prozesse

Deadlocks sind kaum zu debuggen, vielleicht mal in der Zukunft, Alternative Log4Net oder Enterprise Library

Data Races

entstehen, wenn mehrere Treads auf gleiche Ressourcen (Variable) schreibend zugreifen

Ergebnis nicht vorhersehbar, der schnellere Thread gewinnt, bzw. verliert

sind im Code nicht sofort erkennbar, Es kann ein paar mal gut gehen

Es hängt von der Anzahl der parallelen Threads ab

Compiler kann keine Fehlermeldung ausgeben

Nebenläufiger Zugriff auf eine Variable

Parallelisierungstechniken

Normale Threads

Thread Pools

OpenMP

MPI

PPL

Task Parallel Library (TPL)

Parallel Pattern Library (PPL)

Ausgangslage

Neue Bibliotheken sollen den direkten Zugriff of die OS-Thread vereinfachen

Compiler Support ab VS 2010

Zwei Welten, Native C++ Code, Benutzt PPL, Mit Compiler Switch /clr nicht erlaubt, Managed Code, VB, C#, F#, C++/CLI, Benutzung der Task Parallel Library (TPL)

Vorgehensweise

header, #include<ppl.h>

namespace, using namespace Concurrency;

Tasks

sind kleine Ausführungseinheiten

Task-Gruppen

Mehrere Tasks zusammengefasst

Können bis zu 10 Tasks pro Gruppe ausführen

Ablauf, task_group erzeugen, mit run() starten, Aufgabe im Haupt-Thread starten, mit wait() warten (Syncronisierung), Prüfen ob Schleifen paralleisiert werden können

Agenten

C+ Template Library

In-process message passing

Ideal für fein granulare Datenfluss-Aufgaben, Dataflow, Piplining

bauen auf Concurrency Runtime auf

Einsatzzweck, Viele Operationen die miteinander kommunizieren sollen/müssen, Erzeugung von Daten-Pipelines, Daten-Netzwerken, Aufgabentrennung durch Komponenten, Weitergabe von Ergebnissen, Weniger geeignet für Performance-Optimierung

Ablauf, Message passing, send, receive, send, Message landet in einem Buffer, receive, holt die Nachrichten aus dem Buffer

Synchronisierung

critical_section, critical_section object, lock, unlock, Vorsicht mit worst-case lock, lock(), Anweisung, unlock(), lock/unlock ist Zeitaufwendig, InterlockedIncrement verwenden, nicht die optimalste Lösung, Performancetests machen

reader_writer_lock, mehrere lesen, einer schreibt

event

Beispiele

Task Parallel Library (TPL)

Einführung

Klasse, System.Threading.dll - Referenz, System.Threading.Parallel

Granularität, Arbeitseinheit darf nicht zu klein sein, je mehr Prozessoren, desto grösser die Thread-Erzeugungszeit

setzt auf ThreadPool als Standard-Scheduler auf

Hill-climbing Methoden für die optimale Thread-Anzahl

interne Verwendung von SpinWait und SpinLock zur Synchronisierung

Task stealing, Tasks anderen Threads zuordnen

Schleifen

Methoden, Parallel.For, Parallel.ForEach

Ablauf, Aufteilung in kleine Bröckchen, Zuteilung an Thread, wenn dieser die aktuelle Aufgabe komplett erledigt hat

Vorsicht, Schleifendurchläufe müssen unabhängig voneinander sein, Unausgewogene Schleifen, Ausführung basierend auf index-Variable mit if, switch etc., Algorithmus optimieren, mehrere Threads schreiben auf die gleiche Variable (führt zu Rechenfehlern), Synchronisieren mit, lock, bei integer Interlocked.Increment, vor kleinen Arbeitseinheiten, Disk-IO Parallelisierung, Abhängig von der Hardware, lohnt erst ab Solid State Disks, User Interface, Bei Output-Daten, Bildbearbeitung, Einfache Algorithmen nicht parallelisieren

Aggregationen, Zusammenfassung von Ergebnissen, Meistens Locking erforderlich, Ablauf, Vor der Schleife Laufzeitvariable, ParallelLoopState und ThreadLocalState initialsieren, Schleife abarbeiten (LocalState benutzen), Nach der Schleifenabarbeitung Aggregation der Ergebnisse (Achtung: Locking), Rechenungenauigkeit

Code-Bereiche parallelisieren

Demos.zip Demo7

Methode, Parallel.Invoke, aktuell bis 10 Aufrufe möglich

Vorsicht, Gleichzeitiger Zugriff auf die gleichen Daten (schreibend), erst Nachdenken, Seiteneffekte bedenken

Task

DemosTPL4 Demo 10,11,12 (VS 2008) Demos2010.zip Demo2010_Task

Task.Factory.StartNew, TaskFactory-Klasse, FromAsync, ContinueWith, ContinueWhenAll, ContinueWhenAny

Abbruch, t1.Cancel(), Auf Threadsicheren Code achten (siehe Demo10, statische Rückgabevariable)

warten, Task.WaitAll(t1, t2), t1.Wait()

Beendigung, Prüfbar mit t1.IsCompleted, Cancel nicht feststellbar

Eigenschaften, Synchronisierung, Abbrechen von Einheiten, Benutzung wie normale Threads

Task<TResult>

DemoTPL4.zip Demo13, 14 (VS 2008) Früher Future-Klasse Demos2010.zip Demo2010_Task2

Task<TResult>.Factory.StartNew

Ermöglicht asynchrone Berechnung, Abruf with resultVar.Result

lock weiterhin von Bedeutung für Threadsicheren Programmcode

Properties der Result-Variable, result.Result, wenn Ergebnis noch nicht berechnet, wartet Result bis das Ergebnis berechnet ist., kann auch zur Bremse werden, wenn die Berechnungen sehr lange laufen, result.IsCanceled, result.IsCompleted, ContinueWith, Ausführungen nach Berechnungen (result.Result)

Verwendbar im UI, WinForms, WPF, Bei asynchronen Aufrufen werden die EventHandler nicht blockiert, Alte Regel = neue Regel, laufen im STA, Nur der Thread darf auf Controls zugreifen, der sie erzeugt hat, Ab .NET 2.0 Exceptions nur im Debug-Modus, Synchronisierung mit Controls, WinForms, control.InvokeRequired, Test ob richtiger Thread, control.BeginInvoke, Umschalten auf den richtigen Thread, WPF, control.Dispatcher.VerifyAccess bzw. CheckAccess, Test, control.Dispatcher.Invoke, Umschalten auf richtigen Thread

TaskScheduler

Abstrakte Basisklasse, interessant für Prioritätsverwaltung

Neue WorkStealing-Queues in ThreadPools

Zugriff auf das User Interface, TaskSheduler.FromCurrentSyncronizationContext(), notwendig für ContinueWith, Async-Berechnung, Fortführung mit ContinueWith (im korrekten UI-Thread), früher

Fehlerbehandlung

Concurrent Exceptions, Thread läuft bis zu einem Safepoint bevor er abgebrochen werden kann, paralelle Anwendungen können mehrere Exceptions werfen, oft verarbeitet ein anderer Thread diese Exception, bei einen Fehler werden alle Threads angehalten, wenn der nächste Safepoint des jeweiligen Threads erreicht wurde, Weitere Exceptions während des Abbruchs möglich

komplex im parallelen Code

System.Threading.AggregateException, sammelt alle Fehlermeldungen, wenn alle Threads stehen, wird diese neu geworfen, war bisher nicht möglich, einfacher try/catch block um die parallel-Verarbeitung reicht jetzt aus, Abfrage aller Fehler über die InnerExceptions - Auflistung, Klassen die diese Exception werfen, Parallel, Task, Task<TResult>, Parallel LINQ Abfragen (AsParallel)

Synchronisierung

Barrier

CountDownEvent

LazyInit<T>, Variable hat zusätzlich Properties, IsInitialized, Mode, Value, Erzeugte Objekt<T>

ManualResetEventSlim

SemaphoreSlim

SpinLock

SpinWait

WriteOnce<T>, erzwingt die einmalige Initialisierung, weitere Initialisierung wirft Exception, bisher nur mit readonly im Constructor

Collections, ConcurrentQueue, ConcurrentStack, Namespace System.Treading.Collections, Prüfbar mit TryPop(out val), BlockingColle

PLINQ

Ausgenommen sind, Linq to SQL, Linq to Entities, wenn PLINQ der Meinung ist, dass der sequenzielle Ausführungsmodus besser ist

Code-Lesbarkeit wird verbessert

Ausführung mit AsParallel(), nutzt alle verfügbaren Prozessoren, Where, OrderBy, Select

andere Rückgabetypen, aus OrderedEnumerable<T> wird OrderedParallelQuery<T>

Verzögerte Ausführung wie bei LINQ

Verarbeitungsvarianten, WithMergeOptions(opt), FullyBuffered, alle Thread werden vollständig abgearbeitet, Reihenfolge bleibt erhalten, NotBuffered, verarbeitete Daten werden sofort bereit gestellt, Reihenfolge der Daten nicht gewährleistet, AutoBuffered, Verarbeitung hängt von der Implementierung des Operators ab

Abbruch, Abbruchmarke setzen, var cts = new CancellationTokenSource(), WithCancellation(cts), Abfrage mit, cts.IsCancellationRequested, so selten wie möglich abfragen, Ausnahme, OperationCanceledException

Schwachstellen, Bei Schleifen auf Threadsicherheit achten, AsOrdered() kann zu Geschwindigkeitseinbussen führen, Abbruch einer Abfrage ist trickreich, IsCancellationRequested, zu viel abfragen verringert Performance, zu wenig, verlangsamt die Beendigung

Best Practices

DemosTPL3.zip PrimeStd, PrimePar

zuerst prüfen ob Algorithmus optimiert werden kann, bevor parallelisiert wird.

Verschachtelte Schleifen, Nach Möglichkeit die äussere Schleife parallelisieren, Bessere Performance, Parallelisieren der inneren Schleife sollten Sonderfälle bleiben

Bei kleinen und mittleren Arbeitseinheiten, ParallelOptions, Festlegen wie viele Kerne max benutzt werden dürfen, in früheren Beta-Versionen, PLINQ_DOP, Enviroment.SetEnviromentVarialbe("PLINQ_DOP", "2", EnviromentVariableTarget.Process), zurücksetzen mit String.Empty-Wert, EviromentVariableTarget, Machine, Process, User, var options = new ParallelOptions { MaxDegreeOfParallelism = 2 }, MaxDegreeOfParallelism > Prozessoren * Kerne, mehr Threads als gleichzeitig benutzt werden können, Vorteil: wartet ein Thread, kann ein anderer dafür laufen

User Interface, Anfallende Output-Daten sammeln, Synchronisierung so wenig wie möglich, UI-Zugriff mittels Invoke oder BeginInvoke so selten wie möglich

Beispiele

bis DemoTPL5.zip sind die Beispiele in VS2008

Pattern & Practice Parallel Programming

Building parallelized apps with .NET and VS