Gut, heute habe ich als Thema also noch mal ein bisschen Ergänzung zu Parallelarchitekturen.
Und zwar eine Art von Parallelität, Pipelining,
war nun vorgestern schon dran, also sagen wir so als einfachste Variante.
Hier werde ich jetzt noch mal so ein bisschen allgemeinen Überblick geben,
welche Arten von Parallelität es gibt, die wir teilweise auch benutzen,
was teilweise dann aber eben auch so in den Bereich des High-Performance-Computing reingeht,
wenn man sich dann eben wirklich solche richtigen Groß-Superrechner ansieht.
Ja, wofür braucht man das Ganze? Wirklich jetzt bei entsprechend aufwendigen Sachen,
gerade so im Simulationsbereich, nicht klassische Beispiele,
sind dann eben auch immer sowas wie Wettervorhersage, Gehensequenzierung und so weiter,
hat man eben entsprechende Anforderungen an die Rechenleistung, dann bei Datenbanken,
Transaktionssystem, Suchmaschinen wären dann eben auch klassische Anwendungen für entsprechend aufwändige Großrechner oder eben Clusteranlagen.
Und gut bei einigen oder bei entsprechenden großen Projekten in der Softwareentwicklung
wird sowas dann entsprechend eingesetzt und das,
was ich jetzt noch so aus dem eigenen Umfeld dann teilweise auch noch kenne,
Hardwareentwurf, Schaltungsentwurf, weil auch das gehört dann eigentlich nachher in den Bereich der Simulation.
Ich weil man sagt, ich entwerfe jetzt eben irgendeinen Prozessor mit
mehreren Milliardentransistoren oder was weiß ich, wie vielen hundert Millionen an Gattern.
Nicht bevor man das also in Silizium gießt,
wird das Ganze dann eben auch erstmal richtig simuliert und eben geguckt, ob das tut.
Und das macht man dann also auch nicht,
also auf irgendeinem Standard-PC oder eine gut ausgestatteten Workstation,
sondern das macht man also auch in irgendwelchen Rechenclustern,
wo dann entsprechend viel Hardware-Leistung dann also auch dahinter steht.
Wie gesagt, Grundvoraussetzung Performance eines einzelnen Prozesses begrenzt. Und wenn ich es eben schaffe,
jetzt also von den Algorithmen her das Ganze so aufzubauen,
dass das Programm quasi oder der Algorithmus und das Problem partitioniert
werden kann und ich das dann eben auf mehrere Prozessoren aufteilen kann,
kann man da entsprechend viel machen.
Was ich da an Fragestellungen jetzt natürlich immer ergibt, ist, wie funktioniert das Ganze jetzt?
Wie sehen die Prozessoren aus oder wie sieht da dann überhaupt das Computing-Modell aus? Wir unterhalten,
die sich untereinander, da werde ich dann nachher noch kurz drauf eingehen,
weil da gibt es auch so klassische Herangehensweisen,
Shared-Memory oder eben Message-Passing und Wie wird das Ganze dann eben programmtechnisch unterstürzt,
beziehungsweise wie programmiert man dann eben sowas auch? Gut,
hier nur noch mal einige allgemeine Begriffe, Antwortzeit ist letztendlich immer das,
was als Zeit vergeht, zwischen Programmstaat und dem Programm Ende,
inklusive aller IO-Operation, das ist dann auch das,
was man dann immer so klassisch als Execution Time oder Warclock Time nimmt,
beziehungsweise das was man dann auch mit rauslesen kann,
wenn ich mir also irgendwie zum Beispiel jetzt hier unter Unix-System,
also irgendein Programm mit dem Befehl time davor noch starte.
Nicht, dann kriegt man zum Beispiel auch klassisch so eine Ausgabe,
wo ich dann eben Antwort seid bzw. Ausführungszeit draus auslesen kann,
dann habe ich hier nämlich im Prinzip so was wie die User-CPU-Time,
die System-CPU-Time, das heißt also das,
was dann also noch an Zeit jetzt für irgendwelche System-IO bzw. Zyklussachen drauf ging,
dann eben die eigentliche Elaps-Time und dann eben entsprechend der Auslastung,
wie viel hier vorn dann,
also das Programm wirklich darauf gelaufen ist.
Also wie gesagt, die Labstime wäre dann die Antwortzeit,
die Summe aus dem dann die Ausführungszeit.
Dann findet man häufig immer noch als Begriff Durchsatz.
Da geht es dann eben darum, wie viel Programme oder wie
viele Jobs ich in einer bestimmten Zeiteinheit erledigen kann.
Das ist jetzt eigentlich wieder was,
was also im Meer für irgendwelche Anwendung interessant ist,
wo es also jetzt zum Beispiel um irgendwie sowas wie Datenbanken,
Transaktionssysteme und sowas geht. Nicht also uns, sagen wir mal,
am heimischen Rechner interessiert natürlich erstmal irgendwie die Antwortzeit.
Ich starte das Programm, dann soll sich möglichst schnell was getan haben. Nicht,
wenn ich also irgendwie einen Webservice betreibe,
dann geht es eigentlich eher darum, dass man jetzt nicht sagt,
also ein einzelner Job soll möglichst schnell laufen,
sondern ich garantiere jetzt also beispielsweise,
wenn ich als Webposter auftrete in meinem Kunden,
dass so und so viele Anfragen in einer bestimmten Zeiteinheit bearbeitet werden können.
Nicht, dass dann eben typischerweise
eher solche Sachen
Dann war es jetzt also auch gleich als Begriff immer noch weiterfahren wird, ist Speed-up. Sprich,
wenn ich jetzt also zwei unterschiedliche Variantenrealisierung habe, die miteinander vergleiche,
also ist das dann einfach im Prinzip der Quotent irgendwie jetzt von zwei Implementationen hinsichtlich der Antwortzeit.
So, wenn man jetzt ein System hat und man sagt jetzt,
okay, Talgorithmus, läuft jetzt irgendwie so und so lange,
so und so schnell auf dem und dem Rechner,
wie kann ich da jetzt die Performance verbessern, beziehungsweise das entsprechend beeinflussen.
Dann kann man jetzt erstmal sagen, gut, Das,
was ich erstmal ganz stumpf gerechnet als Ausführungszeit ergibt,
ist die Anzahl der Befehle multipliziert mit der Zeitprobefehl.
Und da kann ich jetzt natürlich sagen, okay,
jeden dieser Faktoren kann ich einzeln versuchen, irgendwie zu minimieren.
Ich kann also einmal sagen, mit weniger Befehlen mache ich dieses hier kleiner.
Was ich natürlich erstmal primär irgendwo durch meinen Algorithmus beeinflusse,
wie gut oder wie schlecht ich also ein Problem jetzt dort umgesetzt habe,
Indirekt dann natürlich dadurch, dass ich sage, okay,
wenn ich einen entsprechend effizienteren Compiler habe oder irgendwann Piler-Optimierung einschalte und dadurch dann also weniger Code brauche, wirkt sich das natürlich auch aus.
Und in dem Sinne erstmal weniger Befehle hat man,
also wenn man jetzt sagt, also ich habe sowas wie einen Befehlssatz,
derentsprechend von den Befehlen her mehr kann, was dann eben erstmal so in Richtung Cis-Befehle geht. Weniger Zeit pro Befehl,
sprich jeder zweite Faktor wird erreicht, als erstes erstmal durch Moore's Law,
bessere Technologie, Prozessoren werden immer schneller,
immer schneller getaktet und demzufolge habe ich dadurch dann also erstmal den großen Gewinn,
dann intelligenter Architekturen, also sprich das,
was dann eben so in Pipelining mit drin ist, das,
was dann in Bezug auf die Sparcher Hierarchie sich durch Cashes ergibt,
das führt eben dazu,
dass also ein Befehl oder ein insgesamt dann eben gesehen ein Programm entsprechend schneller abgearbeitet werden kann und Das,
was dann eben jetzt hier wieder in Richtung Riss geht,
wenn ich jetzt sage, ich habe einfache Befehle,
die ich eben entsprechend schnell effizient abarbeiten kann,
wirkt sich das dahingehend aus?
Und insgesamt auf dem Befehlssatz bezogen ist das dann eben letztendlich immer so ein Trade-Off nicht,
also habe ich hiermit mehr Gewinn oder habe ich hiermit mehr Gewinn,
so zahlt sich das aber eben so aus,
dass also auch jetzt eben hin Blick auf die Architekturen,
eigentlich sowas wie reskartige Befehlsätze da eben entsprechend deutlich effizienter sind,
beziehungsweise deutlich mehr Gewinn bringen,
als wenn ich jetzt sagen würde,
ich hätte jetzt also noch irgendwelche Sis-Konzepte.
Gut, und dann kann man jetzt natürlich sagen,
wenn der Algorithmus das erlaubt, kann ich versuchen zu parallelisieren.
Das können sein Superskalare-Architekturen, sage ich gleich was dazu,
was sich dahinter verbirgt, also sprich,
dass ich in einer CPU erstmal mehrere Recheneinheiten habe und dadurch jetzt
nicht nur pro Takt ein Befehl oder mit einer Pipeline,
der Pipeline tiefe N-N-Befehle in Bearbeitung habe,
sondern jetzt eben noch mehr Befehle gleichzeitig in Bearbeitung habe.
Oder im Parallelrechnerkonzepte steht dann für das Akronym, ergibt sich dann quasi immer aus den Anfangsbuchstaben,
Single Instruction, Multiple Data, klassische Vektorrechner. Nicht,
wo ich also zum Beispiel so ein paar Beispielen,
Matrix-Motiplikationen oder sowas sage, ich habe einen Befehl,
der soll dann aber jetzt eben nicht nur auf einen einzigen Wert,
einen Skala angewandt werden, sondern direkt auf ein ganzes Feld,
was dann parallel immer gleichartig bearbeitet wird.
Deswegen Single Instruction, Multiple Data oder eben richtige Parallelrechner,
wo dann also auch noch unterschiedliche Algorithmen oder Verfahren auf den Daten arbeiten, Multiple Instruction, Multiple Data.
Was erreiche ich jetzt mit den Verbesserungen? Das kann man dann,
also sagen wir mal,
erst mal schön berechnen oder sich überlegen mit Amdals-Gesetz,
wurde Auch schon relativ alt, 1997 von Jim Annal,
also einen der Entwickler der damaligen IBM-Architektur, mitentwickelt,
wo es also eigentlich erstmal darum ging, zu sagen,
ich habe jetzt nicht nur eine CPU, sondern entsprechend mehrere,
also im Prinzip, da ging das um die Parallelrechnerentwicklung,
die das, was sie an Konsequenzen da draußen ergibt,
gilt aber im Prinzip ganz allgemein.
Und zwar kann man dort sagen, wie wirkt sich die Beschleunigung oder Speed-up aus,
wenn ich jetzt nicht das gesamte Problem,
sondern nur ein Teil des Problems schneller mache.
Was, also sag mal, typischerweise in den Algorithmen,
wenn überhaupt, dann nämlich eigentlich der Fall ist.
Und dann sage ich, ich habe also ein erstes System,
was also ein Programm P irgendwie berechnet.
In diesem Programm enthalten ist eine Funktion,
die parallelisiert werden kann, die jetzt irgendwie im Bereich zwischen
0 und 100
Prozent der Gesamtberechnungszeit belegt
Ich habe ein zweites System, wo ich das dann eben
entsprechend parallelisiert habe, schneller gemacht habe. Das heißt also,
diese Funktion wurde dann eben durch eine Funktion x Strich ersetzt,
die dann eben irgendwie um einen Faktor S,
was dann eine Speedup ist, schneller ist.
Und da natürlich jetzt nicht die Verbesserung jetzt also auf die Gesamtberechnung des Programms geht,
also außer ich setze hier eins an,
sondern eben nur auf irgendeinen Teil davon
Ergibt sich dann eben ein Gesamtspeed-up als eins
durch 1 minus 11 plus F durch SX.
Was verbirgt sich hinter dieser Formel, beziehungsweise überhaupt jetzt erstmal hinter diesem Speed-up?
Also hier ist das Ganze nochmal so ein bisschen grafisch aufgezeigt.
Also ich habe, wie gesagt, nur einen Teil F
des Gesamtproblems, den ich beschleunigen kann. Das heißt also
ein Anteil von 1 minus F kann nicht beschleunigt werden,
sondern die Beschleunigung wirkt eben nur auf Den Anteil F,
nicht demzufolge, wird da dann die Zeit, um SX beschleunigt.
Das heißt, die Gesamtzeit da ist dann eben F durch SX.
Hier wird die Zeit nicht beschleunigt. Das ist das,
was da eingeht. Klassisch ist da dann eben anzusetzen,
dass ich sage, hier Gesamtzeit, mein Problem,
diesen Teil F könnte ich eben potenziell parallelisieren.
Diesen Teil 1-F
eben nicht
Wenn ich jetzt nicht nur eine, sondern als Beschleunigungsfaktor es
quasi einbringen kann. Ich habe jetzt also mehrere Recheneinheiten,
heißt es dann eben,
dass natürlich dann für die Gesamtzeit dieser Teil hiervon nicht beeinflusst wird und das,
was dann eben hier als Teil F ist,
dann entsprechend durch die Anzahl N geteilt werden muss und demzufolge schrumpft dann natürlich hier dieser Zeitanteil,
der dann insgesamt benötigt oder die Zeit,
die dann insgesamt benötigt wird,
dann eben hier
entsprechend klein ein
So, wann ist das Ganze besonders effizient, logischerweise,
wenn dieser parallelisierbare Anteil F möglichst groß ist?
Demzufolge ergibt sich da dann quasi als Konsequenz immer,
dass die Optimierung dann eigentlich nur für die,
in Anführungszeichen, relevanten Operationen gilt, beziehungsweise umgangssprachlich gesagt,
man soll das optimieren, was am häufigsten vorkommt.
Ich optimiere den häufigsten Fall, dann hast du den größten Gewinn dabei.
Nicht, das ist also nochmal ganz arg,
wenn man ein will, dieses Verfahren,
was also in beliebig vielen Problemen
so auftreten
Die ursprüngliche Idee, wie gesagt,
ist jetzt eben auf Parallelrechner mit Endprozessoren bezogen,
in dieser Formel ist das Ganze hier nochmal um so eine Funktion K von N erweitert,
da ist das dann nochmal ein bisschen realistischer gemacht,
in dem Sinne, dass ich dann eben sage,
wenn ich jetzt ein Problem oder ein Algorithmus habe,
ein Großteil davon könnte ich jetzt also paralysieren,
schmeißt das ja dann also quasi jetzt auf mehrere CPUs,
die dann parallel rechnen, habe ich da dann zwar den entsprechenden Speed-up,
ich waß ich aber natürlich da noch irgendwo mit berücksichtigen muss,
ist also gegebenenfalls also noch irgendein Verwaltungsoverhead,
um erstmal dafür zu sorgen,
dass die Talberechnung auf den einzelnen CPUs entsprechend mit Daten versorgt werden,
angestoßen werden und hinterher die Ergebnisse auch wieder zusammengesammelt werden.
Nicht, dass es dann eben hier in irgendeiner Funktion K von N mit berücksichtigt,
was dann eben den Kommunikationsoverhead zwischen den Prozessoren letztendlich irgendwie berücksichtigt.
Gut, wenn man das erstmal weglassen lässt und jetzt also
wirklich nur mit der reinen Formel hier rechnet,
wie wirkt sich das aus?
Also angenommen mein Parallelisierbarer Anteil ist sehr klein
Zehn Prozent. Und ich setze ihn jetzt nicht ein,
Prozesse ein, sondern zehn Prozessoren.
Dann ist der Gesamtspeedup 1,1. Das heißt, meine Ergebnis wird,
oder die Berechnung wird zehn Prozent schneller.
Da sieht man also, das lohnt sich nicht.
Hier habe ich jetzt also quasi klassisches System,
jetzt irgendwie zwei Prozessoren, 50 Prozent parallelisierbar.
Speedup ist
90 Prozent parallelisierbar bei zwei Prozessoren, Speed Up bis 1,82. Das heißt also,
das, was man da dann eben schon mal deutlich sieht,
ist natürlich, dass je größer dieser Anteil,
dieser Paralysierbare Anteil F ist, umso mehr lohnt sich das Verfahren überhaupt.
Und logischerweise grenzwertig kann ich natürlich dann als Speed Up sowieso
nur die Anzahl der Prozessoren hier erreichen.
Nicht, aber um einfach jetzt erstmal drastisch zu zeigen,
nicht, wenn man jetzt also hört,
ich habe jetzt hier irgendeinen Superrechner und irgendwo so ganz am Anfang der Veranstaltung.
Im Oktober hatte ich ja also auch mal irgendwie so die Folien
so von den Top 500 Rechnern, also irgendwo aufliegen,
wo man dann liest.
Also ich habe da also ungefähr so ein Rechensystem mit 65.000,
535 Rechenkern. Ich dann denke mir, oh,
das muss ja unendlich schnell sein.
Hier hat man eben wirklich mal so für Rechnersysteme das eben mal durchgespielt.
Also ich habe 80 Prozent meines Algorithmus kann ich parallelisieren.
Nur 20 Prozent müssen auch irgendwo sequenzell laufen.
Und ich setze jetzt nicht ein,
sondern 4.536 Prozessoren ein, dann ist das Ganze
genau fünfmal so schnell
Nicht, das ist also dann wirklich das krasse Missverhältnis zwischen Hardwareaufwand und Geschwindigkeit zu wagst.
Selbst wenn ich jetzt hier 99 Prozent parallelisieren kann und
ich setze also dann irgendwie über 9000 Prozessoren ein,
also man gewinnt dann also einen knappen Faktor 100.
Nicht, dass es eben wirklich das, was,
wo man sieht, also das ist dann erstmal vergleichsweise ernüchternd.
Nicht hinzukommt, wenn ich jetzt also normalen Algorithmus nehme in Hochsprachenprogrammen,
habe ich dort eigentlich relativ wenig Parallelität inhärent mit drin
Wobei es ist jetzt natürlich immer eine gewagte Aussage,
weil das ist natürlich von problemabhängig,
nicht aber grob kann man jetzt erstmal sagen,
wenn ich jetzt versuche,
also irgendwas mit irgendwelchen Sräts noch weiter aufzuteilen und Prozesse,
die sich dann selber spawnen und forken,
in der Regel ist man da also im Bereich von maximal vier oder so.
Gut, hier ist das Ganze dann eben
auch nochmal so ein bisschen grafisch aufgeplottet,
sprich hier ganz stumpf einfach die Formel genommen
Zehn Prozessoren, das heißt also, er ist von x gleich 10,
der theoretisch maximale Speedup ist 10, den erreiche ich halt,
wenn da parallelisierbare Anteil bei 100 Prozent, also bei 1 liegt.
Und ansonsten kann man eben hier sehen,
wie das Ganze dann also hier entsprechend größer wird,
nicht allerdings dann eben auch erst nennenswert beispielsweise jetzt hier bei 90 Prozent und 10 Prozessoren erreicht dann,
also gerade mal so ein Speedup von 4. Hier,
da das Ganze jetzt quasi andersrum mal aufgezeigt,
die unterschiedlichen Linienfarben entsprechen dann quasi zu den Parallelisierbaren Anteil.
Im Idealfall 100 Prozent parallelisierbar. Das heißt, die Aufgabe kann ich komplett verteilen.
Habe ich natürlich logischerweise dann hier mit der Anzahl der Prozessoren
einen linearen Speed-up und kann dann eben sagen, okay,
mit zehn Prozessoren bin ich auch zehnmal so schnell.
Aber wenn ich jetzt also hier nur noch 90 Prozent parallelisieren kann,
dann bin ich also hier schon also auf der Grünlinie bei 80 Prozent,
also auf der entsprechenden, also dieser blauen Linie.
Und wenn ich also nur Die Hälfte meines Algorithmus parallelisieren kann,
nicht dann sieht man, also gut, man gewinnt hier was,
aber also ob ich dann acht oder neun oder zehn Prozessoren reinsetze,
das muss man dann also wirklich schon irgendwo ausrechnen und sieht das dann also in irgendwelchen Nachkommastellen,
dass sich da noch ein bisschen was tut,
aber das lohnt sich nicht.
Gut, hier das Ganze nochmal grenzwertig,
wenn ich jetzt eben sage, nicht was gewinne ich jetzt,
wenn ich theoretisch unendlich viel Rechenleistung zur Verfügung habe,
nicht und da sieht man eben auch,
dass das hier eigentlich letztendlich dann Richtig nur ansteigt,
wenn ich mich also hier irgendwie so oberhalb von 90 oder 95 Prozent Parallelisierbarkeit befinde.
Gut, das erstmal ganz allgemein,
so zu ein bisschen begriffen, beziehungsweise zu dem,
was dann da eben als Speedup nach Amdals Gesetz möglich ist.
Gut, wie läuft jetzt Parallelverarbeitung? Welche Möglichkeiten gibt es
da? Das, was er nun vorgestern kennengelernt haben.
Jetzt eben Parallelität im Sinne von Pipelining
Ich meine nicht das, dass ich hier so eine klassische Befehlspipeline reinbringe,
wo ich dann eben sage, okay,
ich kriege damit einen höheren Takt, ich kriege damit einen höheren Durchsatz.
Da wirkte ich das dann natürlich zum einen entsprechend aus,
welche anderen Architekturalternativen gibt es dann im Prinzip jetzt noch,
um zu sagen,
ich habe dann eben zusätzlich zu den Pipelining noch irgendwie Parallelmöglichkeiten.
Zum einen kann ich
sowas wie parallele Pipelines anliegen
Das heißt, hier im Bild zum Beispiel mal angedeutet,
dass ich sage, okay, also Instruction,
Fetch gibt es ja noch eine Einheit,
dann gibt es dann aber im Prinzip dann also zwei parallel arbeitende Pipeline-Einheiten und demzufolge dann insbesondere dann also auch noch parallel arbeitende Rechenwerk,
also spricht dann eben entsprechend noch mehrere Alus,
was denen dann hier entspricht, in der Terminologie aus dem Tarnbaum,
dass man da dann ebenentsprechend arbeitet,
Beispiel dafür war es im Prinzip so der erste Fancium-Prozessor,
den Intel rausgebracht hat,
der also im Prinzip so eine Architektur umgesetzt hat.
Nachteil bei sowas ist dann natürlich immer,
ich hatte ja schon das Thema der Hasar zwar im Pipelining angesprochen,
durch solche Parallelbearbeitung beziehungsweise generell Superskalarität habe ich da natürlich dann
also noch deutlich mehr mögliche Daten oder kontrollabhängigkeiten,
die dann also durch entsprechende Hardware quasi gegeneinander abgesichert werden müssen
Das, was man heutzutage eigentlich hat,
wo Intel dann also quasi mit dem Pentium 2 dann nämlich auch wieder zurückgegangen ist,
ist das,
was man eigentlich so allgemein ist als Superskalan-Prozessor oder Rechner bezeichnet,
wo ich dann eben sage,
ich habe jetzt hier nur in dem klassischen Pipelining erstmal jeweils nur die Stufen entsprechend einzeln.
Ich habe dann aber eben jetzt nicht nur eins,
sondern mehrere Rechenwerke oder Alus,
die dann entsprechend über irgendwelche Hardware-Einheiten,
die die Datenabhängigkeiten mit protokollieren,
verwaltet werden
Und klassisch dann eben natürlich, dass sie eben sagt,
ich habe nicht nur irgendwelche Indiger, sondern ich habe dann also Gleitkomma-Recheneinheiten.
Nicht von denen gab es dann mehrere,
dann gibt es eben noch spezielle Einheiten für Lot- und Store-Befehle,
beziehungsweise spezielle Einheiten für Adressberechnung, was implizit dann eigentlich hier dann mit drin steht.
Und inzwischen muss man eben sagen,
eigentlich alles, was an Prozessoren auf dem X86-Befehlsatz aufbaut,
arbeitet, mehr oder minder Superskalat, das heißt,
da habe ich dann eben auch entsprechend viele Parallelarbeitende,
Generell, ja, zwischen vier und zehn Recheneinheiten.
Man spricht dann auch immer noch vom Instruction-Level Parallelism,
weil es da dann natürlich darum geht,
dass ich dann jetzt nicht nur mit einem Takt eine Instruktion
quasi in die Ausführung oder in die Pipeline reinbringe,
sondern dann eben auch noch mehrere Instruktionen reinbringe,
die dann quasi parallel abgearbeitet werden
Und die Art und Weise, wie das geschieht,
passt,
geht dann eben im Prinzip also über diesen Scoreboard-Mechanismus,
wo dann also im Prinzip die Hardware-Einheit dafür sorgt,
dass eben geguckt wird,
welche Befehle brauchen welche Recheneinheiten erstmal und dann wird eben geguckt,
ist da also quasi jetzt eine entsprechende Recheneinheit frei,
beziehungsweise die werden denen dann also auch in so einem ersten Schritt quasi so eine Art Wartestation oder so eine extra Cue dann nur für diese Alu dann entsprechend reingelegt.
Und entsprechend verteilt. Und das kann dann eben dazu führen,
dass quasi in einem Pipeline-Takt, wenn ich jetzt sage,
ich habe jetzt, also wie jetzt hier in einem Beispiel,
beispielsweise jetzt also fünf Recheneinheiten.
Theoretisch maximal fünf Befehle in die Pipeline reingeschoben werden können,
im Worst Case, aber eben auch gar keiner.
Das wird dann eben wirklich dynamisch durch die Hardware bestimmt,
nicht in das Ganze nennt sich dann eben
Dass man sagt, dass ich jetzt eben hier entsprechend viele
Instruktionen anstoßen kann und maximal wert ist dann eben das.
Also das findet man dann häufig in Datenblättern. Instruction is
you band with, wo dann eben letztendlich dran steht,
wie viele Instruktionen letztendlich parallel angestoßen werden können.
Gut, das Konzept ist eigentlich bei allen modernen CPUs inzwischen
so umgesetzt. Nachteil oder Gefahrbar dabei ist aber natürlich,
dass dann im Prinzip das Hasard-Problem natürlich nochmal deutlich größer wird
Als Datenabhängigkeiten, die da dann eben auch mit auftauchen,
jetzt also bei diesen mehreren Recheneinheiten, höre dann häufig immer noch unterschieden,
also zwischen RAW, Read After Wright, Wright After Read,
Wright After Wright, wo es dann also eben letztendlich darum geht,
wenn jetzt mehrere CPUs oder nein, mehrere von den Rechten,
nein, nicht mehrere CPUs, das war falsch,
mehrere von den Recheneinheiten, jetzt also irgendwie auf Register drauf zugreifen,
ob da dann also noch zusätzliche Zeitbedingungen dazwischen einzuhalten sind.
Da kann man eben sagen, das,
was dann also als Reed After Wright auftaucht,
das ist dann ihm eigentlich noch mal das Beispiel,
was ich also jetzt am Mittwoch immer jeweils gebracht habe,
wo es also wirklich darum geht, ich habe irgendeinen Befehl,
der war es in einem Register zurückschreibt und irgendein späterer Befehl soll das lesen und das ist dann eben noch in einer Pipeline,
wo man dann eben gegebenenfalls mit Forwarding-Einheit dafür sorgen kann,
dass das Ganze Problem umschifft wird,
dass es dann eben die eigentlich echte Abhängigkeit Für diese Beispiele,
wo dann Wright After Reed oder Wright After Wright auftaucht.
Das sind eigentlich keine richtigen Datenabhängigkeiten, sondern geht es darum,
dass im Prinzip eigentlich Daten unabhängig voneinander sind,
der Compiler, aber jeweils immer die gleichen Register verwendet.
So, dagegen hilft dann als Mechanismus etwas,
was dann Register Renaiming ist, wo man dann eben sagt,
ich habe jetzt Zum einen die Register,
die wirklich jetzt als logische Register im Befehlssatz vorhanden sind,
nämlich das, was man jetzt also letztendlich im Assembler-Code sieht.
Sprich das, was der Grompaler rauswirft oder das,
was er jetzt eben in den Übungsaufgaben immer irgendwie aufgetaucht ist und nicht,
wo man sagt, okay,
ich habe da EAX und EBX und wie sie auch alle heißen mögen.
Nicht also da meine acht Register zur Verfügung.
Rein praktisch hat die Hardware aber eben teilweise
deutlich mehr Register
Die sehe ich als Programmierer nicht,
die sehe ich als Betriebssystem nicht oder sonst nicht, sondern das ist etwas,
was dann wirklich jetzt nur von irgendwelchen Hardware-Einheiten verwaltet wird,
wo dann quasi dynamisch diese zusätzlichen Register, die dann immer als Rename-Register bezeichnet werden,
dann also auf die logischen Register abgebildet werden.
Dahinter verbirgt sich dann eigentlich so grob die Idee,
dass ich sage, wenn ich also zum Beispiel jetzt nicht in Assembler,
sondern quasi im C-Code sowas habe,
Ich habe hier eine Zuweisung, tampt gleich A plus B,
Resalt ist gleich C plus Tamp und hier habe ich Tampt,
gleich D plus E und Resalt ist gleich meinetwegen tamp minus 11.
So, das, was ich da, was sich dahinter verbirgt,
ist, dass ich hier jeweils die Bezeichner Tamp habe, die aber eigentlich nichts miteinander zu tun haben.
Also hier in einem zweiten beiden Zahlen konnte ich das eben beliebig anders machen nennen. Nicht nur das ist dann eben etwas,
was dann automatisches Registerrenaming passiert,
dass ich die dann also quasi jetzt hier unterschiedlich benahmen sie und dann führt das Ganze dann eben dazu,
dass man dann quasi diesen Code,
der jetzt also nicht parallelisierbar ist, dann also so umsetzen kann,
dass ich also hier dann entsprechend Code habe,
der dann,
also auch wunderbar parallelisierbar wäre,
wo man dann eben die entsprechenden Talberechnungen hier und hier
dann eben parallel ausführen kann
Generell, wie gesagt, solche Superskalan-Pipelines sind dann noch ein bisschen komplizierter aufgebaut,
als jetzt ein normales Buypelining-Schema ist, sieht das dann eben so aus,
dass die dann eben jetzt nicht nur die klassischen fünf Stufen haben,
sondern eigentlich dann immer noch mehr. Das heißt,
ich habe dann also nicht nur irgendwie so Instruction Fatch,
sondern also habe hier dann in diesem Instruction-Code dann eben unter anderem auch dieses Register-Renaiming untergebracht,
dann gibt es etwas,
was ich dann immer Instruction Window nennt,
das ist dann quasi letztendlich sowas wie so ein Code-Bereich,
wo dann die entsprechenden Hardware-Einheiten jetzt erstmal gucken können von diesem Teil Code,
welche Datenabhängigkeiten sind zwischen welchen Anweisungen in diesem Code-Bereich vorhanden und welche Hardware-Anforderungen sind jetzt also von den einzelnen Befehlen aus angestoßen.
Das heißt also, brauchen die und die und die Befehle
jetzt eine Integr-Einheit und die brauchen jetzt irgendwie eine Fließkummer-Einheit und da soll jetzt irgendeine Pressberechnung stattfinden.
Und dann gibt es dann eben so einen Teil Issue,
wo dann abhängig davon das Ganze oder Teile dieses Codes dann eben auf die unterschiedlichen Ausführungseinheiten quasi unterteilt werden.
In der Regel liegt da dann also auch nochmal was dazwischen.
Execute und anschließend gibt es dann eben auch noch unterschiedliche Arten und Weisen,
wie dann also nachher das Ganze dann noch bei dem Ride Back behandelt wird,
weil Hier sage ich jetzt ja,
ich habe meinetwegen es in meinem Instruction-Fenster fünf Befehle,
die jetzt also irgendwie eine Indiger-Recheneinheit benötigen.
Ich habe jetzt aber meinetwegen nur zwei Indiger-Recheneinheiten zur Verfügung.
Das heißt, die kommen dort dann erstmal in irgendeine Warteschlange.
Ich habe dann aber irgendwo da drunter beispielsweise jetzt noch einen Befehl,
der jetzt also eine Fließkomerecheneinheit benötigt. Die Fließkomerecheneinheit ist frei,
dann kann es dazu führen,
dass also im Prinzip Die Reihenfolge der Anweisungen,
wie sie im Code steht, auf der CPU in anderer Reihenfolge ausgeführt wird,
weil also der Fließkommabefehl quasi direkt zur Abarbeitung kommt,
irgendein Befehl jetzt, also die indigital-rechen-einheitbar oder indigital-alu braucht,
erst noch irgendwo in dieser Warteschlange liegen muss,
bis eine frei geworden ist.
Dann ist es eben, dass wieder so eine Philosophiefrage sollen
hinterher quasi das Rideback der Ergebnisse in der Reihenfolge stattfinden,
wie sie wie die Befehle quasi ursprünglich mal im Assembler-Code standen,
dann nennt sich das Ganze In-Order-Execution.
Das heißt, da gibt es dann eben wieder eine Stufe namens Retire,
die dann also dafür sorgt, dass also quasi das Ergebnis dieser,
wenn ich jetzt bei diesem Beispiel bleibe, Fließkomma-Berechnung erst mal zurückerhalten wird.
Und erst wenn ursprünglich mal im Code davorstehen,
der Indisch der Berechnung abgeschlossen sind und die zurückgeschrieben wurden,
dann wird das Ergebnis zurückgeschrieben. Oder sage ich eben,
ich mache eine Out-of-Order-Execution, das heißt, wenn ein Befehl quasi hier raus ist, wird auch gleich das Ergebnis zurückgeschrieben. Gut,
das sind dann auch unterschiedliche Architektur-Philosophie-Fragen,
also mal hat das eine, mal hat das andere Vorteile,
nicht weil, was man sich denken kann,
das Ganze wirkt sich dann eben teilweise auch entsprechend jetzt wieder auf die Datenabhängigkeiten zwischen den Befehlen entsprechend aus und war es nur so in den Ende der 90er Jahre,
gab es da dann also gerade so mit dieser Order und Out of Order Execution,
also immer Zumindest werbetechnisch, also Elbit hat ja gefähigte,
zwischen AMD und Intel,
was nun eigentlich besser ist.
Und jeder hat dann also quasi jetzt irgendwo sich seine Beispiele konstruiert,
wo das eigene Konzept dann also deutlich schneller gewesen ist,
aber letztendlich kann man mal sagen,
also mal ist das eine besser mal als das andere besser.
Gut, da ist eigentlich erstmal nur so grob zu dem Verständnis,
was da dann noch dahinter ist. Gut, das Scaduling,
also hier ist es ganz nochmal so ein bisschen grafisch angedeutet.
Also ich habe hier meinen Code, der kommt dann
quasi hier einfach als einen Strom von Instruktion hier an.
Es gibt dann eben diesen Bereich, dieses Issue Windows,
das heißt also Instruktion die jetzt gerade gleichzeitig betrachtet werden.
Und dann wird eben geguckt, also gegebenenfalls, also auf welche
von den Rechen einhalten können, die verteilt werden. Nicht,
dass wir dann eben hier in dieser ISV-Unit gemacht und hinterher,
wenn das abgearbeitet ist, gibt es dann eben einen Bereich von Instruktionen,
der gerade in der Ausführung ist, beziehungsweise dann hinterher dann entsprechend zurückgeschrieben wird.
Gut, hier auch nur noch mal so ein paar von diesen Begriffen,
noch mal genauer unterteilt, aber das entspricht eigentlich schon mal dem, was ich gerade gesagt habe.
Da gibt es immer noch diesen Unterschied zwischen diesem Issue,
also dieser globalen Sicht der Befehle und dann eben einen eigentlichen Dispatch,
wo dann eben schon quasi jetzt unterteilt wurde, Der Befehl für die rechne einen Hardware oder der Befehl jetzt, also für die Fließkomma-Recheneinheit. Gut,
für jede Recheneinheit gibt es dann eben eigene Cues,
Reservation Station genannt, in denen dann also letztendlich die Instruktion gespeichert werden,
mit zugehörigen Operanten, gegebenenfalls nach irgendwelchen Zusatzinformationen,
beispielsweise jetzt über die Datenabhängigkeiten und wenn quasi dann alle Parameter bekannt sind,
alle Datenabhängigkeiten erfüllt worden sind,
dann wird eben die entsprechende Operation zur Ausführung gebracht,
sofern natürlich eine Alu passend dann frei ist und wie gesagt,
mit dem, wenn ich dann eben sowas wie eine In-Order Execution machen möchte,
dann brauche ich eben noch so eine Retaria-Stufe,
die dann also quasi dann hinterher das Ganze wieder in die richtige Reihenfolge bringt.
Gut, das Ganze nennt sich in der Literatur dann immer dynamisches Scheduling,
gibt es dann also auch ein entsprechenden Skeduling-Algorithmus,
der heißt ja immer Thomas Solo-Skeduling, also im Sprach,
auch von dem Herrn Huberto Thomas Solo,
der das Ganze da nämlich auch mal umgesetzt hat.
Also auch das Konzept, wie man hier sieht,
also auch nicht komplett neu erfunden, sondern eigentlich auch schon etwas älter.
Ja. Gut, Superskalarität hört sich jetzt natürlich erstmal super
an. Probleme, die da natürlich auftreten,
also das ist zum einen habe ich dann natürlich also noch
deutlich mehr Möglichkeiten,
wo jetzt irgendwelche Hazards auftreten können
Nicht, da kommen dann noch zusätzlich solche Effekte mit rein,
dass man sagt, okay, die unterschiedlichen Alus haben dann immer noch unterschiedliche Latenzzeiten,
nicht typischerweise kann man sagen, okay, eine NHL-Berechnung ist nach ein oder zwei Takten fertig,
wenn ich eine Fließkomma-Berechnung habe, dann braucht die eben schon mal deutlich mehr Takte.
Nicht, weil da kommen dann eben diese Sachen mit rein,
dass man sagt,
ich habe ja nicht nur das Pipeline hinsichtlich der Befehle,
sondern ich habe dann eben in den Recheneinheiten eben auch noch ein Pipelining,
wo man dann eben sagt, gut,
also für Fließkomma-Berechnung habe ich dann eben typischerweise Erstmal anpassende Exponenten,
sprich dann eben Schieben der Mantise,
dann kommt die eigentliche Berechnung,
wo dann also mit der Mantise jetzt irgendwie was gerechnet wird,
wenn ich beispielsweise eine Addition mache und hinterher kommt dann eben nochmal wieder dieser Schritt Normalisierung.
Das dauert natürlich deutlich länger, als wenn ich jetzt
nur quasi zwei 64 bezahlen habe und die addieren muss.
Gut, das heißt, Und unterschiedliche Latenzzeiten. Dann kommt eben hinzu,
dass die Befehle dann eben gegebenenfalls, also auch erstmal in diesen lokalen Cues irgendwo warten können. Und das führt dann eben dazu,
dass die Verwaltung von dem Ganzen entsprechend kompliziert ist,
weil ich da dann eben doch deutlich mehr Hasan-Möglichkeiten habe und sich eben wirklich die Abhängigkeiten zwischen irgendwelchen Sachen dann eben nicht mehr so einfach aus dem Code ergeben wie ich das jetzt also im Prinzip vorgestern vorgestellt habe,
nicht wo ich also nur sage, Assembler-Befehlen,
ich das Register lesen,
dahin schreiben, da habe ich so eine Abhängigkeit,
sondern das kann sich wirklich dynamisch mit jedem Tag verändern,
weil es eben sein kann,
je nach Belegung der Recheneinheiten,
dass da dann natürlich dann also auch entsprechend dynamisch die Befehle
dann ja wirklich auf die CPUs rauf oder auf die Rechenwerke
raufkommen oder eben auch nicht
Schwierig dabei wird daran eben demzufolge dann natürlich also auch die Handhabung von irgendwelchen Kontrollflussabhängigkeiten.
Das heißt, wenn ich jetzt eben Sprünge mit drin habe,
wie gehe ich dann damit um? Weil das dann natürlich,
also das entsprechende Problem ja auch passend nochmal verschärft.
Und das führt dann eben dazu, dass man sagt,
also gerade dann bei Superskalanrechnen an Reiten lohnt sich dann eben
wirklich sowas wie so ein Loop an Rohling,
also doch schon entsprechend gut.
Und wenn ich das dann eben verbinde mit irgendwie dann
auch so einem dynamischen Skeletueling,
dann kann man eben wirklich einen gleichen Algorithmus nehmen und den
also im Faktor 3 beschleunigen
Dieses Stichwort Loop an Rowling, ich hatte es ja am
Mittwoch noch mal kurz oder schon mal so weit skizziert.
Ich habe jetzt hier gerade aus einer anderen Vorlesung noch mal
so irgendwie so eine fast eine Folie bei rausgesucht.
Das ist also im Prinzip so das klassische Beispiel,
um jetzt erst mal zu sehen,
also was verbirgt sich dahinter und nach Motto,
das kostet demzufolge dann ja erst mal für den Compiler in dem Sinne nichts weiter nicht.
Also angenommen, ich habe jetzt hier irgendwie so eine Vorschleife,
wo ich dann also hier Entsprechend jetzt mit jeder Iteration an also hier irgendwie was bei Rechne.
Nicht, wenn ich das jetzt hier um Faktor 2 ausrolle,
würde das eben einfach heißen, dass ich sage,
okay,
ich berechne eben in einem Durchlauf den Wert von PJ und von PJ
plus 1. Verändere hier quasi in meiner Vorschleife die schrittweise und habe demzufolge dann also nur noch halb so viele Durchläufe.
Und dann aber eben vom Assembler erzeugt oder vom Campala erzeugten Assembler-Code
Dann eben auch nur noch die Anwahl, quasi hier die Anweisung entsprechend dann verdoppelt,
aber in weniger Schleifendurchläufe, weniger Sprünge und eben auch weniger Sprungabfragen.
Also das wirkt sich da dann eben auch noch aus.
Und das kann man da jetzt eben je nach Art und Weise,
wie doll man das macht,
dann eben wirklich bis zu komplett ausgerollten Schleifen machen,
was natürlich immer nur jetzt geht,
wenn ich also jetzt wirklich so eine statische Iteration habe,
also sprich eine Vorschleife,
wo ich jetzt eben weiß,
wie lange die läuft
Nicht, aber da kann man eben sagen, okay,
also ein Worst Case wird das eben quasi komplett aufgerollt und
ich habe einfach nur direkt den leeren Code und da bräuchte ich
also keinen einzigen Rücksprung und da brauche ich keine einzige Abfrage,
ob irgendeine Endbedingung erfüllt ist.
Und das ist dann eben entsprechend das,
was ich da jetzt hinter Loop an Rolling verbirgt. Gut,
was dieses Beispiel dann ja eigentlich auch schon ein bisschen gezeigt hat,
ist das, was dort dann eigentlich wichtig ist,
ist eben Auch noch die Unterstützung jetzt eben seien es des Compilers.
Also das heißt, also gerade im Bereich Compilerbau wird da dann
eben entsprechend viel gemacht. Das heißt, wenn er kommt,
da der Campala in der Regel dann eben wirklich weiß,
für welche Zielarchitektur irgendwie was gebaut wird,
kann der dann natürlich also auch schon entsprechende Optimierung vornehmen.
Und das dann eben ergänzend zu jetzt irgendwelchen Hardware-Einheiten, also wie,
also diesen Scoreboards, was dann eben entsprechende endliche Automaten sind,
machen, was dann eben auch ein Vergleichsweise gut funktioniert.
Das ist ja eben auch einer der Gründe,
weswegen es dann,
wenn man sich also mal jetzt irgendwelche Benchmarks anguckt oder selber Programme für Benchmarks übersetzt,
es dann eben auch entsprechend also schon mal wichtig ist oder entsprechend Unterscheidungen gibt,
jetzt in den Ergebnissen,
mit welchem Compiler kompiliere ich das und mit welchen Compiler Optionen mache ich das,
weil man da dann eben sagen kann,
also ein Geschwindigkeitsfaktor von zwei oder drei kriege ich also
schon durch die richtigen Compiler Optionen hin
Ein bisschen Weise entsprechend guten Compiler. Und das wirkt sich
da dann eben auch entsprechender aus. Gut,
dann etwas, was dann natürlich also immer im Prinzip,
also auch entsprechend bei Superskaladenrechnern dann,
also auch das Leben dann zunehmend noch schwierig macht,
sind dann eben Interraptsystem-Calls und Acceptions,
weil da muss ich jetzt nochmal kurz zurückspringen zu einer Folie
Von letzter Woche, die ich ja nämlich also auch irgendwie einmal
gepflegt beim Umblättern übersprungen habe. Und da hatte ich ja gesagt,
okay, also was wirkt sich auf die Pipeline aus?
Nicht gut ist das. Schlecht sind Hazards. Die hatte ich
im Prinzip alle vorgestellt. Struktur, Daten und Controllersatz.
Und ganz schlecht für Parkplaning ist dann eben natürlich sowas,
wo ich sage, naja,
das funktioniert immer so lange gut, wie ich sage,
ich habe ein Programm und das liegt im Speicher und da
wird immer irgendwie brav drauf rumgerechnet.
In der Realität haben wir natürlich
nicht nur ein einziges Programm
Das irgendwo zur Ausführung kommt, beziehungsweise es kann dann eben auch sein,
dass wenn das in dem Programm jetzt sagt,
also ich möchte jetzt also irgendwie über File IO irgendwo von einer Festplatte was lesen,
dass das natürlich also entsprechend langsam ist und es sich deswegen natürlich nicht lohnt,
das Programm so lange zu warten, bis der Wert,
also irgendwie von der Festplatte gelesen wurde,
weil da bin ich dann also irgendwo so im Millisekundenbereich,
was verglichen mit irgendwelchen Gigahertz-Tagdraten dann,
also ein paar Millionen Prozessortakte mich kostet,
die der Prozessor quasi einfach dann nur irgendwie vor sich hin eideln würde,
nicht deswegen man eben das Betriebssystem und ein entsprechendes Scheduling dazwischen,
was dann eben sagt, okay,
ich habe hier irgendwie ein Interrapt, I o wait,
das Programm wird erstmal von der CPU genommen,
irgendein anderes wird zur Ausführung gebracht und irgendwann später,
wenn das Ergebnis von dem Festplattenried da ist,
läuft der andere Algorithmus weiter.
Das ist dann eben etwas, wo dann natürlich die komplette Pipeline,
wenn ich also quasi einen Kontextwechsel mache, irgendwie ausgetauscht werden muss.
Nicht, das heißt also alles, was dann eben Interraptsystem
Call Exception ist, also alles, was den Programmkontext unterbricht.
Bei einigen Out-of-Order-Optimierungen, auch das wirkt sich da dann also auch noch entsprechend aus.
Was man nachher dann noch teilweise gemacht hat, wegen dieser Unterbrechen des Programmkontexts im Pipelining,
ist das, was Intel dann immer als Hyper-Threading verkauft.
In der Literatur heißt es immer Simultanious Malty-Threading,
ist einfach die Idee, dass ich sage,
ich habe in meiner Pipeline zwischen den einzelnen Stufen,
nehmen wir einfach mal irgendwie die Grafik.
Jetzt nicht nur ein Registersatz, sondern ich habe dort mehrere Registersätze.
Beim Hyperstraading, so wie Intel das macht, hat man dort letztendlich zwei Registersätze. Und dann kann man sagen,
wenn ich jetzt also hier irgendeinen Algorithmus habe, der läuft,
der abgearbeitet wird und es kommt eben irgendwie zu so einem Interrabd und was anderes soll laufen,
dann muss ich jetzt nicht Pipeline lernen,
das Ganze irgendwie sichern,
irgendwo hinschreiben ins Deck und hast nicht gesehen,
sondern dann schalte ich quasi einfach nur den Registersatz um habe in dem anderen Registersatz oder in diesem Teil der Parkplanern,
also irgendwas, was hoffentlich entsprechend gleich weiterlaufen kann,
arbeite dort weiter.
Und wenn, meinetwegen jetzt diese Unterbrechung zu Ende ist oder wenn das Datum,
Wasser so gelesen werden soll, also dann beispielsweise im Speicher angekommen ist,
kann der andere Prozess weiterarbeiten. Das ist das,
was man dann eigentlich immer sieht jetzt bei den entsprechend größeren Core-Prozessoren,
nicht wo man also sagt, also was weiß ich, die haben dann,
also meinetwegen ist so ein Corey-7 dann also irgendwie sowas wie Acht.
Prozessoren, logisch drin, virtuell sind das dann, oder virtuell drin,
also rein faktisch sind das dann zwar auch nur vier Kerne,
aber die haben dann eben quasi diese doppelten Registersätze und nach außen
hin beziehungsweise dem Betriebssystem gegenüber sieht das dann so aus,
als ob man dann die doppelte Anzahl von Prozessoren hat.
Theoretisch könnte man das jetzt noch weitertreiben und sagen,
ich habe jetzt nicht nur zwei,
sondern also dann noch
deutlich mehr
Registersätze, das war, sagen wir mal so,
Ende der 90er Jahre relativ heißes Thema in der forschungsmäßig jetzt,
also bei der Entwicklung der Rechnerarchitektur, die Tatsache,
dass es also, sagen wir mal, bei diesem Hyperthreading-Konzept,
wie es eigentlich nur mit Faktor 2 irgendwo angekommen ist,
scheint also dafür zu sprechen,
dass sich mir einfach nicht lohnt,
weil man dann also irgendwo dann im Zweifelsfall den Engpass an irgendeiner anderen Stelle bekommt.
Nicht, aber das ist eigentlich das,
nochmal kurz ergänzt
Dazu war es sich also hinter diesem Hypersrading verbirgt.
Und wie gesagt, was dann eben sein kann,
wenn ich jetzt entsprechende Interrazts und System Course,
also irgendwie dazwischen habe und dann wirklich diese Gesamtprogrammabarbeitung abgebrochen werden muss.
Gut, ja, das hatte ich soweit jeweils schon
Angesprochen, was ich dann letztendlich dahinter verbirgt,
wie gesagt, das Problem natürlich dann jetzt bei solchen Superskalan-Pipelines,
da ist, dass man also wirklich extrem aufwendig,
war ich da dann sagen muss, okay,
ein paar der Anweisungen müssen noch bis zu Ende ausgeführt werden,
ein paar vielleicht nicht,
aber insgesamt muss dann eben auch noch deutlich mehr Informationen quasi zwischen gespeichert werden,
also auf einem Stack oder irgendeinen Mechanismus,
als das jetzt also beim Normal-Pipelining ohnehin schon
der Fall wäre
Nicht das, was man da dann häufig macht,
also gerade so bei Interradbehandlung ist, dass man eben sagt,
also neue Instruktionen werden erstmal nicht mehr reingeschrieben und man guckt dann eben bis Teile,
die man jetzt nicht so einfach zurückdrehen kann.
Also beispielsweise das, was in diesem Reorder-Buffer eigentlich schon als
Ergebnis drin steht, bis das dann entsprechend abgeschlossen ist.
Gut, dazu gibt es dann verschiedene unterschiedliche Verfahren.
Das ist dann also auch dann wieder so ein bisschen davon abhängig, welche Art von Interrapters ist.
Nicht, dann gibt es etwas, was sich Precise and Dip nennt. Da ist dann letztendlich bekannt,
Durch welche Art von Instruktion, also diese Interrappe ausgelöst wurde,
also gerade so bei Lese- und Schreiboperationen passiert das typischerweise,
wenn die Sachen jetzt also nicht direkt im Cash liegen,
sondern also von Hauptspeicher oder sogar von virtuellem Speicher gelesen werden,
dass man das weiß, dass man dann eben auch entsprechend sagen muss,
okay, alle Instruktionen, die jetzt vor dieser Instruktion sind,
wurden vollständig ausgeführt und stecken nicht noch an irgendwelchen Reservation Stations in der Q mit drin,
Alles oder noch keine Instruktion, die danach kommt,
wurde schon irgendwo vorgezogen, ausgeführt.
Nicht, dann kann ich sagen, das ist ein Precise-Interrap,
dann kann man im Prinzip die Pipeline-Aktivität komplett beenden,
in allen anderen Fällen muss man das dann entsprechend aufwendig machen,
beziehungsweise was man häufig macht, ist,
dass es nennziellen Imprecise-Interrap ist,
sondern eben das Ganze verhandelt wie so eine Art verzögerten Sprung.
Das heißt, Teile der Pipeline laufen noch leer,
es kommen dann aber eben, wie gesagt,
nichts Neues mehr rein und das war es dann letztendlich
nur noch in die Pipeline reinkommt,
ist dann im Prinzip ein Sprung auf die Interraptroutine
Gut, Beispiel für so eine Architektur,
auch nur ganz groß skizziert oder vorgestellt, ist dann also das,
was im Pentium 4 dann mit der sogenannten Netburst-Architektur mal eingeführt wurde,
wo ich dann eben sage, ich habe da mehrere Alus,
wie gesagt, x, 86 Befehlssatz ist eigentlich ein CIS-Befehlssatz,
was man da dann aber immer macht,
weil das intern ja, also dann als Risk läuft,
dass dann also die einzelnen Befehle in sogenannte Mikrooperationen umgesetzt werden,
wo dann eben die entsprechenden Befehlern Durch kleinere Teile ersetzt werden,
die dann im Prinzip riskmäßig dann eben in Sympathplanning-Schema reingeschoben werden können.
Gut, dann habe ich da dann eben diese entsprechende Reservation Stations.
Wichtig ist dann eben auch noch ein zusätzlicher Cash,
das heißt also in dem Speicher stehen dann nicht die ursprünglichen Assembler-Befehle,
sondern im Prinzip diese Mikrooperation direkt mit drin,
auf die dann entsprechend schnell darauf zugegriffen werden kann und was
dann eben auch gerade für irgendwelche Schleifenbehandlungen dann wieder ganz interessant ist.
Wenn ich quasi einmal durch so einen Teil- oder Teilalgorithmus durchgelaufen bin,
dann bleiben die quasi jetzt in diesem Cashing-Mechanismus,
also direkt für den Prozessor Dorf zugreifbar,
noch erhalten beim nächsten Schleifen,
Durchlauf muss man dann eben nicht jedes Mal den Befehl nochmal
wieder neu übersetzen oder dekodieren,
sondern man holt sich dann gleich aus diesem Cash so einen
kompletten Block und hat dann also schon diese Anweisung dafür entsprechend
Mit drin. Nicht, was dann eben diese Dekodierung dieser Anweisung dann entsprechend einfacher macht. Nicht,
dann hat man also Alos,
wo man dann quasi pro Tag Zyklus dann nicht nur eine,
sondern quasi so zwei Werte direkt mit reinschieben kann, Double Pumped,
also dahinter verbirgen sich dann eben auch noch wieder so Mechanismen,
wo man sagt, das,
was dann teilweise an Datenraten dort gemacht oder implementiert wird,
entspricht jetzt nicht mehr eins zu eins den Taktraten,
ähnliches Verfahren ist im Prinzip bei dem,
was also in dem dynamischen Rahmen beim Speicher ist.
Nicht also ursprüngliche Idee war mal, also DDR-Speicher, also ein getakteter,
dynamischer Speicher, wo ich also jetzt wirklich mit jedem Takt ein Speicherwort lesen kann.
Nicht dann kam also DDR 2 und 3 und so weiter,
dass man dann also quasi mit, der speichert zwar eine bestimmte Taktrate hat,
ich aber mit dieser Taktrate dann eben innerhalb der entsprechenden Periode dann eben gleich zwei oder drei Werte lesen kann,
nicht also beim Grafikspare ich ja erstmal da,
also inzwischen dann schon beim Faktor 5 irgendwo mit angekommen.
Nicht, dass dann ein GDDR 5,
wo es dann eben heißt,
die haben also im Prinzip die und die Takterate,
nicht ein Wellen, nicht dann also den Datendurchsatz ausrechnen würde,
müsste ich dann eben quasi dann pro Takt sagen,
okay,
da werden jetzt also
fünf Werte gelesen bzw. geschrieben
Gut, was ähnliches ist dann eben auch teilweise eine Recheneinheiten mit drin,
dass die dann eben auch nicht eins zu eins zur nominellen Prozessor-Taktrate arbeiten.
Aber gut, das ist dann eigentlich jetzt wieder genau
von der CPU abhängig oder von dem Typ nicht.
Also das hier nur als Hintergrunderklärung. Gut, was dann
im Prinzip mit dieser Pension 4 Architektur auch eingeführt wurde.
Ich hatte ja so auch vorgestern auch schon diese eine Folie,
wo es also im Spiritlining ging und dann also Anstieg der Tagfrequenzen.
Nicht, dass da dann eben auch die Pipeline-Länge entsprechend groß geworden sind, nicht.
Also beim Vorgängerprozessor habe ich Also hier im Prinzip so eine Pipeline-Länge von 10. Nicht,
da haben sie das dann erst mal eben also auf 20,
verdoppelt, führt dann aber eben auch dazu,
dass also dann auch die Taktrate deutlich gestiegen ist.
Und zumindest solange ich die Pipeline mit Werten versorgt bekomme,
man dann eben auch einen entsprechend hohen Datendurchsatz bekommt.
Wie gesagt, also auf den entsprechenden Seiten von Intel,
die sind da zumindest mit irgendwelchen Presse- und Informationsmaterial,
also auch relativ gut bestückt.
Also da kann man sich dann,
also wenn einen sowas interessiert, also da noch entsprechend was
mit raus
Hier nur so ein bisschen rausgezogen. Also hier sieht man
da so grob die Architektur. Wille jetzt gar nicht
im Einzelnen vorstellen, weil das interessiert niemanden mehr.
Die Dinge gibt es also auch schon seit Jahren nicht mehr.
Nicht immer, was man hier eigentlich erstmal nur sieht.
Also hier unten an eben genau das,
was eigentlich dann eben dieses Superskalare ist.
Nicht, dass ich sage, ich habe hier mehrere Integer-A-Los.
Ich habe hier also irgendwelche Fleecekomma-Rechenwerke. Ich habe hier dann
AGU-Stedteln immer für Adress Generation Unit. Mehrere Rechenwerke,
die dann eben benutzt werden, um irgendwelche Adressen zu berechnen
Nicht das, was ich,
als sie das ursprünglich hervorgestellt hatte, ja,
das Argument genommen habe,
weswegen habe ich im Prinzip den Memory Access hinter der Execute Stufe in der Alu,
um jetzt eben quasi bei Read oder bei Storbe fehlen irgendwelche Adressen durch die Alu zu berechnen.
Also auch dafür gibt es dann eben auch in aktuellen Prozessoren
dann also entsprechend spezieller Recheneinhalten. Gut, also wie gesagt,
das Pentium 4, nicht so im Bereich Jahrtausendwende,
2001, bei den aktuellen Prozessoren sieht das also ähnlich aus,
also das hier auch nochmal irgendwie so eine Grafik
Der zweiten Generation Core-Prozessoren von Intel,
wo ich dann eben auch hier unten diverse Indiger und Fließkomma-Recheneineinheiten zur Verfügung stehen habe,
nicht und dann also hier über unterschiedliche Cashes und also Mechanismen,
die dann also quasi dieses ganze Registery-Naming machen,
dass die das Issue,
wenn du generieren und dann eben gucken,
welche Befehle können jetzt wann vielleicht,
von welcher CPU oder von welchem Rechenwerk hier bearbeitet werden,
nicht das Ganze dann eben hier dann durch
entsprechend lange Pipeline letztendlich umgesetzt wird
Gut, neben solchen Konzepten, wo ich jetzt erst mal sage,
gut, alles, was wir bislang betrachtet haben,
war immer nur eine einzige CPU. Die wurde dann ergänzt um Pipelining,
die wurde jetzt ergänzt als Superskalarechner quasi um mehrere Recheneinheiten.
Wie sie das jetzt eben wirklich aus mit Parallelrechnern mit mehreren Prozessoren. Ich war,
auch da kann man jetzt sagen, oder hatte ich auch schon angedeutet,
also immer weiter mit den Taktfrequenzen raufzugehen, lohnt einfach nicht mehr,
weil dann also der Energieverbrauch der Schaltung, also wirklich so stark anwächst,
dass man das eben einfach rein technisch dann also nicht mehr in den Griff bekommt,
beziehungsweise dann die Schaltung nicht mehr gekühlt bekommt.
Und wenn man sich jetzt eben beispielsweise nur mal veranschaulicht und sagt,
na gut, also ich habe,
also das Beispiel habe ich ja drüber auch schon mal gebracht,
also ich habe jetzt im Prinzip,
also hier irgendwie so einen modernen Prozessor,
der hat dann also irgendwie laut Datenblatt, TDP,
Terminal Designpower, so was wie 160 Watt.
Du warst da also quasi eine Leistung verbrät,
nicht das Ganze, also irgendwie mal ganz großzügig gerechnet,
zweimal drei Zentimeter Kanten länger, also sechs Quadratzentimeter Fläche.
Nicht, wenn man das jetzt in Relation setzt,
so einer 21 Zentimeter Herdplatte, die 3000 Watt fabrät,
hat der Prozessor die deutlich höhere Leistungsdichte.
Und wenn ich den jetzt nicht nur mit 3,8,
sondern mit 10 Giga-Herz-Takten würde, dann hätte ich also da wirklich das Problem,
dass sich das jetzt also ohne irgendwelche Stickstoffflüssigkühlung,
also dann wirklich nicht mehr hinkriege,
dass mir da das Elizium nicht, also irgendwie dann anfängt wegzuschmelzen.
Gut, deswegen mehrere Prozessoren, Parallelrechner. Problem ist natürlich,
wie kriege ich da jetzt die Datenaustausch,
die zwischen den Prozessoren hin und wie gesagt,
die ganz klassischen Mechanismen sind eben Shared Memory.
Einen gemeinsamen Speicher, auf den alle Prozessoren irgendwie darauf zugreifen.
Oder eben Message Passing, das heißt die Prozessoren unterhalten sich
jetzt über Nachrichten untereinander
Problem ist natürlich bei beiden dann immer,
wie kriege ich das, also letztendlich erst mal angeordnet,
wie sie das dann eben mit irgendwelchen Kommunikations-Overhead aus und generell natürlich,
wenn ich jetzt also einen Algorithmus habe und sage,
das soll jetzt mehr oder minder automatisch auf mehrere Prozessoren verteilt werden,
also wie würde sowas programmiert?
Das war es, man heute macht das,
was wir auch eigentlich alles benutzen,
sind dann eben busbasierte Systeme, SMPs sind Magical Marty Processor,
wo quasi Symmetrical deshalb war im Prinzip alle Prozessoren,
gleiche Priorität oder gleiche Rechte haben.
Nicht mit typischerweise dann eben, ja,
so im Desktop-Bereich dann eben so bis zu 16 CPUs,
die dann letztendlich damit drin sind.
Unterteilung bei Parallelrechnern oder Parallelarchitekturen folgt, also so einer Klassifikation,
die ein Herr Flynn sich mal überlegt hatte.
Also das Ursprüngliche von Neumann-Konzept, einzelne CPU,
Single Instruction Single Data
Ich dann parallel rechne, kann man eben sagen, Single Instruction Multiple Data,
da gibt es dann eben Unterscheidungen, eben Amazon und so klassische Vector-Rechner oder Feldrechner, beziehungsweise implizit ist sowas teilweise auch natürlich in modernen CPUs schon mit drin, in entsprechenden Befehlssatzerweiterungen. Und zwar das,
was intern also ganz früher mal mit diesen MMX-Befehl setzen,
eingeführt hat, was dann also im Prinzip jetzt also über noch entsprechend andere Befehlsätze auch noch erweitert wurde,
nutzt dann eben auch schon explizite Parallelität mit aus,
dass es eben bestimmte Befehle gibt, mit denen ich,
wenn ich in der Hardware,
wie er also eben diese Grafik schon gezeigt hat,
also jetzt mehrere Rechenwerke habe,
die dann also auch wirklich explizit mit einem Befehl ansprechen kann und ich dann eben so ein Single Instruction Multiple Data machen kann,
dass ich sagen kann, okay,
ich nehme jetzt also irgendwie ein langes Datenwort und der Teil geht auf die CPU,
der Teil geht auf DC, oder nein, nicht CPU,
der Teil geht auf die Alu-Derta, geht auf die Alu,
der Teil geht auf die Alu, das macht zum Beispiel Sinn,
Wie gesagt, so im ganz einfachen Fall, das, was also ursprünglich dieser MMX-Befehlsätze sind, dass ich sage, okay, ich habe beispielsweise eine 32-Bit-Alu.
Ich möchte jetzt von irgendwieem RGB-Bild irgendwas berechnen, dass ich dann sage,
gut, dieser Alu wird letztendlich aufgeteilt, logisch gesehen,
indem ich einfach irgendwie das Carry zwischendurch mal auftrenne,
in vier, acht Bit-Alus, kann dann eben sagen,
mit allen 32 Bit-Daten-Wert, das entspricht dann Brot,
Grün, Blauanteil und meinetwegen noch im Alpha-Kanal,
also für die Transparenz und kann dann also mit einem einzigen Befehl sagen,
dieses Datenwort ist dann nicht ein 32-Bit-Enteger,
sondern das ist dann 4-8-Bit-Integer-Wert,
mit dem kann ich jetzt also irgendeine Berechnung machen und dann hinterher mit dem Ergebnis dann wieder was machen und kann damit dann,
also zum Beispiel jetzt also bei irgendwelchen einfachen Bildverarbeitungsoperationen da natürlich entsprechend Effizienz sein.
Nicht das ist also das,
was mit solchen Befehlssätzen da dann mit drin ist und wie gesagt,
das Ganze gilt dann also gerade so im Bereich von Signalverarbeitungsaufgaben
Gut, und ganz allgemein eben das, was eben richtig jetzt Parallelrechner sind,
Multiple Instruction Multiple Data, wo ich dann eben wirklich von Compute Cluster,
aber eben auch wirklich mal die Core CPUs so was habe.
Detaillierte Klassifikation, wie man sie in der Literatur findet,
für Parallelrechner wäre dann, also hier im Prinzip sowas,
wo ich dann eben hier die Grobunterteilung habe und dann geht das dann eben weiter ins System,
wo ich dann also Multi-Computer oder Multi-Prozesse-Systeme habe,
nicht dann wird das hier noch unterteilt in die Art und Weise,
wie die einzelnen Prozessoren auf den Speicher zugreifen können,
können alle Prozessoren gleich auf den Speicher zugreifen.
Ist da ein Unified-Memory-Access oder hat quasi jeder Prozesse
seinen eigenen Speicherbereich oder es gibt sowas wie ein Speichercontroller,
an den sich andere jetzt wenden müssen.
Das ist dann Non-Unified-Memory-Access und so weiter nicht.
Und da gibt es dann eben entsprechende Weiterunterteilung, je nachdem,
wie das Ganze dann also irgendwie technisch unterteilt ist, wie das Ganze umgesetzt wird. Gut,
hier nur nochmal zur Veranschaulichung, So das erste,
was dann also wirklich Single Instruction Multiple Data war, Vector-Rechner,
nicht die berühmte Cray 1, Mitte der 70er Jahre,
wo dann also im Prinzip ich dann ein Rechenbefehl, also auf so ein ganzes Array anwenden konnte, was dann also auch entsprechend erfolgreich war. Man konnte dann entsprechend schnell mit arbeiten,
das Ganze führt dann dazu,
also das wurde dann immer irgendwie so als beheizte Sitzbank betitelt,
nicht das sah also dann wirklich so aus,
wie dieses Tal hier innen drin,
hier waren dann eigentlich hier in der Mitte,
waren dann im Prinzip im Bereich für Kabel und dazwischen dann eben die ganzen Schaltelemente,
dann kamen dann noch so Tricks da rein hinzu,
also alle Kabel waren 30, 60 oder 90 Zentimeter lang,
was, wenn man die Lichtgeschwindigkeit zugrunde liegt,
dann eben entsprechend ein, zwei oder drei Nanosekunden entspricht,
an Verzögerungszeit, das Ganze dann in einer Technologie,
die also damals dazu geführt hatte,
dass das Mornstrom dann also schon mit 80 Megahertz-Takt betrieben wurden konnte,
dass also zu einer Zeit, als ein IBM-PC,
also mal gerade 8 Megahertz-Schaftel, war ein 10-Marter so schnell,
war aber als ECL-Technologie, was also unglaublich stromaufwendig ist,
dann also im Prinzip,
also nur mit irgendeinem flüssig Kühlmädeln mit Frionern ging und so weiter,
nicht immer hat dann also eine Rechenleistung von 136 Megaflops erreicht,
da kann dann sagen, na gut,
wenn ich jetzt im Bereich von einer doppelt genauen Fließkomma-Berechnung bin,
erreicht das inzwischen eine 300-Euro-Grafikkarte.
Also die aktuellen Nvidia Maxwells, CPUs sind so ungefähr,
also zumindest bei der Double Precision-Berechnung in dem Bereich,
bei der Single Precision-Berechnung sind sie also schon bei etwas über vier Terra-Flop.
Da kann man sagen, ja gut, inzwischen nicht,
also jeder bessere Gamer hat dann sowas zu Hause stehen. Ja,
aber das eben wirklich so als Beispiel für das,
was dann also ursprünglich mal so als großer Parallelrechner entwickelt,
wo der anderes berühmtes Beispiel, sowas wie Iliac,
das war so Feldrechner,
wo ich dann im Prinzip auch so ein ganzes Array von Rechenwerken hatte,
die dann also im Prinzip in solchen Karten irgendwie Riesenschränken da letztendlich rumstanden.
Gut, hier auch nur noch mal bei dieser Unterscheidung,
wenn ich jetzt sage, ich habe jetzt eben wirklich Parallelrechner,
Multiple Struction, Multiple Data,
wie greifen die CPUs dann eben letztendlich irgendwo auf den Speicher rauf zu,
nicht wenn ich jetzt sage,
ich habe die Prozessoren über eine Art Bussystem oder über ein Ö irgendein Netzwerk miteinander verbunden.
Gibt es sowas für einen gemeinsamen Speicher,
der dann von AMCPUs angesprochen wird,
wobei man sich jeder natürlich schon denken kann, quasi der Bottleneck oder Engpasswörtern,
also hier letztendlich das Bussystem oder hat dann eben jede CPU ihren lokalen Speicher und es gibt dann noch irgendwelche gemeinsamen Teile.
Also da gibt es dann eben je nach Architektur dann eben entsprechend unterschiedliche Herausprägung, wie das dann aufgesetzt ist. Also klassisch Shared-Memory kann man sich eben immer so vorstellen,
ein von allen genutzter Speicher,
nicht und jede Prozess oder jede Prozessoreinheit berechnet dann eben hier,
also klassisch hat man dann immer irgendwie so Bildverarbeitung als Beispiel berechnet dann,
also quasi immer irgendwo so eine Art lokalen Kontext,
da jetzt also irgendwie so ein bisschen was rum,
eine Teilaufgabe nicht und solange das Problem eben überhaupt erstmal so unterteilbar ist,
dass die Berechnung von dieser Teilaufgabe mit der Berechnung von dieser Teilaufgabe
nichts miteinander zu tun hat oder eben möglichst wenig,
kommt man mit solchen Architekturen dann also schon
relativ weit
Und wie gesagt,
so eine Lokalität von irgendwelchen Werten hat man also dann schon relativ häufig,
also gerade auch so eine typische Beispiele,
wo man ja auch, womit ich ja heute angefangen hatte,
gerade so in der Simulation, wenn ich also finite Elemente-Methoden,
Wettervorhersagen, nicht, dass ich dann eben sage,
na gut, also um das Wetter zu berechnen,
legt man dann eben typischerweise also irgendwelche Gritz, irgendwelche Raster,
zwei oder dreidimensional dann, also letztendlich fest und sagt,
okay, also Das, was das Simulationsmodell in einem Punkt berechnet,
wird dann eben vielleicht noch bestimmt von den Nachbarpunkten,
aber dann eben erstmal nicht direkt,
sondern dann eigentlich nur über Umwege von irgendeinem Punkt,
der dann also irgendwo entsprechend weit entfernt ist.
Und da kann man also mit solchen Konzepten dann eigentlich ganz gut leben und arbeiten.
Im Gegensatz dazu Message Passing ist dann eben etwas,
wo ich sage, also jeder Prozessor hat quasi seinen eigenen Speicher,
was dann also hier durch die entsprechende Grafik mit angedeutet ist und es gibt dann eben noch sowas wie ein Verbindungsnetzwerk zum Nachrichtenaustausch,
wo dann eben immer nur diese Informationen zwischen CPUs oder den Recheneinheiten ausgetauscht wird,
die dann eben wirklich solche Grenzbereiche beispielsweise betreffen.
Und je nach Art und Weise kann man sich dann unterschiedliche Verbindungsnetzwerke ausdenken,
nicht also von im Idealfall vollständiger Vernetzung,
was natürlich irgendwo rein technisch von der Verdrahtung her einfach nicht mehr möglich ist,
nicht typischerweise gibt es dann eben Sternbaumring,
so verschiedene Konzepte beziehungsweise irgendwie sowas wie Würfel,
Toros oder Hypercube sind da eigentlich immer relativ häufig benutzt,
wenn man dann sagen kann, okay, damit erreiche ich eben,
dass irgendwelche Prozessoren hier sich mit irgendwelchen Prozessoren hier auch noch einigermaßen gut unterhalten kann,
mit möglichst wenig Zwischenstationen.
Ja, aber da gibt es eben sehr viele unterschiedliche Techniken,
also hier nur als Beispiel angedeutet,
würde ich jetzt aber Klima überspringen,
sowas wie, nicht von irgendwie so Kreuzschienenverteiler,
wo ich dann eben sagen kann,
also wenn sich der mit dem unterhalten soll,
kann dann eben entsprechende Verbindung geschaltet werden,
dadurch sind dann aber natürlich jetzt wieder bestimmte andere Verbindungen dann
nicht mehr möglich
Also irgendwelche Netzwerke,
die dann, also sagen wir mal, ähnlich wie,
wenn ich das jetzt hier vergleiche mit so einer Art Barrashif,
da, wenn ich jetzt also wieder in die Schaltnätze zurückgehe,
vergleichbar ist, wo ich dann,
also im Prinzip dadurch,
dass hier die Verbindung entweder gerade durchgehen oder eben entsprechend sogar kreuzt sind,
Archie im Prinzip jede beliebige Verbindung hinkriege,
aber eben zu einem bestimmten Zeitpunkt dann natürlich nicht alle Verbindungen möglich sind,
nicht aber damit kommt man dann also mit einem lugarithmischen Hardwareaufwand
dann eben auch noch dazu,
dass sich alle
miteinander unterhalten können
Gut, zur Skalierbarkeit. Nicht also auch das hat er ja schon kurz gesagt,
wenn ich so ein Bus basiertes System habe, nicht dann ist das natürlich das Problem,
dass dann also die Bandbreite letztendlich dadurch durch den Bus bestimmt wird.
Deswegen, gut, im Desktop-Bereich stört das erstmal nicht weiter,
da lebt man damit,
aber wenn ich dann eben wirklich in solche richtig großen Parallelrechner gehe mit mehreren tausend Prozessoren oder so nicht,
dann hat man eben in der Regel so ein gitterbasiertes System,
nicht weil man da also allein oder eben entsprechend eine andere Anordnung,
also Vater, diese Toro-Systeme sind da immer ganz beliebt.
Nicht, weil das dann eben zumindest noch mit der Anzahl
die verfügbare Übertragungsbandbreite nehmen mit der Anzahl der CPUs ein bisschen skaliert. Gut,
und dann, das ist dann eigentlich immer das Entscheidende,
wenn ich jetzt sage, ich habe so ein Parallelsystem der Speedup,
den man gewinnen kann, hängt eben wirklich davon ab, Welche Art von Problemen habe ich?
Ist das gut parallelisierbar? Ist das nicht parallelisierbar? Dies ist jetzt also wirklich mal so aus dem High-Performance-Computing-Bereich,
so Grafik, wo man sagen kann, gut,
also ich habe hier nicht von einer bis zu 70 CPUs und dann eben unterschiedliche mathematische Probleme,
die damit irgendwie berechnet werden sollen und nicht,
und da gibt es also wirklich Probleme, wo man sagt,
na gut, nicht, da habe ich anscheinend diesen Parallel dieser Parallelisierbaren Anteil bei über 99 Prozent.
Nicht, das wächst also schon fast Also je near wäre dieses Jahr,
aber das wächst also schon sehr schön mit der Anzahl der CPUs und es gibt andere Probleme,
wo man sagen kann, also hier,
also je mehr CPUs ich habe,
wird das hier anscheinend dann sogar eher langsamer, was,
also dann darauf hindeutet,
dass also im Prinzip dann also irgendwo Kommunikations-Overhead immer größer wird und ich dann eigentlich mehr Zeit damit verbringe,
wenn ich jetzt nochmal zehn CPUs zusätzlich spendiere,
mehr Zahl damit verbringe,
also die irgendwie mit Daten zu bestücken und von irgendwelchen anderen Nachbarn die Werte einzuholen,
damit die weiterrechnen können, nicht als wenn ich das weglasse.
Aber wie gesagt, das ist letztendlich dann immer problemabhängig.
Gut, zur Programmierung hatte ich jetzt also noch nichts weiter gesagt.
Das kann man immer sagen, ungelöstes Problem, beziehungsweise das ist das,
wo sich die Leute, wenn sie jetzt also hier irgendwo im Klimarechenzentrum arbeiten, dann eben auch entsprechend mit auseinanderschlagen dürfen. Teilweise gibt es dann eben Unterstützung durch entsprechende Compiler-Werkzeuge,
nicht und gerade für das,
was jetzt in den letzten paar Jahren dann eben auch ein Spein populär geworden ist,
nämlich für das, was wir quasi als günstig,
Parallelrechner einkaufen können, sprich Fließkommaberechnung auf der Grafikkarte,
bieten dann ja also auch die Hersteller sei,
dass dann eben AMD oder sah das Nvidia dann eben entsprechende Entwicklungswerkzeuge an,
wo man dann eben zumindest jetzt also für ihre Architektur dann also entsprechend über Teile,
wo man dann im Programmcode sagt, also jetzt habe ich,
betrete ich hier ein Teil, wo parallelisiert werden kann,
dann das eben automatisch schon so umgesetzt wird,
dass es dann eben auch entsprechend automatisch und effizient versucht wird,
dann eben auch in die Rechnereinheiten der Grafikkarte so umzusetzen.
Ich habe ansonsten ist das eben wirklich ein Problem. Programme teilweise parallelisierbar,
wie gesagt, dass es eben letztendlich davon abhängig,
welche Art von Algorithmus man dort betrachtet. Und gut,
das, womit wir jetzt eigentlich in der Regel arbeiten,
sind dann eben Symagical Multi-Processing, also Merkern, CPUs,
nicht, wo man sagt, na gut,
also bis zu 16 Prozessoren werden dann noch gemacht,
nicht alles andere, sondern eben wirklich irgendwelche Gut,
GPUs, aber sonst eben wirklich irgendwelche entsprechenden Spezialrechner, Spezialarchitekturen.
Gut, hier nochmal zu dem Begriff SMPs im Magical Magic Processing,
dass man eben sagt, also alle Prozessoren sind gleichberechtigt,
teilen sich letztendlich den Hauptspeicher, unterhalten sich im Prinzip über ein Bussystem.
Nicht, das ging also früher,
als man so die ersten Boards mit zwei CPU-Sorkeln hatte,
letztendlich los, bis zu dem, was man also,
sagen wir mal,
heute aktuell die letzte Xeon-Generation hat,
also quasi eine 15-Kern-CPU mit drauf
Bis zu dem, was man dann letztendlich kaufen kann.
Nachteil bei dem Ganzen ist dann aber eben auch schon wieder so was,
nicht ein gemeinsamer Bus, der wird dann eben schnell zum
Flaschenhals und wie kriege ich da dann entsprechend die Datenkonsistent?
Gut, angesichts der Zeit werde ich jetzt hier abbrechen.
Nächste Woche muss ich nochmal sehen,
also ob ich hierzu nochmal irgendwie fünf Minuten was sage.
Ansonsten noch ein bisschen was zur Speicherhierarchie und zum Cashing,
was dann eigentlich auch noch so ein bisschen diesen letzten Teil ergänzt,
wo es eigentlich darum geht, wie jetzt aktuelle Rechner Architekturen aufgebaut sind.
Und ja, dann war das eigentlich soweit dann
auch schon der Inhalt der Rechnerstrukturenvorlesung.
Gut, dann Schluss für heute,
ein schönes Wochenende