---
# System prepended metadata

title: Testat - OpenMP

---

# 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