StructorizerHandbuch DE

PARALLEL

Was ist ein Parallel-Abschnitt?

Das PARALLEL-Element dient zur Darstellung einer Gruppe von nebenlÀufigen Threads, die beim Eintritt in das PARALLEL-Element gestartet werden und auf deren Beendigung am Ende des PARALLEL-Elements gewartet wird, d. h. das PARALLEL-Element wird erst verlassen, nachdem alle gestarteten Threads ihre jeweiligen Algorithmen abgeschlossen haben. Auf diese Weise enthÀlt der Parallel-Abschnitt eine Synchronisation.

Wie sollte ein Parallel-Abschnitt aufgebaut sein?

WĂ€hrend Sie beliebige Anweisungen in den parallelen Zweigen einfĂŒgen dĂŒrfen, ist die ĂŒbliche Praxis, die Threads durch Unterroutinen-Aufrufe darzustellen. Einige Programmiersprachen (und der StrukTeX-Export) erwarten sogar, dass die Threads (Zweige) Aufrufe von Thread-Funktionen mit einer bestimmten Signatur sind. Dies macht Sinn, da andernfalls ein hohes Risiko gegenseitiger Auswirkungen auf gemeinsame Variablen bestĂŒnde, was zu Wettlaufsituationen, Inkonsistenzen und widersprĂŒchlichen Ergebnissen fĂŒhren wĂŒrde. (Wenn die entsprechende Analyser-Option aktiviert ist, erhalten Sie Warnungen bei einigen offensichtlichen potenziellen Inkonsistenzen.)

Code-Export

Derzeit gibt es fĂŒr viele der Code-Exportsprachen eine Strategie zur Umwandlung von PARALLEL-Elementen in funktionierenden Multithreading-Code, z. B. C++, C#, Java, Python, Perl und bash/ksh. In der Regel werden zunĂ€chst Worker-Klassen oder Funktionsobjekte aus den Zweigen des PARALLEL-Elements definiert, dann wird fĂŒr jeden ein entsprechender Thread gestartet, und nach dem Warten auf deren Beendigung werden die in den Threads zugewiesenen Variablenwerte fĂŒr die weitere Verwendung im Hauptthread extrahiert. FĂŒr Zielsprachen ohne Multithreading-UnterstĂŒtzung (z. B. gibt es fĂŒr C keine systemunabhĂ€ngige Thread-UnterstĂŒtzung in den Standardbibliotheken) oder ohne vollstĂ€ndige GeneratorunterstĂŒtzung serialisiert der Code-Export lediglich die Zweige der PARALLEL-Elemente, markiert diese jedoch mit auffĂ€lligen Kommentaren, sodass der Benutzer selbst eine nebenlĂ€ufige Lösung suchen kann.

AusfĂŒhrung / Debugging

Der Executor ist ĂŒbrigens nicht in der Lage, die Threads tatsĂ€chlich parallel auszufĂŒhren. Stattdessen versucht er, die NebenlĂ€ufigkeit zu simulieren, indem er zufĂ€llig fĂ€llige Anweisungen aus dem Pool der noch nicht beendeten Threads auswĂ€hlt. Dies geht jedoch nicht tiefer als nur auf der ersten Anweisungsfolgenebene. Daher werden Schleifen, Aufrufe usw. stets vollstĂ€ndig im sequenziellen Modus ausgefĂŒhrt, bevor der Thread die Kontrolle an einen anderen wartenden abgibt.

Wie fĂŒgen Sie ein PARALLEL-Element hinzu?

  1. WĂ€hlen Sie das Element aus, vor oder nach dem ein PARALLEL-Element eingefĂŒgt werden soll.
  2. Klicken Sie auf den entsprechenden Eintrag im KontextmenĂŒ oder auf die rot markierte Symbolleisten-SchaltflĂ€che im Bild (optional mit gedrĂŒckter <Shift>-Taste) oder drĂŒcken Sie die Taste <F13> (Versionen ≀ 3.29-12) oder die Tastenkombination <Ctrl><F6> (Versionen ≄ 3.29-13).
  3. Wenn der Element-Editor öffnet, schreiben Sie einfach die Anzahl der parallelen Threads in das Textfeld — nicht mehr und nicht weniger. Nur eine konstante Kardinalzahl ist hier gĂŒltig. FĂŒr erlĂ€uternden Text verwenden Sie den Kommentartextbereich.
    Editor fĂŒr den Parallel-Abschnitt
    Editor fĂŒr den Parallel-Abschnitt
    Wenn Sie ein vorhandenes PARALLEL-Element bearbeiten, beachten Sie, dass beim Verringern der Zweiganzahl die ĂŒberzĂ€hligen Threads automatisch entfernt werden. (Wenn Sie also eine Sicherungskopie von ihnen möchten, erstellen Sie diese vorher. Sie können die Thread-Anzahlreduzierung und damit die Entfernung natĂŒrlich rĂŒckgĂ€ngig machen, falls Sie das Sichern vergessen haben.)
    QuickSort nach dem EinfĂŒgen eines Parallel-Abschnitts
    QuickSort nach dem EinfĂŒgen eines Parallel-Abschnitts
  4. FĂŒgen Sie wie gewohnt Elemente in die Zweige ein — jeder Zweig verhĂ€lt sich wie eine gewöhnliche Anweisungsfolge —, aber beachten Sie die einleitenden Hinweise: Es ist vorzuziehen, die Threads jeweils aus einem einzigen Unterroutinen-Aufruf bestehen zu lassen, wie in der folgenden rekursiv-parallelen Implementierung eines QuickSort-Algorithmus (zur besseren Erkennung wurden die beiden nebenlĂ€ufigen Threads unterschiedlich eingefĂ€rbt):
    Rekursiv-paralleler QuickSort-Algorithmus
    Rekursiv-paralleler QuickSort-Algorithmus
    Die AusfĂŒhrungsreihenfolge der grĂŒnen und der tĂŒrkisen Aufrufe wird zufĂ€llig gewĂ€hlt.