Die Präsentation wird geladen. Bitte warten

Die Präsentation wird geladen. Bitte warten

Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Einführung.

Ähnliche Präsentationen


Präsentation zum Thema: "Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Einführung."—  Präsentation transkript:

1 Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Einführung

2 Optimierungstechniken in modernen CompilernEinführung2 Klassifizierung von Computersystemen Klassifizierung nach Flynn: Single Instruction Single Data (SISD): Ein einzelner Prozessor führt einen Befehlsstrom auf Daten in einem Datenspeicher aus. Multiple Instruction Single Data (MISD): Eine Sequenz von Daten aus demselben Speicher wird von mehreren Ausführungseinheiten bearbeitet, von denen jede einen eigenen Steuerfluss besitzt. Single Instruction Multiple Data (SIMD): Ein einzelner Befehl steuert mehrere Ausführungseinheiten, von denen jede Zugriff auf einen lokalen Speicher hat. Multiple Instruction Multiple Data (MIMD): Mehrere Steuerflüsse steuern mehrere Ausführungseinheiten, von denen jede Zugriff auf einen lokalen Speicher hat. Es existiert ein Steuerfluss im Programm. Es existieren mehrere Steuerflüsse im Programm. Alle Ausführungseinheiten greifen auf denselben Datenspeicher zu. Jede Ausführungseinheiten besitzt einen lokalen Datenspeicher (z.B. einen Cache).

3 Optimierungstechniken in modernen CompilernEinführung3 Einordnung von Prozessorarchitekturen Prozessororganisation SISDSIMDMISDMIMD Shared Memory Distributed Memory ClusterSymmetric Multiprocessor (SMP) Non-Uniform Memory Access (NUMA) Vector Processor Array Processor Uniprocessor ScalarSuperscalar Dynamic Scheduled Static Scheduled Static AllocationDynamic Allocation i386, i486 Pentium VLIW: Transmeta Crusoe, Philips TriMedia Geclusterte VLIWs Dual-Core Pentium Itanium TMS320C62x

4 Optimierungstechniken in modernen CompilernEinführung4 Skalarer Prozessor ohne Pipeline Typische Optimierungen des Compilers: Registerdruck minimieren Geeigneten Zielcode auswählen Steuerwerk Registerbank ALU Speicher ldm (r8) r0 ldm (r9) r1 ldm (r10) r2 add r0,r1 r0 add r0,r2 r0 … use r8,r9,r10 ldm (r8) r0 ldm (r9) r1 add r0,r1 r0 ldm (r10) r1 add r0,r1 r0 … use r8,r9,r10 ldc #8 r0 add r0,r8 r0 ldm (r0) r1 ldm (r8+8) r1 Speicher Schematischer Aufbau: Hoher Registerdruck:Geringer Registerdruck: Schlechte Codeauswahl:Bessere Codeauswahl:

5 Optimierungstechniken in modernen CompilernEinführung5 Skalarer Prozessor mit Befehlspipeline Typische Optimierungen des Compilers: Registerdruck minimieren Geeigneten Zielcode auswählen Pipeline-Hazards vermeiden Registerbank ALU Speicher FE/DE Speicher DE/EX EX/MEM Steuerwerk MMU MEM/WB ldm (r8) r0 ldm (r9) r1 stall add r0,r1 r0 ldm (r10) r2 stall add r0,r2 r0 ldm (r8) r0 ldm (r9) r1 ldm (r10) r2 stall add r0,r1 r0 stall add r0,r1 r0 Schematischer Aufbau: Schlechte Befehlsanordnung: Bessere Befehlsanordnung:

6 Optimierungstechniken in modernen CompilernEinführung6 Superskalarer Prozessor Typische Optimierungen des Compilers: Registerdruck minimieren Geeigneten Zielcode auswählen Umordnung der Operationen, um Abhängigkeiten zwischen Operationen im Befehlspuffer zu minimieren. Registerbank ALU Speicher DE1/DE2 DE2/EX EX/MEM Steuerwerk MMU ALU FE/DE1 Speicher Befehlspuffer add r0,r1 r2 add r0,r2 r2 add r0,r3 r4 add r0,r4 r4 add r0,r1 r2 add r0,r3 r4 add r0,r2 r2 add r0,r4 r4 Schlechte Befehls- anordnung für Puffer mit Kapazität 2: Schematischer Aufbau: Bessere Befehls- anordnung für Puffer mit Kapazität 2:

