# Testat - OpenMP
## Fragenkatalog 1 (leicht)
Was ist der Unterschied zwischen private und shared Variablen?
- Shared Semantik
- Threads können auf Variablen im selben Speicher zugreifen
- Kommunikation via lesen/schreiben von geteilten Variablen
- Private Semantik
. Mehrere Speicherorte
- Eine im Ausführungskontex jedes Threads
- Andere Threads können nicht darauf zugreifen
Was ist OpenMP?
- Open specifications for Multi Processing
- Community Standard einer Shared-Memory-Programmierschnittstelle
- Compiler-Direktiven zur Beschreibung von Parallelität im Quellcode
- Bibliotheksfunktionen
- Umgebungsvariablen
- `#include <omp.h>`
- Ablauf:
- Erstellung von Team von Threads, welche nebenläufig ausgeführt werden (Paralleles Konstrukt)
- Verteilung von Aufgaben an die vorhandenen Threads
- Generierung von Tasks (Task Konstrukt)
Nennen Sie eine Möglichkeit die Anzahl der Threads für das parallele Konstrukt festzulegen.
- Vor Programm, Einfluss auf komplettes Programm: `setenv OMP_NUM_THREADS number`
- Laufzeit, beeinflusst nachfolgende parallele Konstrukte: `omp_set_num_threads(number)`
- Paralleles Konstrukt: `num_threads_clause(number)`
Welche Reduktionsoperationen gibt es (nenne 4)?
- Binäre Operation
- +, -, /, &, |, &&, ||, min, max
## Fragenkatalog 2 (mittel)
Beschreiben Sie die Funktionalität vom Vom Konstrukt `single?
```c
#pragma omp single [clauses]
{
code_block
}
```
- Gibt an, dass der Codeauschnitt nur durch einen einzigen Thread ausgeführt werden soll
nur durch einen einzigen Thread
Erklären Sie die Begriffe "construct" und "region" in OpenMP
- Construct
- Lexical or static extent
- Code lexically enclosed
- Region
- Dynamischer Umfang
- Lexikalischer Umfang plus Code von aufgerufenen Unterroutinen innerhalb des Konstrukts
Beschreiben Sie die Funktionalität vom Vom Konstrukt `critical`?
```c
#pragma omp critical [(name)]
{
code_block
}
```
- Gibt an, dass Code jeweils nur in einem Thread ausgeführt wird
Was ist der Unterschied zwischen den folgenden Codeauschnitten:
```c
#pragma omp parallel for
for(int i = 0; i < n; i++){}
}
```
```c
#pragma omp parallel
for(int i = 0; i < n; i++){}
}
```
- Der erste Code parallelisiert die `for`-Schleife
- Der zweite Code führt in jedem Thread die `for`-Schleife durch
Führt der folgende Code zu einem Problem, wenn `i` nicht explizit als `private` gesetzt wurde?
```c
#pragma omp parallel for
for(int i = 0; i < n; i++){}
}
```
## Fragenkatalog 3 (schwer)
Gegeben sei folgender (Pseudo-)Code. Wie viele Task werden generiert?
```c
#pragma omp parallel num_threads(n)
{
#pragma omp task
{
... work1 ...
}
#pragma omp task
{
... work2 ...
}
}
```
Anschlussfrage. Wie kann man erreichen, dass nur ein Thread die Tasks generiert?
- 2 * n Tasks
- Mit dem Konstrukt `single`
Was sind (die wichtigsten) Unterschiede von pragma omp atomic und pragma omp critical?
- `atomic`
- Gibt an, dass ein Speicherspeicherort atomar aktualisiert wird
- Weniger Overhead, da Ausnutzung von Hardware bspw. atomare Inkrementoperation; In diesem Fall ist beim Betreten/Verlassen der Codezeile kein Sperren/Entsperren (Lock/Unlock) erforderlich
- Spezielle Form von `critical`
- Nur eine Codezeile
- Mehrere Aktualisierungen an verschiedenen Orten können gleichzeitig erfolgen
- Single Update
- Eher bei wenigen Update oder wenigen Orten
- `critical`
- Gibt an, dass Code jeweils nur in einem Thread ausgeführt wird
- Codeblöcke
- Multiple Update
- Overhead
- Eher Update bei mehreren Orten
Gegeben sei folgendes Code-Skelett
```c
#pragma omp parallel
{
#pragma omp for
for(int i = 0...) {
...
}
#pragma omp single
call_foo();
}
```
An welchen Stellen gibt es eine implizite Barriere?
```c++
#pragma omp parallel
{
#pragma omp for
for(int i = 0...) {
...
} // 1. Durch Parallelisierung der Schleife
#pragma omp single
call_foo(); // 2. Durch Konstrukt single
} // 3. Durch die parallele Region
```
Beschreiben Sie die Funktionalität des Konstrukts `if` und nennen Sie einen Beispiel, wo es verwendet wird.
- Bestimmung, ob serielle oder parallele Ausführung
- Beispiel: Quicksort -> bei kleinen Mengen ist seriell besser, da parallel Overhead größer ist, als die eigentliche Aufgabe
## Zusatz (Potentiell möglich?)
Was ist der Unterschied zwischen `private` vs. `firstprivate` vs. `lastprivate`?
- `private`: Jeder Thread hat seine eigene uninitialisierte Variable
- `firstprivate`: Jeder Thread hat seine eigne Variable, wobei der Wert vom Masterthread kopiert wird
- `lastprivate`: Nach Austritt der parallelen Region ist die Variable auf dem Wert der letzten Iteration der Schleife gesetzt
Was ist Tasking?
- Problemstellung wird in unabhängige Problemstellungen zerlegt und als eigenständige Tasks erstellt
- Tasks werden in einem Taskpool gelegt
- Threads holen sich jeweils Tasks aus dem Taskpool bis alle Tasks abgeschlossen sind und der Taskpool leer ist
- Vorteil: Gute Balance der Last bei Überzerlegung des Problems
Wie kann man Tasks synchronisieren?
- `#pragma omp barrier`
- `#pragma omp taskwait`
Was sind implizite und explizite Tasks?
- Implizit: Tasks die für jeden Thread generiert werden, wenn ein paralleles Konstrukt geöffnet wurde
- Explizit: Werden durch das Task-Konstrukt erzeugt
Beschreiben Sie die Funktionalität vom Vom Konstrukt `reduction`?
- Variablen, die für jeden Thread privat sind, werden mittels einer Reduktionsoperation verknüpft
Was ist der Unterschied zwischen `race condition` und `data race`?
- `race condition`: Bei erneuter Ausführung des Programmes kommen unterschiedliche Ergebnisse raus, da die zeitliche Überlagerung (also wie unterschiedliche Threads ihre Arbeit verrichten) sich verändert.
- `data race`: Bezieht sich auf den Speicherzugriffe -> wenn mehrere Prozesse versuchen auf eine Speicherstelle zuzugreifen und mindestens einer davon schreibt, so resultiert dies in undefiniertem Verhalten