Multithreading fix

This commit is contained in:
WieErWill 2021-04-09 10:02:33 +02:00
parent bd21045741
commit 3cd4b5951e
2 changed files with 153 additions and 224 deletions

Binary file not shown.

View File

@ -2601,17 +2601,17 @@ $\lambda x.xx$ wendet sein Argument auf das Argument selbst an $\Rightarrow$ dad
\begin{itemize*}
\item Rekursive Funktion von g
\begin{itemize*}
\item $g = \lambda n.…g…n…$ Rumpf verwendet g
\item $g = \lambda n...g...n...$ Rumpf verwendet g
\end{itemize*}
\item Daraus gewinnt man das Funktional
\begin{itemize*}
\item $G = \lambda g.\lambda n.…g…n…$
\item $G = \lambda g.\lambda n...g...n...$
\end{itemize*}
\item Falls G einen Fixpunkt g* hat, d.h. $G(g*) = g*$, so
\begin{itemize*}
\item $g* = G(g*) = \lambda n.…g*n$
\item $g* = G(g*) = \lambda n...g*...n$
\end{itemize*}
\item Vergleiche: $g = \lambda n.…g…n…$
\item Vergleiche: $g = \lambda n...g...n...$
\end{itemize*}
\begin{center}
Rekursive Definition $\Leftrightarrow$ Fixpunkt des Funktionals
@ -2647,7 +2647,7 @@ $\lambda x.xx$ wendet sein Argument auf das Argument selbst an $\Rightarrow$ dad
\begin{itemize*}
\item Anfangsfunktionen:
\begin{itemize*}
\item Projektion: $U_i^k (n_1,n_2,,n_k) = n_i$ für $1<=i<=k$
\item Projektion: $U_i^k (n_1,n_2,...,n_k) = n_i$ für $1<=i<=k$
\item Nullfunktion: $Z(n) = 0$
\item Nachfolger: $S(n) = n+1$
\end{itemize*}
@ -2656,15 +2656,15 @@ $\lambda x.xx$ wendet sein Argument auf das Argument selbst an $\Rightarrow$ dad
\item Für eine Relation $P(m)$ bezeichne $\mu m[P(m)]$ die kleinste Zahl m sodass P(m) gilt.
\end{itemize*}
\end{itemize*}
\item Bemerkung: im Folgenden notieren wir $n_1,n_2,,n_k$ kurz als $\overline{n_k}$
\item Bemerkung: im Folgenden notieren wir $n_1,n_2,...,n_k$ kurz als $\overline{n_k}$
\item Eine numerische Funktion ist Lambda-definierbar, wenn es einen Kombinator M gibt, sodass $M\overline{n_k} = f(\overline{n_k})$
\end{itemize*}
\begin{itemize*}
\item Im folgenden sei C eine Klasse von numerischen Funktionen, und es gelte $g,h,h_1,h_2,,h_m \in C$
\item Im folgenden sei C eine Klasse von numerischen Funktionen, und es gelte $g,h,h_1,h_2,...,h_m \in C$
\item Wir definieren nun die folgenden Eigenschaften:
\begin{itemize*}
\item C ist \color{blue} abgeschlossen unter Komposition\color{black}, wenn für jede Funktion f, die über $f(\overline{n_k}):= g(h_1(\overline{n_k}),,h_m(\overline{n_k}))$ definiert ist, gilt $f \in C$
\item C ist \color{blue} abgeschlossen unter Komposition\color{black}, wenn für jede Funktion f, die über $f(\overline{n_k}):= g(h_1(\overline{n_k}),...,h_m(\overline{n_k}))$ definiert ist, gilt $f \in C$
\item C ist \color{blue} abgeschlossen unter primitiver Rekursion\color{black}, wenn für jede Funktion f, die über
$$f(0,\overline{n_k}) = g(\overline{n_k})$$
$$f(j+1, \overline{n_k}) = h(f(j,\overline{n_k}),j,\overline{n_k})$$
@ -2683,7 +2683,7 @@ $\lambda x.xx$ wendet sein Argument auf das Argument selbst an $\Rightarrow$ dad
\item \color{blue} Lemma 1: Die Anfangsfunktionen sind Lambda-definierbar \color{black}
\item Beweis:
\begin{itemize*}
\item $U_i^k = \lambda x_1 x_2 x_k.x_i$
\item $U_i^k = \lambda x_1 x_2 ... x_k.x_i$
\item $S = \lambda n.\lambda s. \lambda z.s(nsz)$ (siehe succ bei Churchzahlen)
\item $Z = \lambda fx.x$ (siehe $c_0$ bei Churchzahlen)
\end{itemize*}
@ -2799,7 +2799,7 @@ $\lambda x.xx$ wendet sein Argument auf das Argument selbst an $\Rightarrow$ dad
\item Hierbei ist es insbesondere von Interesse, wie Parameter gehandhabt werden, deren Werte undefiniert sind (z.B. 1/0)\newline
\colorbox{lightgray}{
\begin{minipage}[h]{1.0\linewidth}
Wir definieren zunächst den zentralen begriff "strikt": \newline Eine n-stellige Funktion heißt strikt im k-ten Argument $(1<=k<=n)$, wenn gilt: $f(x_1,x_2,,x_{k-1},\bot,x_{k+1},,x_n)=\bot$
Wir definieren zunächst den zentralen begriff "strikt": \newline Eine n-stellige Funktion heißt strikt im k-ten Argument $(1<=k<=n)$, wenn gilt: $f(x_1,x_2,...,x_{k-1},\bot,x_{k+1},...,x_n)=\bot$
\end{minipage}}
\item Ein undefiniertes Argument führt hier zu einem undefinierten Resultat
\item Grundsätzlich kann man die Auswertungsstrategien von Programmiersprachen in strikte und nicht-strikte Strategien einteilen; sehr gebräuchlich sind dabei insbesondere:
@ -2849,7 +2849,7 @@ $\lambda x.xx$ wendet sein Argument auf das Argument selbst an $\Rightarrow$ dad
\item Die folgenden Gleichungen definieren eine nicht-strikte Multiplikation $\otimes$ auf der Basis der Multiplikation · für Zahlen:
$$0 \otimes y = 0$$
$$x \otimes 0 = 0$$
$$x \otimes y = x · y$$
$$x \otimes y = x * y$$
\item Wenn ein Arguemnt undefiniert ist, dann liefert $\otimes$ ein Ergebnis, sofern das andere Argument zu 0 evaluiert wird ($\rightarrow fak(-1) \otimes (fak(3)-6)$)
\item Implementiert werden kann die Funktion nur durch eine Art von paralleler Auswertung mit Abbruch der anderen Berechnung sobald 0 als Resultat berechnet und zurückgegeben wurde
\end{itemize*}
@ -2899,10 +2899,10 @@ $\Rightarrow$ call-by-name, call-by-value
\subsubitem $\Rightarrow (\lambda \color{blue}y\color{black}(\lambda x. \color{blue}y\color{black}(\lambda z.z)x))\color{red}(\lambda y.y)\color{black}$
\subsubitem $\Rightarrow (\lambda x.(\lambda y.y(\lambda z.z)x)) \nRightarrow$
\item Intuition: Argumente vor Funktionsaufruf auswerten
\item Auswertungsstrategie vieler Sprachen: Java, C, Scheme, ML,
\item Auswertungsstrategie vieler Sprachen: Java, C, Scheme, ML, ...
\item Arithmetik in Haskell: Auswertung by-value
\item $prodOf(x) = y * prodOf x$
\item $3 * prodOf 3 \Rightarrow 3 * (3 * prodOf 3) \Rightarrow$
\item $3 * prodOf 3 \Rightarrow 3 * (3 * prodOf 3) \Rightarrow$ ...
\item $((div \space1 \space 0) * 6) * 0 \Rightarrow \bot$
\item $((div \space2 \space 2) * 6) * 0 \Rightarrow ((1 * 6) * 0) \Rightarrow 6 * 0\Rightarrow 0 \nRightarrow$
\end{itemize*}
@ -2974,7 +2974,7 @@ $\Rightarrow$ call-by-name, call-by-value
\subsubsection{The free launch is over}
Taktfrequenz wächst nur noch langsam
\begin{itemize*}
\item Physikalische Gründe: Wärmeentwicklung, Energiebedarf, Kriechströme,
\item Physikalische Gründe: Wärmeentwicklung, Energiebedarf, Kriechströme,...
\end{itemize*}
Auswege
\begin{itemize*}
@ -3080,8 +3080,8 @@ $\Rightarrow$ call-by-name, call-by-value
\begin{itemize*}
\item Maße für Laufzeitgewinn durch Parallelisierung
\item $T_n$ = Laufzeit des Programms mit n Prozessoren/Kernen
\item Speedup $Speedup = {{T_1} \over {T_n}}$
\item Effizienz $Effizienz = {Speedup \over n}$
\item Speedup $Speedup = \frac{T_1}{T_n}$
\item Effizienz $Effizienz = \frac{Speedup}{n}$
\end{itemize*}
\subsubsection{Amdahlsches Gesetz}
@ -3091,7 +3091,7 @@ $\Rightarrow$ call-by-name, call-by-value
\item s = serieller Anteil
\item n Prozessoren
\item $p+s = 1$
\item Maximaler Speedup $Speedup_{max} = {T_1 \over T_n} = {{s+p}\over{s+{p \over n}}} = {1 \over {s+{p \over n}}} = \frac{1}{s+\frac{p}{n}}$
\item Maximaler Speedup $Speedup_{max} = \frac{T_1}{T_n} = {\frac{s+p}{s+ \frac{p}{n}}} = \frac{1}{s+\frac{p}{n}}$
\end{itemize*}
\begin{center}
\includegraphics[width=0.35\linewidth]{Assets/Programmierparadigmen-parallelisierung}
@ -3177,7 +3177,7 @@ $\Rightarrow$ call-by-name, call-by-value
\includegraphics[width=0.9\linewidth]{Assets/Programmierparadigmen-Datenparallelität}
\caption{Datenparallelität}
\begin{itemize*}
\item homogene Datenmenge: Felder, Listen, Dokumentenmenge,
\item homogene Datenmenge: Felder, Listen, Dokumentenmenge,...
\item Verteilung der Daten
\item alle Prozessoren führen gleiches Programm auf jeweils eigenen Daten aus
\item Beispiel: Matrixaddition S = A + B
@ -3216,7 +3216,7 @@ $\Rightarrow$ call-by-name, call-by-value
\begin{itemize*}
\item Problemzerlegung
\item Synchronisation
\item
\item ...
\end{itemize*}
\item im Weiteren: konkrete Methoden und Techniken in Erlang und C++
\end{itemize*}
@ -3228,9 +3228,9 @@ $\Rightarrow$ call-by-name, call-by-value
\item SMP-Support (Symmetric Multi Processing)
\item Ziele für effiziente Parallelisierung
\begin{itemize*}
\item Problem in viele Prozesse zerlegen (aber nicht zu viele )
\item Seiteneffekte vermeiden (würde Synchronisation erfordern )
\item Sequentiellen Flaschenhals vermeiden (Zugriff auf gemeinsame Ressourcen: IO, Registrierung von Prozessen, ) -> Small Messages, Big Computation!
\item Problem in viele Prozesse zerlegen (aber nicht zu viele ...)
\item Seiteneffekte vermeiden (würde Synchronisation erfordern ...)
\item Sequentiellen Flaschenhals vermeiden (Zugriff auf gemeinsame Ressourcen: IO, Registrierung von Prozessen, ...) -> Small Messages, Big Computation!
\end{itemize*}
\end{itemize*}
@ -3434,7 +3434,7 @@ $\Rightarrow$ call-by-name, call-by-value
\subsubsection{Datenparallelität: Das Map-Reduce-Paradigma}
\begin{itemize*}
\item Parallelisierungsmuster inspiriert von Konzepten funktionaler Programmiersprachen (map,reduce/fold)
\item Basis von Big-Data-plattformen wie Hadoop, Spark,
\item Basis von Big-Data-plattformen wie Hadoop, Spark,...
\item Grundidee:
\begin{itemize*}
\item map(F, Seq) ? wende Funktion F (als Argument übergeben) auf alle Elemente einer Folge Seq an,
@ -3496,7 +3496,7 @@ $\Rightarrow$ call-by-name, call-by-value
\begin{itemize*}
\item Prozess für das Sortieren der einen Hälfte starten
\item Elternprozess kann andere Hälfte sortieren
\item rekursive Zerlegung
\item rekursive Zerlegung...
\end{itemize*}
\subsubsection{Parallel Quicksort}
@ -3695,7 +3695,7 @@ $\Rightarrow$ call-by-name, call-by-value
\includegraphics[width=0.7\linewidth]{Assets/Programmierparadigmen-code-snippet-20}
\end{center}
\begin{itemize*}
\item Nutzung für Implementierung von Threadpools, Task Libraries,
\item Nutzung für Implementierung von Threadpools, Task Libraries, ...
\end{itemize*}
\subsubsection{Probleme nebenläufiger Ausführung}
@ -3851,7 +3851,7 @@ $\Rightarrow$ call-by-name, call-by-value
\begin{itemize*}
\item Jeder greift die linke Gabel
\item und wartet auf die rechte Gabel
\item … und wartet …
\item ... und wartet ...
\end{itemize*}
\begin{center}
\includegraphics[width=0.3\linewidth]{Assets/Programmierparadigmen-philosophen}
@ -3883,37 +3883,37 @@ $\Rightarrow$ call-by-name, call-by-value
\paragraph{Gabeln und Spaghetti-Teller}
\begin{center}
\includegraphics[width=0.7\linewidth]{Assets/Programmierparadigmen-073}
\includegraphics[width=0.4\linewidth]{Assets/Programmierparadigmen-code-snippet-25}
\end{center}
\paragraph{Die Philosophen-Klasse}
\begin{center}
\includegraphics[width=0.7\linewidth]{Assets/Programmierparadigmen-074}
\includegraphics[width=0.4\linewidth]{Assets/Programmierparadigmen-code-snippet-26}
\end{center}
\paragraph{Die Philosophen-Klasse: Hilfsmethoden}
Textausgabe erfordert synchronisierten Zugriff auf cout über globalen Mutex
\begin{center}
\includegraphics[width=0.7\linewidth]{Assets/Programmierparadigmen-075}
\includegraphics[width=0.4\linewidth]{Assets/Programmierparadigmen-code-snippet-27}
\end{center}
Hilfsmethode für zufällige Wartezeit in Millisekunden
\begin{center}
\includegraphics[width=0.7\linewidth]{Assets/Programmierparadigmen-076}
\includegraphics[width=0.4\linewidth]{Assets/Programmierparadigmen-code-snippet-28}
\end{center}
\paragraph{Die Philosophen-Klasse: Essen}
\begin{center}
\includegraphics[width=0.7\linewidth]{Assets/Programmierparadigmen-077}
\includegraphics[width=0.4\linewidth]{Assets/Programmierparadigmen-code-snippet-29}
\end{center}
\paragraph{Die Philosophen-Klasse: Denken}
\begin{center}
\includegraphics[width=0.7\linewidth]{Assets/Programmierparadigmen-078}
\includegraphics[width=0.4\linewidth]{Assets/Programmierparadigmen-code-snippet-30}
\end{center}
\paragraph{Das Leben eines Philosophen}
@ -3922,13 +3922,13 @@ $\Rightarrow$ call-by-name, call-by-value
\item Zur Erinnerung: überladener ()-Operator eines Objekts definiert auszuführende Funktion eines Threads
\end{itemize*}
\begin{center}
\includegraphics[width=0.7\linewidth]{Assets/Programmierparadigmen-079}
\includegraphics[width=0.4\linewidth]{Assets/Programmierparadigmen-code-snippet-31}
\end{center}
\paragraph{Das Dinner: Initialisierung}
\begin{center}
\includegraphics[width=0.7\linewidth]{Assets/Programmierparadigmen-080}
\includegraphics[width=0.7\linewidth]{Assets/Programmierparadigmen-code-snippet-32}
\end{center}
\paragraph{Das Dinner beginnt}
@ -3938,7 +3938,7 @@ $\Rightarrow$ call-by-name, call-by-value
\item Philosophen-Threads arbeiten ihre operator()()-Methode ab
\end{itemize*}
\begin{center}
\includegraphics[width=0.7\linewidth]{Assets/Programmierparadigmen-081}
\includegraphics[width=0.4\linewidth]{Assets/Programmierparadigmen-code-snippet-33}
\end{center}
\paragraph{Fazit}
@ -3965,7 +3965,7 @@ $\Rightarrow$ call-by-name, call-by-value
\item typischer Anwendungsfall: Warten auf Ereignis / Setzen eines Flags
\end{itemize*}
\begin{center}
\includegraphics[width=0.7\linewidth]{Assets/Programmierparadigmen-082}
\includegraphics[width=0.4\linewidth]{Assets/Programmierparadigmen-code-snippet-34}
\end{center}
\subsubsection{Bedingungsvariablen}
@ -3975,10 +3975,8 @@ $\Rightarrow$ call-by-name, call-by-value
\item notwendig: synchronisierter Zugriff über Mutex
\end{itemize*}
\begin{center}
\includegraphics[width=0.7\linewidth]{Assets/Programmierparadigmen-083}
\end{center}
\begin{center}
\includegraphics[width=0.7\linewidth]{Assets/Programmierparadigmen-084}
\includegraphics[width=0.4\linewidth]{Assets/Programmierparadigmen-code-snippet-35}
\includegraphics[width=0.4\linewidth]{Assets/Programmierparadigmen-code-snippet-36}
\end{center}
\subsubsection{Thread-sichere Datenstrukturen}
@ -4008,7 +4006,6 @@ $\Rightarrow$ call-by-name, call-by-value
\end{itemize*}
\end{itemize*}
\subsubsection{Anforderungen}
\begin{itemize*}
\item mehrere Threads können gleichzeitig auf die Datenstruktur zugreifen
@ -4020,7 +4017,7 @@ $\Rightarrow$ call-by-name, call-by-value
\subsubsection{Thread-sichere Queue}
\begin{center}
\includegraphics[width=0.7\linewidth]{Assets/Programmierparadigmen-085}
\includegraphics[width=0.4\linewidth]{Assets/Programmierparadigmen-code-snippet-37}
\end{center}
\begin{itemize*}
\item Zeilen 1,2,6: Kapselung der std::queue-Klasse
@ -4031,7 +4028,7 @@ $\Rightarrow$ call-by-name, call-by-value
\paragraph{Thread-sichere Queue: Methode push}
\begin{center}
\includegraphics[width=0.7\linewidth]{Assets/Programmierparadigmen-086}
\includegraphics[width=0.4\linewidth]{Assets/Programmierparadigmen-code-snippet-38}
\end{center}
\begin{itemize*}
\item Zeile 2: Lock Guard sichert exklusiven Zugriff
@ -4042,7 +4039,7 @@ $\Rightarrow$ call-by-name, call-by-value
\paragraph{Thread-sichere Queue: Methode waiting\_pop}
\begin{center}
\includegraphics[width=0.7\linewidth]{Assets/Programmierparadigmen-087}
\includegraphics[width=0.4\linewidth]{Assets/Programmierparadigmen-code-snippet-39}
\end{center}
\begin{itemize*}
\item Zeile 2: Lock Guard sichert exklusiven Zugriff
@ -4056,7 +4053,7 @@ $\Rightarrow$ call-by-name, call-by-value
\item std::async() - asynchrones Starten eines Tasks
\begin{center}
\centering
\includegraphics[width=0.7\linewidth]{Assets/Programmierparadigmen-088}
\includegraphics[width=0.4\linewidth]{Assets/Programmierparadigmen-code-snippet-40}
\end{center}
\item std::promise - erlaubt Wert zu setzen, wenn der aktuelle Thread beendet ist, of in Kombination mit std::future eingesetzt
\item future = Ergbenisobjekt, promise = Ergebnisproduzent
@ -4072,20 +4069,19 @@ $\Rightarrow$ call-by-name, call-by-value
\end{itemize*}
\end{itemize*}
\begin{center}
\includegraphics[width=0.7\linewidth]{Assets/Programmierparadigmen-089}
\includegraphics[width=0.4\linewidth]{Assets/Programmierparadigmen-future-task}
\end{center}
\paragraph{Beispiel}
Beispiel
\begin{center}
\includegraphics[width=0.7\linewidth]{Assets/Programmierparadigmen-090}
\includegraphics[width=0.4\linewidth]{Assets/Programmierparadigmen-code-snippet-41}
\end{center}
\subsubsection{Deklarative Parallelisierung mit OpenMP}
\begin{itemize*}
\item Programmierschnittstelle für Parallelisierung in C/C++/Fortran
\item Programmiersprachenerweiterung durch Direktiven
\item in C/C++: \#pragma omp
\item in C/C++: \#pragma omp ...
\item zusätzliche Bibliotheksfunktionen: \#include <omp.h>
\item aktuelle Version 5.0
\item Unterstützung in gcc und clang
@ -4104,7 +4100,7 @@ $\Rightarrow$ call-by-name, call-by-value
\item Fortsetzung des Master-Threads
\end{itemize*}
\begin{center}
\includegraphics[width=0.2\linewidth]{Assets/Programmierparadigmen-091}
\includegraphics[width=0.2\linewidth]{Assets/Programmierparadigmen-master-worker-thread}
\end{center}
@ -4114,12 +4110,12 @@ $\Rightarrow$ call-by-name, call-by-value
\item Ende des parallelen Abschnitts $\rightarrow$ implizite Synchronisation $\rightarrow$ Fortsetzung des Master-Threads
\item der dem 'pragma' folgende Block wird parallel von allen Threads ausgeführt
\begin{lstlisting}[language=C++]
\#include <iostream>
\#include <omp.h>
#include <iostream>
#include <omp.h>
int main() {
\#pragma omp parallel
#pragma omp parallel
{
std::cout << "Hello World from thread \#"
std::cout << "Hello World from thread #"
<< omp_get_thread_num() << " of "
<< omp_get_num_threads() << "\n";
}
@ -4129,26 +4125,26 @@ $\Rightarrow$ call-by-name, call-by-value
\end{lstlisting}
\item Schleifenparallelisierung: jedem Thread wird ein Teil der Iteration zugewiesen (beeinflusst nur äußere Schleife)
\begin{lstlisting}[language=C++]
...
\#pragma omp parallel for
for (int i = 0; i < 20; i++) {...
...
#pragma omp parallel for
for (int i = 0; i < 20; i++) {...
\end{lstlisting}
\begin{itemize*}
\item collapse(n) gibt an, dass n Schleifen in einem gemeinsamen Iterationsbereich zusammengefasst und auf die Threads verteilt werden sollen
\begin{lstlisting}
#pragma omp parallel for collapse(3)
\end{lstlisting}
#pragma omp parallel for collapse(3)
\end{lstlisting}
\end{itemize*}
\item Beeinflussung der Thread Anzahl
\begin{itemize*}
\item maximale Anzahl:
\begin{lstlisting}
\begin{lstlisting}
#pragma omp parallel for num_threads(8)
\end{lstlisting}
\end{lstlisting}
\item bedingte Parallelisierung:
\begin{lstlisting}
\begin{lstlisting}
#pragma omp parallel for if(i>50)
\end{lstlisting}
\end{lstlisting}
\end{itemize*}
\item Aufteilung des Iterationsbereichs; Beeinflussung durch schedule -Direktive
\begin{itemize*}
@ -4162,7 +4158,7 @@ $\Rightarrow$ call-by-name, call-by-value
\item '\#pragma omp single/master' Abschnitt wird nur durch einen/den Master-Thread ausgeführt
\item '\#pragma omp critical' kritischer Abschnitt
\item '\#pragma omp barrier' Warten auf alle Worker-Threads
\item '\#pragma omp atomic' kritischer Abschnitt \item Zugriff auf gemeinsame Variable (z.B. Zähler)
\item '\#pragma omp atomic' kritischer Abschnitt, Zugriff auf gemeinsame Variable (z.B. Zähler)
\end{itemize*}
\item Speicherklauseln für Variablen
\begin{itemize*}
@ -4173,13 +4169,13 @@ $\Rightarrow$ call-by-name, call-by-value
\end{itemize*}
\item zuweisung von Programmabschnitten zu Threads $\rightarrow$ statische Parallelität (geeignet für rekursive Abschnitte)
\begin{lstlisting}[language=C++]
\#pragma omp parallel sections
{
\#pragma omp section
qsort(data, left, p \item 1);
\#pragma omp section
qsort(data, p + 1, right);
}
#pragma omp parallel sections
{
#pragma omp section
qsort(data, left, p - 1);
#pragma omp section
qsort(data, p + 1, right);
}
\end{lstlisting}
\item Task Programmierung
\begin{itemize*}
@ -4188,13 +4184,13 @@ $\Rightarrow$ call-by-name, call-by-value
\item von beliebigem Thread definiert werden kann
\end{itemize*}
\begin{lstlisting}[language=C++]
unsigned int f1, f2;
\#pragma omp task shared(f1)
f1 = fib(f \item 1);
\#pragma omp task shared(f2)
f2 = fib(f \item 2);
\#pragma omp taskwait
return f1 + f2;
unsigned int f1, f2;
#pragma omp task shared(f1)
f1 = fib(f - 1);
#pragma omp task shared(f2)
f2 = fib(f - 2);
#pragma omp taskwait
return f1 + f2;
\end{lstlisting}
\end{itemize*}
@ -4203,7 +4199,7 @@ $\Rightarrow$ call-by-name, call-by-value
\item der dem pragma folgende Block wird parallel von allen Threads ausgeführt
\end{itemize*}
\begin{center}
\includegraphics[width=0.7\linewidth]{Assets/Programmierparadigmen-092}
\includegraphics[width=0.4\linewidth]{Assets/Programmierparadigmen-code-snippet-42}
\end{center}
\subsubsection{Schleifenparallelisierung}
@ -4212,17 +4208,18 @@ $\Rightarrow$ call-by-name, call-by-value
\item für for-Schleifgen mit eingeschränkter Syntax (ganzzahlige Schleifenvariablen, Operatoren auf Schleifenvariablen) und für STL-Iteratoren
\end{itemize*}
\begin{center}
\includegraphics[width=0.7\linewidth]{Assets/Programmierparadigmen-093}
\includegraphics[width=0.7\linewidth]{Assets/Programmierparadigmen-code-snippet-43}
\end{center}
\subsubsection{Beeinflussung der Thread-Anzahl}
maximale Anzahl
\begin{center}
\includegraphics[width=0.7\linewidth]{Assets/Programmierparadigmen-094}
\includegraphics[width=0.7\linewidth]{Assets/Programmierparadigmen-code-snippet-44}
\end{center}
\noindent
bedingte Parallelisierung
\begin{center}
\includegraphics[width=0.7\linewidth]{Assets/Programmierparadigmen-095}
\includegraphics[width=0.7\linewidth]{Assets/Programmierparadigmen-code-snippet-45}
\end{center}
\subsubsection{Aufteilung des Iterationsbereichs}
@ -4234,7 +4231,7 @@ $\Rightarrow$ call-by-name, call-by-value
\item schedule(static,n): statische Round-Robin-Verteilung - Bereiche der Größe n (Angabe von n ist optional)
\item schedule(dynamic, n): dynamische Verteilung nach Bedarf
\item schedule(guided, n): Verteilung nach Bedarf und proportional zur Restarbeit
\item
\item ...
\end{itemize*}
\end{itemize*}
@ -4245,7 +4242,7 @@ $\Rightarrow$ call-by-name, call-by-value
\item Beispiel: Matrizenmultiplikation
\end{itemize*}
\begin{center}
\includegraphics[width=0.7\linewidth]{Assets/Programmierparadigmen-096}
\includegraphics[width=0.4\linewidth]{Assets/Programmierparadigmen-code-snippet-46}
\end{center}
\subsubsection{Synchronisation}
@ -4272,7 +4269,7 @@ $\Rightarrow$ call-by-name, call-by-value
\item geeignet z.B. für rekursive Aufrufe
\end{itemize*}
\begin{center}
\includegraphics[width=0.7\linewidth]{Assets/Programmierparadigmen-097}
\includegraphics[width=0.4\linewidth]{Assets/Programmierparadigmen-code-snippet-47}
\end{center}
\subsubsection{Task-Programmierung mit OpenMP}
@ -4285,7 +4282,7 @@ $\Rightarrow$ call-by-name, call-by-value
\end{itemize*}
\end{itemize*}
\begin{center}
\includegraphics[width=0.7\linewidth]{Assets/Programmierparadigmen-098}
\includegraphics[width=0.4\linewidth]{Assets/Programmierparadigmen-code-snippet-48}
\end{center}
\subsubsection{Fazit}
@ -4293,18 +4290,15 @@ $\Rightarrow$ call-by-name, call-by-value
\item C++ bietet weitreichende und mächtige Konzepte zur Parallelisierung
\begin{itemize*}
\item von Basiskontrolle wie Threads und Synchronisationsprimitiven (u.a. Mutexe)
\item über höherwertige Abstraktionen wie async, Features und Promises
\item ...über höherwertige Abstraktionen wie async, Features und Promises
\item bis hin zu deklarativen Ansätzen wie OpenMP
\end{itemize*}
\item alle Formen von Parallelität (Instruktions-, Daten-, und Taskparallelität) möglich
\item aber anspruchsvolle Programmierung
\item erleichtert durch zusätzliche Bibliotheken und Frameworks wie Parallel STL, TBB,
\item erleichtert durch zusätzliche Bibliotheken und Frameworks wie Parallel STL, TBB, ...
\end{itemize*}
\begin{lstlisting}[
language=java,
showspaces=false,
basicstyle=\ttfamily
]
\begin{lstlisting}[language=java]
//[Hello.java]
package runnable;
public class Hello {
@ -4327,13 +4321,8 @@ public class Hello {
}
}
\end{lstlisting}
\hfill
\begin{lstlisting}[
language=C++,
showspaces=false,
basicstyle=\ttfamily
]
\hfill
\begin{lstlisting}[language=C++]
//[Hello.cpp]
#include <iostream> // Datei iostream aus System-Includes
#include "X.hpp" // Datei X.hpp aus Projekt-Ordner
@ -4367,13 +4356,8 @@ int main(int argc, char* argv[]){
return 0;
}
\end{lstlisting}
\hfill
\begin{lstlisting}[
language=erlang,
showspaces=false,
basicstyle=\ttfamily
]
\hfill
\begin{lstlisting}[language=erlang]
%[Hello.erl]
-module(cheat_sheet). % end with a period
@ -4441,11 +4425,7 @@ countdown() $\rightarrow$
\begin{itemize*}
\item Methode \textbf{public void run()} - wird beim Start des Threads aufgerufen
\end{itemize*}
\begin{center}
\includegraphics[width=0.7\linewidth]{Assets/Programmierparadigmen-099}
\end{center}
\begin{lstlisting}[
language=java]
\begin{lstlisting}[language=java]
public class Heartbeat implements Runnable {
int pulse;
public Heartbeat(int p) { pulse = p * 1000; }
@ -4457,15 +4437,10 @@ countdown() $\rightarrow$
}
}
}
\end{lstlisting}
public static void main(String[] args) {
Thread t = new Thread(new Heartbeat(2)); //Thread Objekt mit runnable erzeugen
t.start(); //methode start() aufrufen $\rightarrow$ ruft run() auf
}
\end{lstlisting}
\paragraph{Thread-Erzeugung}
\begin{itemize*}
\item Thread-Objekt mit Runnable-Objekt erzeugen
\item Methode \textbf{start()} aufrufen
@ -4473,9 +4448,12 @@ countdown() $\rightarrow$
\item Ruft \textbf{run()} auf
\end{itemize*}
\end{itemize*}
\begin{center}
\includegraphics[width=0.7\linewidth]{Assets/Programmierparadigmen-100}
\end{center}
\begin{lstlisting}[language=java]
public static void main(String[] args) {
Thread t = new Thread(new Heartbeat(2)); //Thread Objekt mit runnable erzeugen
t.start(); //methode start() aufrufen $\rightarrow$ ruft run() auf
}
\end{lstlisting}
\paragraph{Subklasse von Thread}
@ -4484,7 +4462,7 @@ countdown() $\rightarrow$
\item Methode run() muss überschrieben werden
\end{itemize*}
\begin{center}
\includegraphics[width=0.7\linewidth]{Assets/Programmierparadigmen-101}
\includegraphics[width=0.4\linewidth]{Assets/Programmierparadigmen-code-snippet-49}
\end{center}
\begin{itemize*}
@ -4495,52 +4473,32 @@ countdown() $\rightarrow$
\end{itemize*}
\begin{center}
\centering
\includegraphics[width=0.7\linewidth]{Assets/Programmierparadigmen-102}
\includegraphics[width=0.4\linewidth]{Assets/Programmierparadigmen-code-snippet-50}
\end{center}
\item Spätere Beeinflussung durch andere Threads möglich
\begin{center}
\centering
\includegraphics[width=0.7\linewidth]{Assets/Programmierparadigmen-103}
\includegraphics[width=0.4\linewidth]{Assets/Programmierparadigmen-code-snippet-51}
\end{center}
\end{itemize*}
\paragraph{Threads: Wichtige Methoden}
\begin{itemize*}
\item void start(): initiiert Ausführung des Threads durch Aufruf der Methode run
\item void run(): die eigentliche Arbeitsmethode
\item static void sleep(int millis): hält die Ausführung des aktuellen Threads für 'millis' Millisekunden an; Keinen Einfluss auf andere Threads!
\item void join(): blockiert den aufrufenden Thread so lange, bis der aufgerufene Thread beendet ist
\end{itemize*}
\begin{itemize*}
\item \textbf{void start()}
\begin{itemize*}
\item initiiert Ausführung des Threads durch Aufruf der Methode run
\end{itemize*}
\item \textbf{void run()}
\begin{itemize*}
\item die eigentliche Arbeitsmethode
\end{itemize*}
\item \textbf{static void sleep(int millisec)}
\begin{itemize*}
\item hält die Ausführung des aktuellen Threads für millisec Millisekunden an
\item Hat keinen Einfluss auf andere Threads!
\end{itemize*}
\item \textbf{void join()}
\begin{itemize*}
\item blockiert den aufrufenden Thread so lange, bis der aufgerufene Thread beendet ist
\end{itemize*}
\end{itemize*}
\begin{description*}
\item[void start()] initiiert Ausführung des Threads durch Aufruf der Methode run
\item[void run()] die eigentliche Arbeitsmethode
\item[static void sleep(int millis)] hält die Ausführung des aktuellen Threads für 'millis' Millisekunden an; Keinen Einfluss auf andere Threads!
\item[void join()] blockiert den aufrufenden Thread so lange, bis der aufgerufene Thread beendet ist
\end{description*}
\subsubsection{Parallele Berechnung von Fibonacci-Zahlen}
\begin{center}
\includegraphics[width=0.7\linewidth]{Assets/Programmierparadigmen-104}
\includegraphics[width=0.4\linewidth]{Assets/Programmierparadigmen-code-snippet-52}
\end{center}
Thread-Erzeugung und Ausführung
\begin{center}
\includegraphics[width=0.7\linewidth]{Assets/Programmierparadigmen-105}
\includegraphics[width=0.4\linewidth]{Assets/Programmierparadigmen-code-snippet-53}
\end{center}
\subsubsection{Wechselseitiger Ausschluss in Java}
@ -4555,14 +4513,14 @@ countdown() $\rightarrow$
\begin{itemize*}
\item nur ein Thread darf diese Methode auf einem Objekt zur gleichen Zeit ausführen
\end{itemize*}
\item für Anweisungen: \textbf{synchronized(anObject)\{\}}
\item für Anweisungen: \textbf{synchronized(anObject)\{...\}}
\begin{itemize*}
\item nur ein Thread darf den Block betreten
\item Sperre wird durch das Objekt \textbf{anObject} verwaltet (jedem Java-Objekt ist eine Sperre zugeordnet)
\end{itemize*}
\end{itemize*}
\begin{center}
\includegraphics[width=0.7\linewidth]{Assets/Programmierparadigmen-106}
\includegraphics[width=0.4\linewidth]{Assets/Programmierparadigmen-java-synchronized}
\end{center}
\begin{itemize*}
\item Schlüsselwort synchronized
@ -4584,23 +4542,14 @@ countdown() $\rightarrow$
\end{itemize*}
\subsubsection{wait \& notify}
\begin{itemize*}
\item Signalisierung zwischen Threads in Java
\item Basismethoden der Klasse \textbf{java.lang.Object}
\item \textbf{wait()}: der aktive Thread wartet an diesem Objekt, Sperren werden ggf. freigegeben.
\item \textbf{notify()}: wekct an diesem Objekt wartenden Thread auf
\item \textbf{notifyAll()}: weckt alle an diesem Objekt wartenden Threads auf
\item \textbf{wait() \& notify()} dürfen nur in einem \textbf{synchronized}-Block aufgerufen werden
\end{itemize*}
\begin{itemize*}
\item Signalisierung zwischen Threads in Java
\item Basismethoden der Klasse java.lang.Object
\item wait() : der aktive Thread wartet an diesem Objekt, Sperren werden ggf. freigegeben!
\item notify() : weckt an diesem Objekt wartenden Thread auf
\item notifyAll() : weckt alle an diesem Objekt wartenden Threads auf
\item wait() \& notify() dürfen nur in einem synchronized -Block aufgerufen werden
\end{itemize*}
\begin{description*}
\item[] Signalisierung zwischen Threads in Java
\item[] Basismethoden der Klasse \textbf{java.lang.Object}
\item[wait()] der aktive Thread wartet an diesem Objekt, Sperren werden ggf. freigegeben.
\item[notify()] wekct an diesem Objekt wartenden Thread auf
\item[notifyAll()] weckt alle an diesem Objekt wartenden Threads auf
\item[wait() \& notify()] dürfen nur in einem \textbf{synchronized}-Block aufgerufen werden
\end{description*}
\subsubsection{Java: High-Level-Klassen}
\begin{itemize*}
@ -4619,12 +4568,9 @@ countdown() $\rightarrow$
\item Task = logische Ausführungseinheit
\item Thread = Mechanismus zur asynchronen/parallelen Ausführung von Tasks
\end{itemize*}
\begin{center}
\includegraphics[width=0.7\linewidth]{Assets/Programmierparadigmen-107}
\end{center}
\begin{lstlisting}[
language=java]
Runnable task = () $\rightarrow$ {
\begin{lstlisting}[language=java]
Runnable task = () -> {
String me = Thread.currentThread().getName();
System.out.println("Hallo " + me);
};
@ -4642,8 +4588,8 @@ thread.start();
\end{itemize*}
\item Starten einer Aufgabe mit \textbf{submit}
\begin{itemize*}
\item \textbf{Future<T> submit(Callable c)}
\item \textbf{Future<?> submit(Runnable r)}
\item \textbf{$Future<T>$ submit(Callable c)}
\item \textbf{$Future<?>$ submit(Runnable r)}
\end{itemize*}
\item Zugriff auf das Ergebnis mit \textbf{get}
\begin{itemize*}
@ -4655,7 +4601,7 @@ thread.start();
\paragraph{Future \& ExecutorService: Beispiel}
\begin{center}
\includegraphics[width=0.7\linewidth]{Assets/Programmierparadigmen-108}
\includegraphics[width=0.7\linewidth]{Assets/Programmierparadigmen-code-snippet-54}
\end{center}
\subsubsection{RecursiveAction \& Fork/Join}
@ -4664,10 +4610,6 @@ thread.start();
\item Solange bis Problem klein genug um direkt ausgeführt werden zu können
\item Task erstellt zwei oder mehr Teiltasks von sich selbst $\rightarrowtail$ Datenparallelität
\item ForkJoinPool zum Ausführen $\rightarrow$ implementiert Executor Interface
\item \textbf{ForkJoinPool} zum Ausführen
\begin{itemize*}
\item implementiert \textbf{Executor} Interface
\end{itemize*}
\item Fazit
\begin{itemize*}
\item Parallelprogrammierung in Java sehr ähnlich zu C++
@ -4684,7 +4626,7 @@ thread.start();
\paragraph{Beispiel}
\begin{center}
\includegraphics[width=0.7\linewidth]{Assets/Programmierparadigmen-109}
\includegraphics[width=0.4\linewidth]{Assets/Programmierparadigmen-code-snippet-55}
\end{center}
Starten der Verarbeitung:
\begin{enumerate*}
@ -4693,24 +4635,12 @@ thread.start();
\item Aufgabe vom Pool ausführen lassen
\end{enumerate*}
\begin{center}
\includegraphics[width=0.7\linewidth]{Assets/Programmierparadigmen-110}
\includegraphics[width=0.4\linewidth]{Assets/Programmierparadigmen-code-snippet-56}
\end{center}
\subsubsection{Fazit}
\begin{itemize*}
\item Parallelprogrammierung in Java sehr ähnlich zu C++
\item Konzepte: Threads, kritische Abschnitte über \textbf{synchronized}
\item mächtige Abstraktionen in \textbf{java.util.concurrent}
\begin{itemize*}
\item Tasks und Futures, Executor und Threadpool
\item thread-sichere Datenstrukturen
\item Synchronisation: Barrieren, Semaphoren,…
\end{itemize*}
\end{itemize*}
\subsection{Zusammenfassung}
\begin{itemize*}
\item Parallelprogrammierung als wichtige Technik zur Nutzung moderner Hardware (Multicore, GPU, )
\item Parallelprogrammierung als wichtige Technik zur Nutzung moderner Hardware (Multicore, GPU, ...)
\item verschiedene Architekturen und Programmiermodelle
\item Instruktions-, Daten- und Taskparallelität
\item Message Passing vs. gemeinsamer Speicher
@ -4764,18 +4694,17 @@ thread.start();
\begin{itemize*}
\item Datei \~/.erlang.cookie
\item Erlang-Funktion
\begin{lstlisting}[
language=erlang,
]:set_cookie(node(), Cookie).
\end{lstlisting}
\begin{lstlisting}[language=erlang]
:set_cookie(node(), Cookie).
\end{lstlisting}
\item Option
\begin{lstlisting}
erl -setcookie Cookie
\end{lstlisting}
erl -setcookie Cookie
\end{lstlisting}
\end{itemize*}
\item Verbindungsaufbau mittels Funktion
\begin{lstlisting}
net_adm:ping(adress)
net_adm:ping(adress)
\end{lstlisting}
\end{itemize*}
@ -4847,7 +4776,7 @@ thread.start();
\end{itemize*}
\item Knoten sind über Netzwerke verbunden
\begin{itemize*}
\item LAN(Wohnräume, Büros,): bis zu 10 Gbit/s
\item LAN(Wohnräume, Büros,...): bis zu 10 Gbit/s
\item MAN(Metropolitan Area Network, Behördennetze, dicht besiedelte Regionen): bis zu 10 Gbit/s
\item WAN(Wide Area Network, weltweite Vernetzung): hohe Kapazitäten zwischen den ISPs
\end{itemize*}
@ -4882,8 +4811,8 @@ thread.start();
\item Middlewaresysteme: Hardware, OS, Middleware, Anwendung
\begin{itemize*}
\item verteilte Dienste
\item Programmierparadigmen: RPC, Client/Server,
\item Java, CORBA,
\item Programmierparadigmen: RPC, Client/Server,...
\item Java, CORBA, ...
\end{itemize*}
\item Heute: Virtualisierung
\begin{itemize*}
@ -4906,9 +4835,9 @@ thread.start();
\color{orange} $\Rightarrow$ brauchen Modelle zur Beschreibung der Kommunikation \color{black}
\subsubsection{Anforderungen}
\color{orange} Anforderungen an Kommunikationsmodelle in \color{black}
\color{orange} Anforderungen an Kommunikationsmodelle in ... \color{black}
\newline
verteilten Systemen\newline \newline
... verteilten Systemen\newline \newline
\begin{itemize*}
\item Korrektheit
\item Sicherheit
@ -4917,7 +4846,7 @@ thread.start();
\item Heterogenität
\end{itemize*}
verteilten Verkehrsmanagementsystemen\newline \newline
...verteilten Verkehrsmanagementsystemen\newline \newline
\begin{itemize*}
\item Echtzeitfähigkeit
\item Offenheit
@ -5037,9 +4966,9 @@ thread.start();
\end{itemize*}
\item Programmbestandteile im Aktormodell
\begin{itemize*}
\item Verhaltensdefinition $\Rightarrow$ f() $\rightarrow$ end.
\item Erzeugen neuer Aktoren $\Rightarrow$ Pid = spwan(fun ).
\item Empfangen von Nachrichten $\Rightarrow$ receive end.
\item Verhaltensdefinition $\Rightarrow$ f() $\rightarrow$ ... end.
\item Erzeugen neuer Aktoren $\Rightarrow$ Pid = spwan(fun ...).
\item Empfangen von Nachrichten $\Rightarrow$ receive ... end.
\item Senden $\Rightarrow$ Pid ! Request.
\end{itemize*}
\item kein globaler Zustand
@ -5144,7 +5073,7 @@ ok
\end{center}
drei Prozesse mit \textbf{initialize(ErrorRate, NumberOfMessages, ReceiverPid, SenderPid, ChannelPid)} initialisieren und starten
\begin{itemize*}
\item Sender hat vier Zustandsfunktionen; Startet mit senderReady0(List): Liste mit Zahlen 1,,NumberOfMessages
\item Sender hat vier Zustandsfunktionen; Startet mit senderReady0(List): Liste mit Zahlen 1,...,NumberOfMessages
\item Kanal: Nachricht "verlieren", wenn Zufallszahl $\ngeq$ ErrorRate
\item Empfänger hat zwei Zustandsfunktionen; zu Beginn wird receiverWait0 gestartet
\item initialize wartet auf eine ready-Nachricht; sendet danach stop-Nachrichten an alle
@ -5476,7 +5405,7 @@ end
\item Clients: "Gib mir alle Personen, die älter als 18 Jahre alt sind"
\end{itemize*}
\item \textbf{Web}: Webserver stellt HTML Dokumente bereit, Brwoser ruft URLs für Dokumente auf
\item \textbf{E-Mail}: Mailserver verwalten Postfächer, leiten Mails weiter, Outlook/Thunderbird/senden/lesen von Emails
\item \textbf{E-Mail}: Mailserver verwalten Postfächer, leiten Mails weiter, Outlook/Thunderbird/...senden/lesen von Emails
\item Namensdienste (DNS), Fileserver, Zeitserver (NTP)
\end{itemize*}
@ -5579,7 +5508,7 @@ end
\item oftmals existiert ein HTTP Server / Anwendungsserver schon
\item Idee: Jede Ressource die vom Server angeboten wird, ist durch eine URI beschrieben/identifiziert
\begin{itemize*}
\item Datei, ein Eintrag in einer Datenbank, Tweet,
\item Datei, ein Eintrag in einer Datenbank, Tweet,...
\end{itemize*}
\item Anlegen, Lesen, Verändern, Löschen (CRUD)
\begin{itemize*}
@ -5599,7 +5528,7 @@ end
\item bei jeder Anfrage werden alle Informationen gesendet
\end{itemize*}
\item Einheitliche Schnittstelle: über HTTP Standardmethoden auf Ressourcen zugreifen
\item Entkopplung von Ressource und Repräsentation: Ressourcen können in verschiedenen Formaten angeboten werden (JSON, XML,)
\item Entkopplung von Ressource und Repräsentation: Ressourcen können in verschiedenen Formaten angeboten werden (JSON, XML,...)
\end{enumerate*}
\paragraph{HTTP Methoden für REST}
@ -5636,7 +5565,7 @@ end
\begin{itemize*}
\item manuelle Implementierung recht aufwändig
\begin{itemize*}
\item unterscheiden von HTTP Methoden (GET, POST,)
\item unterscheiden von HTTP Methoden (GET, POST,...)
\item parsen/prüfen von URL Pfaden und Parametern
\item setzen von Antwortheadern \& Kodierung in XML/JSON
\end{itemize*}
@ -5687,7 +5616,7 @@ end
https://reques.in kostenloser Dienst zum Testen von REST-Clients
\begin{itemize*}
\item Variante 1: telnet reques.in 80
\item Variante 1: telnet reques.in 80 ...
\item Variante 2: Auf der Kommandozeile \newline
\$ curl https://reqres.in/api/users/1
\begin{center}
@ -6066,7 +5995,7 @@ fileservice.proto
\begin{itemize*}
\item erhebliche Management-Last beim Vermittler
\begin{itemize*}
\item potentieller Engpass, SPoF - es sei denn
\item potentieller Engpass, SPoF - es sei denn...
\end{itemize*}
\end{itemize*}
Variante: mehrere Vermittler-Instanzen parallel und verteilt in einer Clusterumgebung