7 Optimierungstechniken in modernen CompilernEinführung7 VLIW Typische Optimierungen des Compilers: Registerdruck minimieren Geeigneten Zielcode auswählen Pipeline-Hazards vermeiden Feingranulare Parallelität erkennen und Operationen statisch parallelisieren. Registerbank ALU Speicher FE/DE DE/EX EX/MEM Steuerwerk MMU ALU Speicher add r0,r1 r2 add r0,r2 r2 add r0,r3 r4 add r0,r4 r4 add r0,r1 r2 | add r0,r3 r4 add r0,r2 r2 | add r0,r4 r4 Schematischer Aufbau: Sequentieller Programmcode: Parallelisierter Programmcode:

8 Optimierungstechniken in modernen CompilernEinführung8 SMP Typische Optimierungen: Grobgranulare Parallelität erkennen und das Programm in Threads aufteilen, so dass wenig Synchronisation zwischen den Threads erforderlich ist. Registerdruck minimieren Geeigneten Zielcode auswählen Pipeline-Hazards vermeiden call f call g call f Registerbank ALU FE/DE Speicher DE/EX EX/MEM Steuerwerk MMU MEM/WB Registerbank ALU FE/DE Speicher DE/EX EX/MEM Steuerwerk MMU MEM/WB Bus ldc #100 r0 loopHead: … dec r0 cmp r0,#0 jnz loopHead ldc 100 r0 loopHead: … dec r0 cmp r0,#50 jg loopHead ldc 50 r0 loopHead: … dec r0 cmp r0,#0 jnz r0 loopHead Cache gemeinsamer Speicher Schematischer Aufbau:Sequentieller Code:Code Proc1:Code Proc2: call g Sequentieller Code:Code Proc1:Code Proc2:

9 Optimierungstechniken in modernen CompilernEinführung9 Warum soll der Compiler optimieren? Optimierungen auf Quelltextebene (z.B. durch den Programmierer) sind möglich, machen es aber erforderlich, dass der Quelltext für jede Zielarchitektur optimiert wird. Verschiedene Optimierungen, die auf Zielcodeebene erforderlich sind, lassen sich in einer Hochsprache nicht formulieren (z.B. Registerplanung): Statisch geplante Architekturen: Compiler führt Scheduling und Allokation durch – auf Quelltextebene in der Regel nicht ausdrückbar Dynamisch geplante bzw. skalare Architekturen Compiler kann Hazards vermeiden helfen und Pipeline besser füllen Nur ein kleines Fenster für die Optimierung in Hardware; Compiler kann optimierbaren Code in dieses Fenster schieben SMP Compiler verteilt Programmcode und macht Parallelisierung möglich Programmiersprachen besitzen sequentielle Semantik; Geeignete Form der Parallelität muss durch den Compiler erkannt werden: feingranular, grobgranular.

10 Optimierungstechniken in modernen CompilernEinführung10 Demonstration dieser Problematik an einem Beispiel: Matrixmultiplikation Optimal für eine skalare Architektur. Ergebnis der Multiplikation wird im Register für t akkumuliert. for i = 1 to 100 step 1 do for j = 1 to 100 step 1 do t = 0.0; for k = 1 to 100 step 1 do t = t + a[j][k] * b[k][i] od c[j][i] = t; od i = 1 iLoop: j = 1 jLoop: t = 0.0; k = 1 kLoop: t = t + a[j][k] * b[k][i] k = k + 1 if k <= 100 then goto kLoop c[j][i] = t; j = j + 1 if j <= 100 then goto jLoop i = i + 1; if i <= 100 then goto iLoop

11 Optimierungstechniken in modernen CompilernEinführung11 Was kann parallel ausgeführt werden? for i = 1 to 100 step 1 do for j = 1 to 100 step 1 do t = 0.0; for k = 1 to 100 step 1 do t = t + a[j][k] * b[k][i] od c[j][i] = t; od Basisblock enthält keine nennenswerte Parallelität Iterationen der k-Schleife können nicht parallel ausgeführt werden: Iteration k+1 benötigt Wert von t aus Iteration k. Iterationen der j-Schleife können nicht parallel ausgeführt werden: Benutzung derselben Variablen t. Iterationen der i-Schleife können nicht parallel ausgeführt werden: Benutzung derselben Variablen t. b ac j k k i t

12 Optimierungstechniken in modernen CompilernEinführung12 t Scalar Expansion Basisblock enthält keine nennenswerte Parallelität Iterationen der k-Schleife können nicht parallel ausgeführt werden: Iteration k+1 benötigt Wert t[j] aus Iteration k. Iterationen der j-Schleife können parallel ausgeführt werden, weil a und b nur gelesen werden und Akkumulation in unterschiedliche Elemente von t erfolgt. Iterationen der i-Schleife können nicht parallel ausgeführt werden: Benutzung derselben Variablen t. b ac j k k i for i = 1 to 100 step 1 do for j = 1 to 100 step 1 do t[j] = 0.0; for k = 1 to 100 step 1 do t[j] = t[j]+a[j][k]*b[k][i] od c[j][i] = t[j]; od t[j] for i = 1 to 100 step 1 do for j = 1 to 100 step 1 do t = 0.0; for k = 1 to 100 step 1 do t = t + a[j][k] * b[k][i] od c[j][i] = t; od

