104 lines
6.8 KiB
Markdown
104 lines
6.8 KiB
Markdown
# Projektbericht – Tricorn-Fraktal
|
||
|
||
## 1. Ziel des Projekts
|
||
|
||
Ziel ist ein C-Programm, das einen Ausschnitt des Tricorn-Fraktals berechnet und als BMP-Datei speichert. Über Kommandozeilenargumente werden Startpunkt, Bildgröße, Auflösung, maximale Iterationszahl, Ausgabedatei, Farbmodus und Implementierungsvariante festgelegt. Neben der skalaren Vergleichsversion enthält das Projekt SIMD- und Thread-Varianten, deren Laufzeiten miteinander verglichen werden.
|
||
|
||
## 2. Implementierungen
|
||
|
||
**V1** ist die skalare Vergleichsimplementierung. Real- und Imaginärteil werden direkt mit `float`-Operationen berechnet. Das Bild wird zeilenweise durchlaufen und die Koordinaten werden inkrementell erhöht.
|
||
|
||
**V2** verarbeitet vier benachbarte Pixel gleichzeitig mit 128-Bit-SSE-Registern. Eine aktive Maske speichert, welche SIMD-Lanes die Fluchtschranke noch nicht überschritten haben. Sobald alle vier Lanes inaktiv sind, wird die Iterationsschleife beendet. Für null bis drei Restpixel am Zeilenende wird eine skalare Funktion verwendet.
|
||
|
||
**V0**, die Hauptimplementierung, verwendet ebenfalls SIMD. Gegenüber V2 werden Real- und Imaginärkoordinaten inkrementell als Vektoren fortgeführt.
|
||
|
||
**V3** erweitert die optimierte SIMD-Berechnung um POSIX-Threads. Die verfügbaren logischen Prozessoren werden mit `sysconf` beziehungsweise `GetSystemInfo` bestimmt. Jeder Thread erhält einen zusammenhängenden Zeilenbereich und schreibt ausschließlich in diesen Teil des gemeinsamen Bildpuffers. Bei kleinen Bildern wird die Threadzahl reduziert, sodass ungefähr mindestens zehn Zeilen pro Thread verbleiben.
|
||
|
||
## 3. Tests und Performanzanalyse
|
||
|
||
Die Laufzeit wird mit `clock_gettime(CLOCK_MONOTONIC)` gemessen. Im Benchmark-Modus wird die gewählte Berechnung mehrfach ausgeführt; die BMP-Ausgabe liegt außerhalb der Messung. Der Mittelwert ist Gesamtzeit geteilt durch Wiederholungszahl. Der Speedup gegenüber einer Referenz \(R\) lautet
|
||
|
||
$$
|
||
S=\frac{T_R}{T_\mathrm{optimiert}}
|
||
$$
|
||
|
||
Die Testsuite enthält ein farbiges 1920×1080-Bild, ein 7680×4320-Bild mit niedriger Iterationszahl, einen vergrößerten Fraktalrand und einen nahezu schwarzen Bereich mit hoher Iterationszahl. Für einen fairen Versionsvergleich müssen in jedem Szenario identische Parameter verwendet werden
|
||
|
||
Wir haben versucht die Tests so zu wählen, dass unsere Implementierung in verschiedene Situationen zu testen, die zu verschiedene Ergebnissen führen.
|
||
|
||
Alle Tests werden auf die Rechnerhalle ausgeführt, um die volles Potenzial, die Optimierungen für High-End-Hardware zu prüfen.
|
||
|
||
#### Testumgebung:
|
||
- **Host-System:** TUM lxhalle
|
||
- **OS:** Ubuntu 24.04.2 LTS
|
||
- **CPU:** AMD EPYC 9554P 64-Core Processor
|
||
- **Thread-Anzahl:** 64 physische Kerne / 128 logische Threads
|
||
- **Taktfrequenz:** Basis 2.3 GHz / Boost 3.1 GHz
|
||
- **L3 Cache:** 256 MiB
|
||
- **L2 Cache:** 64 MiB
|
||
- **RAM:** 768 GB
|
||
- **Compiler:** gcc 13.3.0 (mit -O3 flag)
|
||
|
||
*(Diese Spezifikationen werden aus der Ausgabe von `lscpu` und `lshw` Befehle auf `lxhalle`, der CIT wiki und der Message of the Day)*
|
||
|
||
|
||
Alle Benchmarking-Tests werden 100 mal ausgeführt um eine genaue Messung zu erhalten.
|
||
|
||
#### Test 1: Default 1920x1080 Bild
|
||
|
||
| | Durchnitliches Laufzeit | Speedup gegenüber V1 |
|
||
| --- | ----------------------- | -------------------- |
|
||
| V0 | 0.046 | 3.2528 |
|
||
| V1 | 0.150 | 1.00 |
|
||
| V2 | 0.047 | 3.21 |
|
||
| V3 | 0.007 | 20.29 |
|
||
#### Test 2: 7680×4320-Bild mit niedriger Iterationszahl
|
||
| | Durchnitliches Laufzeit | Speedup gegenüber V1 |
|
||
| --- | ----------------------- | -------------------- |
|
||
| V0 | 0.047 | 1.81 |
|
||
| V1 | 0.086 | 1.00 |
|
||
| V2 | 0.049 | 1.74 |
|
||
| V3 | 0.006 | 13.71 |
|
||
|
||
#### Test 3: Fraktalrand
|
||
| | Durchnitliches Laufzeit | Speedup gegenüber V0 |
|
||
| --- | ----------------------- | -------------------- |
|
||
| V0 | 0.591 | 2.54 |
|
||
| V1 | 1.502 | 1.00 |
|
||
| V2 | 0.419 | 3.59 |
|
||
| V3 | 0.031 | 48.38 |
|
||
#### Test 4: Schwarzen Bereich mit hoher Iterationszahl
|
||
| | Durchnitliches Laufzeit | Speedup gegenüber V0 |
|
||
| --- | ----------------------- | -------------------- |
|
||
| V0 | 1.572 | 3.55 |
|
||
| V1 | 5.589 | 1.00 |
|
||
| V2 | 1.573 | 3.55 |
|
||
| V3 | 0.022 | 250.64 |
|
||
|
||
## 4. Korrektheit und Fazit
|
||
|
||
Zur Korrektheitsprüfung wurden V0, V1, V2 und V3 mit identischen Parametern ausgeführt. Die erzeugten Graustufenbilder wurden mit ImageMagick und der Metrik `AE` pixelweise verglichen. Von insgesamt 523776 Pixeln unterschieden sich V0 und V1 an 5864 Pixeln (1,120 %), V2 und V1 an 5523 Pixeln (1,054 %) sowie V3 und V1 an 5993 Pixeln (1,144 %).
|
||
|
||
Die Implementierungen erzeugen somit keine vollständig identischen Ergebnisse. Ursache sind unterschiedlich angeordnete Gleitkommaoperationen bei der Berechnung der komplexen Koordinaten. Da `res` nicht immer exakt als `float` darstellbar ist, entstehen kleine Rundungsabweichungen, die insbesondere nahe der Fraktalgrenze eine andere Fluchtiteration verursachen können.
|
||
|
||
Zusätzlich wurden nicht durch vier teilbare Bildbreiten, positive und negative Höhen sowie Grau- und Farbausgabe getestet. Die verbleibenden Pixel am Zeilenende wurden durch den skalaren Restpfad verarbeitet. Bei umgekehrter Bildhöhe traten ebenfalls geringe Rundungsabweichungen auf.
|
||
|
||
Die Messungen zeigen, dass SIMD die skalare Berechnung deutlich beschleunigt. V3 erreicht gegenüber V1 einen Speedup zwischen 13,71 und 250,64. Der größte Vorteil tritt bei hohen Iterationszahlen auf, da der Aufwand für die Thread-Verwaltung gegenüber der eigentlichen Berechnung weniger ins Gewicht fällt. V0 und V2 besitzen dagegen in mehreren Tests nahezu identische Laufzeiten, sodass die Thread-Parallelisierung den größten zusätzlichen Performanzgewinn liefert.
|
||
|
||
Insgesamt zeigt das Projekt die schrittweise Optimierung von einer skalaren Implementierung über SIMD bis zur Kombination aus SIMD und Multithreading. Grenzen bleiben Rundungsabweichungen, unterschiedlich lange aktive SIMD-Lanes, der Aufwand der Thread-Verwaltung und die Geschwindigkeit von RAM-Zugriffe.
|
||
|
||
## 5. Individuelle Beiträge
|
||
|
||
**Yashar Alan Zenker:**
|
||
|
||
**Nikola Granitsky:**
|
||
- Implementierung von SIMD- und Skalar-Optimierungen
|
||
- Implementierung des BMP-Exports
|
||
- Konzeption und Integration von Testfällen
|
||
- Refactoring und Bugfixing
|
||
|
||
**Cem Temizkan:**
|
||
- Implementierung des Rahmenprogramms
|
||
- Implementierung der Kommandozeilenverarbeitung
|
||
- Implementierung des Benchmarkings
|
||
- Beschreibung der mathematischen Grundlagen. |