13 Optimierungstechniken in modernen CompilernEinführung13 Loop-Distribution for i = 1 to 100 step 1 do for j = 1 to 100 step 1 do t[j] = 0.0; od for j = 1 to 100 step 1 do for k = 1 to 100 step 1 do t[j] = t[j]+a[j][k]*b[k][i] od for j = 1 to 100 step 1 do c[j][i] = t[j]; od t b ac j k k i for i = 1 to 100 step 1 do for j = 1 to 100 step 1 do t[j] = 0.0; for k = 1 to 100 step 1 do t[j] = t[j]+a[j][k]*b[k][i] od c[j][i] = t[j]; od Zuerst Vektor t initialisieren. Werte in t berechnen. Werte aus t nach c zurück schreiben. Initialisieren, Berechnen und Zurückschreiben wurde separiert; kann aber nicht parallel ausgeführt werden. Initialisieren, Berechnen und Zurückschreiben geschieht Elementweise in t.

14 Optimierungstechniken in modernen CompilernEinführung14 Loop-Interchange for i = 1 to 100 step 1 do for j = 1 to 100 step 1 do t[j] = 0.0; od for k = 1 to 100 step 1 do for j = 1 to 100 step 1 do t[j] = t[j]+a[j][k]*b[k][i] od for j = 1 to 100 step 1 do c[j][i] = t[j]; od t b ac j k k i Iterationen der inneren Schleife können parallel ausgeführt werden. for i = 1 to 100 step 1 do for j = 1 to 100 step 1 do t[j] = 0.0; od for j = 1 to 100 step 1 do for k = 1 to 100 step 1 do t[j] = t[j]+a[j][k]*b[k][i] od for j = 1 to 100 step 1 do c[j][i] = t[j]; od Keine nennenswerte Parallelität in der inneren Schleife, da jede Iteration den Wert t[j] aus der vorigen Iteration benötigt.

15 Optimierungstechniken in modernen CompilernEinführung15 Möglichkeit der Vektorisierung (idealisiert) for i = 1 to 100 step 1 do t[1..100] = 0.0; for k = 1 to 100 step 1 do t[1..100] = t[1..100]+a[1..100][k]*b[k][i] od c[1..100][i] = t[1..100]; od for i = 1 to 100 step 1 do for j = 1 to 100 step 1 do t[j] = 0.0; od for k = 1 to 100 step 1 do for j = 1 to 100 step 1 do t[j] = t[j]+a[j][k]*b[k][i] od for j = 1 to 100 step 1 do c[j][i] = t[j]; od t b ac j k k i Vektoroperation erfordert die parallele Ausführbarkeit der Operationen auf den Elemente des Vektors. Damit sind diese Operationen parallel auf einem superskalaren nicht-Vektor Prozessor ausführbar.

16 Optimierungstechniken in modernen CompilernEinführung16 Möglichkeit der Vektorisierung (praktisch) for i = 1 to 100 step 1 do t[1..100] = 0.0; for k = 1 to 100 step 1 do t[1..100] = t[1..100]+a[1..100][k]*b[k][i] od c[1..100][i] = t[1..100]; od for i = 1 to 100 step 1 do for j = 1 to 100 step 32 do t[j..j+31] = 0.0; od for k = 1 to 100 step 1 do for j = 1 to 100 step 32 do t[j..j+31] = t[j..j+31]+a[j..j+31][k]*b[k][i] od for j = 1 to 100 step 32 do c[j..j+31][i] = t[j..j+31]; od t b ac j k k i

17 Optimierungstechniken in modernen CompilernEinführung17 Ausführung auf VLIW-Prozessor mit N Ausführungseinheiten for i = 1 to 100 step 1 do for j = 1 to 100 step N do t[j] = 0.0;... ; t[j+N-1] = 0.0; od for k = 1 to 100 step 1 do for j = 1 to 100 step N do t[j] = t[j]+a[j][k]*b[k][i];... t[j+N-1] = t[j+N-1]+a[j+N-1][k]*b[k][i]; od for j = 1 to 100 step N do c[j][i] = t[j];... c[j+N-1][i] = t[j+N-1]; od N Multiplikationen und Additionen können parallel ausgeführt werden. for i = 1 to 100 step 1 do for j = 1 to 100 step 32 do t[j..j+31] = 0.0; od for k = 1 to 100 step 1 do for j = 1 to 100 step 32 do t[j..j+31] = t[j..j+31]+a[j..j+31][k]*b[k][i] od for j = 1 to 100 step 32 do c[j..j+31][i] = t[j..j+31]; od

18 Optimierungstechniken in modernen CompilernEinführung18 t1 Matrixmultiplikation für SMP mit zwei Prozessoren for i = 1 to 100 step 1 do for j = 1 to 100 step 1 do t = 0.0; for k = 1 to 100 step 1 do t = t + a[j][k] * b[k][i] od c[j][i] = t; od for i = 1 to 50 step 1 do for j = 1 to 100 step 1 do t0 = 0.0; for k = 1 to 100 step 1 do t0 = t0 + a[j][k] * b[k][i] od c[j][i] = t0; od for i = 51 to 100 step 1 do for j = 1 to 100 step 1 do t1 = 0.0; for k = 1 to 100 step 1 do t1 = t1 + a[j][k] * b[k][i] od c[j][i] = t1; od t0 b a j k k i

19 Optimierungstechniken in modernen CompilernEinführung19 Grob- vs. feingranulare Parallelität for i = 1 to 100 step 1 do for j = 1 to 100 step 1 do t[j] = 0.0; od for j = 1 to 100 step 1 do for k = 1 to 100 step 1 do t[j] = t[j]+a[j][k]*b[k][i] od for j = 1 to 100 step 1 do c[j][i] = t[j]; od t b ac j k k i Matrixmultiplikation vor Loop-Interchange (keine feingranulare Parallelität in der inneren Schleife): for j = 1 to 50 step 1 do for k = 1 to 100 step 1 do t[j] = t[j]+a[j][k]*b[k][i] od for j = 51 to 100 step 1 do for k = 1 to 100 step 1 do t[j] = t[j]+a[j][k]*b[k][i] od Aber äußere Schleife kann auf zwei verschiedenen Prozessoren verteilt werden. t[j]

20 Optimierungstechniken in modernen CompilernEinführung20 Grob- vs. feingranulare Parallelität for i = 1 to 100 step 1 do for j = 1 to 100 step 1 do t[j] = 0.0; od for k = 1 to 100 step 1 do for j = 1 to 100 step 1 do t[j] = t[j]+a[j][k]*b[k][i] od for j = 1 to 100 step 1 do c[j][i] = t[j]; od t b ac j k k i Aufteilen der äußeren Schleife auf verschiedene Prozessoren führt zu gleichzeitigem Schreiben derselben Elemente in t. Ist also nicht möglich. Matrixmultiplikation nach Loop-Interchange (viel feingranulare Parallelität in der inneren Schleife):

21 Optimierungstechniken in modernen CompilernEinführung21 Aufgeworfene Fragen Unter welchen Umständen ist eine bestimmte Transformation zulässig? Welche Transformationen erzeugen fein granulare Parallelität, grob granulare Parallelität? Wie kann die erzeugte fein granulare Parallelität in superskalaren Prozessorarchitekturen genutzt werden? Wie kann die erzeugte grob granulare Parallelität in SMP Architekturen genutzt werden?

22 Optimierungstechniken in modernen CompilernEinführung22 Aufbau der Vorlesung Einleitung Grundlagen Aufbau eines Compilers Überblick über die Analysephase Vorgehen bei einfacher Synthesephase Zwischencodeformate Datenflussanalyseschema Modellierung von Datenabhängigkeiten Abhängigkeitsanalyse

23 Optimierungstechniken in modernen CompilernEinführung23 Aufbau der Vorlesung Optimierungstechniken für DSPs und Mikrocontroller Globale Registerallokation Scheduling-Techniken Code-Selektion Optimierunbgstechniken für superskalare Prozessoren Erzeugung fein granularer Parallelität Trade-Off Registerallokation/ILP Statische/Dynamische Parallelisierung HW-Support für bessere statische Parallelisierung Region-Based-Scheduling Global Code Motion Traces, Superblöcke, Hyperblöcke Modulo Scheduling IF-Conversion

24 Optimierungstechniken in modernen CompilernEinführung24 Aufbau der Vorlesung Optimierungstechniken für SMPs Erzeugung grob granularer Parallelität Parallelisierung ohne Synchronisierung Parallelisierung mit Synchronisierung (OpenMP)


Herunterladen ppt "Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Einführung."

Ähnliche Präsentationen


Google-Anzeigen