Gut, dann, ja, ich hatte ja vorgestern,
nee, vorgestern,
Freitag im Prinzip mit dem Teil Parallelarchitekturen eigentlich so aufgehört,
mit Beschreibungen zu jetzt wirklich Hochleistungsrechnern und bei den letzten drei Folien,
gut, da ist mir dann die Zeit ausgegangen,
da geht es jetzt eben eigentlich nochmal so ein bisschen um Symagic Multi-Processing,
das ist also genau das, was wir eigentlich letztendlich sehen,
wenn wir jetzt also quasi mit dem,
was wir also in Form von PC, Laptop,
egal welche Marke das auch sein mag, im Prinzip arbeiten,
wo man eben sagt,
ich habe also in einer CP oder in einem CPU-Kern dann also letztendlich mehrere Prozessoren mit drin,
die quasi über einen Bus den gemeinsamen Hauptspeicher nutzen.
Vorteil bei diesem busbasierten System, wie gesagt,
sie sind vergleichsweise kostengünstig, skalieren aber schlecht,
deswegen eben für richtige Hochleistungsrechner dann nicht sehr gut geeignet.
Nicht, wenn man jetzt sagt,
also man ist so bis im Bereich von 16 Kern
oder so funktioniert das soweit noch ganz gut.
Problem bei dem Ganzen ist immer so ein bisschen die Konsistenz der Daten,
werde ich mit der nächsten Folie noch kurz motivieren,
dann werde ich diesen Teil hier abschließen und noch ein bisschen
was zur Speicherhierarchie und zum Cashing sagen,
was eigentlich dann sich also auch noch so
ein bisschen inhaltlich dann hiermit anschließt
Dieses Problem der Datenkonsistenz, auf das werde ich dann also
auch gleich nochmal beim Caching ein bisschen genauer bei eingehen.
Und ansonsten ein anderes Problem bei dem Symagic Multi-Processing,
was hier nur kurz angesprochen werden soll, was sie vielleicht auch kennen.
Etwas, was man dann also immer gerne als Hopping bezeichnet,
das also im Prinzip Prozesse, die laufen,
eben die CPU oder den Kern,
auf dem sie rechnen,
wechseln,
was gelegentlich eben auch
Nachteile haben kann
Ich war in der Regel werden die Prozesse ja
automatisch vom Betriebssystem auch die verfügbaren Recheneinheiten bzw. CPUs verteilt.
Und was dann eben ist,
dass wenn jetzt also irgendwie eine Unterbrechung stattfindet,
sei das jetzt also irgendwie interrabt sonstiges Prozess, wird quasi erstmal unterbrochen.
Beispielsweise, weil, also jetzt irgendwelche Daten noch fehlen,
die jetzt also erstmal nachgeladen werden, das dauert eine Zeit lang,
währenddessen soll natürlich was anderes rechnen.
Nicht anschließend wird der Prozess vom Betriebssystem
wieder neu aufgesetzt
Und dabei kann es eben sein, dass er dann eben auf einer
physikalisch anderen CPU ist. Sehen würde man das beispielsweise,
wenn man im Prinzip sich zum Beispiel unter Windows, das also mit dem Taskmanager ansieht,
wo man dann ja für die einzelnen Rechenkerne eben auch die Auslastung sieht.
Und wenn man jetzt also mehrere Sachen, die dann eben
auch wirklich mal ein bisschen CPU-Lasterzeugung parallel laufen hat, kann man eben teilweise sehen, wie das also wirklich springt. Ich sag mal so bei Anna-Systemen,
also hier bei dem Linux,
also ich habe dann immer irgendwie so ein XOS You Love,
wo man dann eben hier sieht, ich habe hier,
also in dem Teil, irgendwie sowas wie vier CPUs,
die dann also gelegentlich mal so ein bisschen was tun,
ansonsten eitelt der Rechner mehr oder minder vor sich hin,
in was man eben hier munter sieht, ist,
wie dann teilweise, also die Sachen immer irgendwie wechseln,
mich und im Zweifelsfall wird also der Akrobatreader,
den ich jetzt also hier quasi laufen habe,
dann eben, also mal auf der CPU,
mal hier auf irgendeiner anderen laufen.
Das ist also im Prinzip dann dieses Hobbing. Gut,
letztendlich hat es zusammengefasst Multikor-Prozessoren, sind dann eben sowas wie symmetric multiplificing on the chip.
Gut, Nachteil oder was da eben Probleme bereiten kann,
ist jetzt eben wirklich die Konsistenz von Daten. Nicht,
wenn man jetzt sagt, also ich habe mehrere Prozessoren,
die auf allen gemeinsamen Speicherbereich arbeiten. Wie sieht das aus,
wenn die jetzt also quasi in die gleichen Adressen auch zugreifen möchten?
In der Regel ist das natürlich etwas,
wo man sagt, also Prozess 1 und Prozess 2,
sofern die nichts miteinander zu tun haben,
sollen das
tunlichst nicht
Nicht, das heißt, da sollte eigentlich das Betriebssystem davor sein, dass genau das nicht passiert. Vorausgesetzt,
ich habe jetzt aber eben wirklich ein paralleles Programm,
was also jetzt mit mehreren Frätz beziehungsweise mehreren Prozessen,
die dann also über Shared Memory miteinander kommunizieren,
quasi genau sowas macht, wie das hier angedeutet ist,
wo ich dann also sage, beispielsweise auf C4CPUs,
also hier habe ich also auf eine Speicheradresse einen Schreibzugriff,
hier von auch einen Schreibzugriff, hier wird zweimal gelesen,
hier wird gelesen, und je nachdem,
In welcher Reihenfolge ich das Ganze irgendwie durchpermutiere?
Habe ich da also beliebig unterschiedliche Werte, was dort gelesen wird?
Beispielsweise jetzt von den Prozessen P3 und P4. Ja,
und da muss er jetzt eben sagen, gut,
wenn die Prozesse nichts miteinander zu tun haben sollen,
dann soll das Betriebssystem logischerweise hier ablocken und quasi diese Schreibzugriff oder Speicherzugriffe natürlich,
also irgendwie völlig das junge Adressen betreffen.
Wenn das aber eben wirklich jetzt gemeinsam ist,
dann ist es letztendlich Aufgabe des Programmierers,
der dann eben wirklich dafür sorgen muss,
dass bei parallel ablaufenden Sachen dann eben auch wirklich bestimmte Reihenfolgen eingehalten werden,
um dann eben letztendlich sowas wie ein Determinismus in einem Programm oder in einem Algorithmus mit drin zu haben.
Und da hat man dann letztendlich keine andere Möglichkeit,
als zu sagen, also ich muss das explizit im Code mit einbauen,
indem ich dann eben Seemarfore benutze,
über irgendwelche Locking-Mechanismen dafür sorge,
dass sich also quasi die Sachen da jetzt nicht gegenseitig irgendwie was zerschießen können,
ich eben irgendwelche Befehle habe,
um sowas wie atomare Operationen auszuführen und so weiter und so
Gut, ich denke mir, das sind natürlich alles Inhalte,
die dann noch sehr viel genauer und dann auch wirklich im Einzelnen in der Softwareentwicklung drankommen werden.
Ich, aber das ist dann hier also auch nur
noch mal drauf hingewiesen. Gut, ansonsten alles,
was jetzt hier auf den letzten paar Folien noch kommt,
ist etwas, was sie dann zumindest teilweise nachher entsprechend wiederholt.
Aus Zeitgründen werde ich das jetzt hier überspringen,
beziehungsweise zu diesem Teil Speicherhierarchie jetzt eigentlich auch sagen, Das,
was ich jetzt hier eigentlich so ein bisschen vermitteln möchte,
jetzt in dieser letzten Vorlesung, ist nochmal so ein bisschen Grundidee,
weswegen gibt es eine Speicherhierarchie, wofür braucht man die?
Cash-Speicher, was ist das, wie funktioniert das und ein bisschen was zu virtuellem Speicher?
Von daher werde ich dann hier bei den Folien, also einiges auch überspringen.
Teilweise sind die Sachen, wenn noch nicht ganz so genau,
also schon mal in anderen Bereichen drangekommen.
Ansonsten kann ich aber da dann eben auch nur sagen,
also das hier ist jetzt nochmal so ein bisschen Informationen,
Hintergrund wissen, was aber in dem Fall,
ich sag mal, was eine erste Informatiker sicherlich auch wissen sollte,
was aber in dem Fall also jetzt nicht in der Klausur an irgendwelchen Aufgaben drankommt.
Deswegen werde ich das jetzt auch vergleichsweise locker handhaben. Gut,
Grundidee, Speicherhierarchie ist halt eben, dass man sagt,
okay, also man hat das häufig immer, wie jetzt hier,
also in dieser Grafik aus dem Buch von Brian und All Helleran in Form,
so eine Art Pyramide, aufgezeichnet, dass man eben sagt,
ich habe direkt am Prozessor eben sehr schnellen Speicher,
in der Regel natürlich eben erstmal die direkten Prozessoregister.
Nicht dann also irgendwelche Cash-Speicher, dann den eigentlichen Hauptspeicher,
dann eben sowas wie Persistentenspeicher,
also sprich Festplatten oder aktuell dann eben SSDs und dann eben alles,
was man dann eben als verteilten Speicher nehmen kann bzw. heutzutage würde man dann eben sagen,
alles,
was in der Cloud gespeichert ist
Nicht, was sich dann dahinter verbirgt, ist,
dass man eben von kleinen Speicherbereichen, also Register,
dann eben bis zu entsprechend großen Speicherbereichen,
dann eben genau diese ganze Unterteilung hat,
um damit eben wirklich so einen möglichst optimalen Kompromiss hinzubekommen aus den Kosten,
Zugriffszeit und der verfügbaren Kapazität für Speicher,
weil man könnte natürlich auch sagen, na gut,
also nicht statt Festplate, Startcash,
statt sonstigen baue ich eben in den Prozessor.
Jetzt eben keine 8 oder 16, sondern Register,
um da also quasi 4 Gigabyte Speicher drin unterzubringen. Nicht,
was das Würden dazu führen,
das letztendlich dann die Chips also auf einmal so groß wären
und damit dann also nicht mehr bezahlbar und das dann eben,
sagen wir mal, natürlich dann auch um die Daten dauerhaft zu speichern,
die dann eben quasi auch dauernd mit Strom versorgt werden müssten.
Nicht deswegen hat man da dann eben letztendlich diese Speicherhierarchie davor.
Was sich dann dahinter verbirgt, ist dann eben auch etwas,
das man als richtige Begriffe noch hat, räumliche und zeitliche Lokalität. Nicht,
dass es also etwas, womit dann eigentlich auch gewährleistet ist,
dass das Ganze überhaupt funktioniert, weil ich kann eben sagen,
wenn ich ein Programm habe,
was also gerade auf der CPU läuft,
was irgendwo rechnet,
dann braucht das Programm quasi jetzt von dem Assemblierten Code natürlich
genau die Befehle,
wo es sich gerade befindet
Es braucht aber jetzt nicht also irgendwelchen Code oder irgendwelche Befehle
von irgendwelchen anderen Programmen, die gerade nicht laufen.
Und es braucht natürlich auch nur seine eigenen Daten und im Zweifelsfall,
wenn es vernünftig programmiert ist von seinen eigenen Daten natürlich,
also auch nur einen gewissen Ausschnitt. Und das ist eben das,
was dann letztendlich räumliche und zeitliche Lokalität meint,
dass eben zu einem gewissen Zeitausschnitt ich eben mit einem Teil der Daten
sowohl Programmdaten als auch jetzt Daten oder Instruktion auskommen kann.
Und ich muss eben dann nur dafür sorgen,
dass das quasi der CPU zur Verfügung steht,
aber eben der gesamte Rest im Zweifelsfall nicht,
beziehungsweise dann eben nur Ballbedarf nachgeladen werden kann.
Gut, hier sind dann die einzelnen Bereiche, Register,
Halbleiterspeicher als S-RAM oder als DERAM. Dazu hatte ich ja
schon mal so ein bisschen was in dem Kapitel Äh,
hier entsprechend zurück. Rechner, Architektur hier unter Hardware-Strukturen gebracht.
Da ging das also schon mal ein bisschen um Rammspeicher,
wie die aufgebaut sind, wie die sich unterscheiden, beziehungsweise um Bussysteme.
Nicht, das heißt, da wiederholt sich einiges,
deswegen will ich da jetzt also auch gleich hier noch ein bisschen mehr überspringen.
Gut, also wie gesagt, Halbleiterspeicher, Festplatten beziehungsweise Flash und SSDs
und dann eben als unterster Ebene sowas wie Hintergrundspeicher.
So rein aktuell könnte man jetzt eben sagen, grob zusammengefasst,
Nicht, also bei so einem normalen, gut,
hier ist es Memory Hirockey for Server, gilt aber letztendlich genauso,
beziehungsweise inzwischen mit den Eckwerten auch für Standard-Desverbrechen nach, beziehungsweise Laptops.
Ich kann nicht eben sagen, ich habe hier in der CPU meine Register,
dann also klassisch drei Ebenen Cash,
den eigentlichen Hauptspeicher und eben irgendwelchen Hintergrundspeicher dann eben auf Festplatten und dahinter verbirgt sich dann eben noch das,
was man dann als virtuellen Speicher bezeichnet war,
womit ich dann also heute letztendlich dann noch abschließen werde.
Nicht ähnliches gilt dann eben genauso für irgendwelchen Mobilgeräte.
Also auch da ist man inzwischen schon so weit,
dass man sagt, na gut,
also ich habe jetzt eben nicht nur den eigentlichen Hauptspeicher,
sondern dann eben auf dem Weg,
auf dem Weg zur CPU dann eben auch noch irgendwelche Cash-Speicher dazwischen.
Gut, hier wird jetzt auf den nächsten Folien also nochmal
ein bisschen was zum Rahmen bzw. zum Festplattenspeicher gesagt,
das werde ich jetzt alles mal überspringen.
Hier jetzt nur nochmal zusammenfassend eigentlich die als Eigenschaften,
wie gesagt, Zugriff auf Register, geht entsprechend schnell,
ist dann aber eben auch jetzt einfach von den Anschaffungskosten teuer.
Esram ist auch noch vergleichsweise schnell ein teuer, möchten während meinen Festplatten,
bin ich dann eben günstig, die sind dann aber eben entsprechend langsam.
Hier sind dann eben so ein paar typische Werte,
also zum Beispiel für den DRAM-Speicher, Kosten pro Gigabyte,
da ist man also irgendwo so im Bereich von 5 Euro,
je nachdem welche Speicherriegel man nimmt, also plus minus das Epstilon.
Bei Festplatten ist man also irgendwo so im Bereich von 4 Cent pro Bigabyte,
hat dafür aber eben ein Faktor 500.000 in der Geschwindigkeit dazwischen. 800 Sekunden,
4 Millisekunden, nicht und also auch diese 8 Nanosekunden sind natürlich noch vergleichsweise langsam,
weil wenn ich auf der anderen Seite sehe,
wie oder mit welcher Geschwindigkeit, also quasi jetzt der Zugriff auf Register ist,
nicht bei einer Tagtrate von 3,3 Gigahertz, sagen wir mal nicht,
da ist man da bei 300 Pico-Sekunden.
Nicht, dann dauert das also auch noch entsprechend lange.
Gut, ich habe eine Frage. Ja, erstens sind
die ganzen Potien, die Sie übersprungen haben, trotzdem relevant.
Ich bin also inhaltlich. Da kann man nur Sachen geben
. Also die Frage war jetzt eben nochmal zu den,
zu den übersprungenen Folien. Ja, sowas davon lud dezent
natürlich nie fragen, ob die inhaltlich relevant sind.
Jetzt muss ich natürlich sagen, natürlich ist das relevant,
sonst hätte ich das ja nicht in die Folien mit reingebracht
Nein, also ehrlich gesagt, also es ist irgendwas,
was man als Informatiker wissen müsste oder sollte oder im Hinterkopf haben soll.
Es ist aber jetzt nichts, was man also irgendwie zwingend auswendig lernen muss.
Und grob, worum es geht, ist also schon mehrfach in der Vorlesung gefallen.
Und sagen wir mal so ein paar Sachen,
die da drin sind, das sind also irgendwie jetzt Beispiele,
also aus den Referenzbüchern, wo ich dann auch sage,
da wird also bei Festplattenkapazitäten,
also irgendwie so ein Rechenbeispiel gemacht,
wo man sagt,
das hat mit aktuellen Festplatten
überhaupt nichts mehr
zu tun
Deswegen kann man nur sagen, okay,
also man sollte grob wissen, was ich, wie,
wo dahinter verbirgt, aber wirklich einzelne Zahlen oder alles.
Das kann man jetzt also großzügig drüber weggehen.
Also nachher kommen auch noch so ein paar Sachen,
wo ich dann also auch nochmal entsprechend schnell vorsprühen werde.
Also Interesse halber, reingucken, aber kann man diagonal lesen.
Gut, ja, deswegen,
eben eigentlich nochmal Motivation zur Speicherhierarchie bzw. in dieser Folie,
die nun auch
ein bisschen älter ist
Ist das Ganze, also insofern noch mal ein bisschen auf den Punkt gebracht,
wo man da wirklich sehen kann, also hier von 2000,
nein, Blödsinn 1992 bis 2002, habe ich hier die Entwicklung der Geschwindigkeit bei Prozessoren.
Logarithmische Skala, Moas Law, ja,
das hatten wir alles schon mal, exponentielles Wachstum auf lugarithmischer Skala,
gibt dann also Pima Daumen irgendwo so eine Gerade,
was hier dann eben auch mit einigen der wärmers aktuellen Prozessoren und hier dann also irgendwie als schnellstes,
also ein 3, 3 Gigahertz-Pentium 4 dann also irgendwie aufgezählt,
ist also auch einigermaßen stimmt.
Inzwischen ist das Ganze hier oben so ein bisschen abgeflacht.
Gut, da sieht man, wie die Prozessoren schneller geworden sind.
Hier in dem Bereich habe ich SD-RAM, also das,
was Hauptspeicher ist. Auch der ist exponentiell schneller geworden.
Also auch hier ist das Wachstum irgendwo auf so einer Garde.
Was man aber sieht, ist, dass die Steigerung hier
schon mal eine andere ist als beim Hauptspeicher. Das heißt,
Diese Geschwindigkeitsdifferenz, die ich also zwischen Hauptspeicher und Prozessor habe,
wird eben Größenordnungsmäßig mit jeder Generation dann eben auch immer noch größer.
Ich hier unten dann eben nochmal die Geschwindigkeit,
das ist dann hier als Prozessor IO-Gap bezeichnet,
die Geschwindigkeit jetzt mit irgendwelchen Ein-Ausgabekanälen. So, das heißt,
wir haben jetzt hier einfach erstmal massives Problem,
dafür zu sorgen, dass unsere hochgetakteten CPUs mit Instruktionen versorgt werden,
weil die kommen irgendwo letztendlich aus dem Hauptspeicher und mit Daten versorgt werden, beziehungsweise Daten irgendwie schreiben können.
Also bislang, also Kapitel da, 15,
wo es also um Assembler-Programmierung ging,
da habe ich eben gesagt, ja, Load und Store,
da holt man jetzt irgendwas aus dem Hauptspeicher und schreibt das in den Hauptspeicher zurück.
Nicht, wenn ich hier nachgehe,
kann ich das natürlich machen, das dauert dann aber,
also pro Load und Store-Befehl,
also irgendwie mehrere hundert oder mehrere
tausend Taktzyklen
Das möchte man natürlich nicht, weil dann nützt du die ganze teure CPU nichts,
wenn die also irgendwie bei dem zweiten Befehl also erstmal irgendwie ein paar tausend Takt zu denen warten muss.
Das ist eigentlich genau das,
weswegen man jetzt eben immer noch die Cashes dazwischen hat,
die dann hier schon mal schneller sind und dann,
indem man quasi jetzt in der Übertragung dafür sorgt,
dass, wenn ich ein Lot oder ein Store mache,
ich im Prinzip ein einzelnes Datenwort von der Addressierung im X86-Assembler,
also beispielsweise erstmal ein einzelnes Bike, lese oder schreibe.
Wenn jetzt aber vom Hauptspeicher in den Cash was übertragen wird,
dann passiert das nicht weitweise,
sondern wird gleich ein gesamter Block von mehreren Kilobyte komplett übertragen,
sodass, wenn ich das erste Mal irgendwas in den Cash geladen habe und ich eben diese räumliche Lokalität habe.
Das heißt, das nächste Datum ist bei einer ähnlichen Speicheradresse,
ich eine relativ große Wahrscheinlichkeit habe, nächsten Speicherzugriff,
ich das Ergebnis dann eben auch schon in einem Cash finde.
Dass es dann eigentlich der Trick dabei für diese Speicherhierarchie.
Gut, hier nochmal eben so ein bisschen zusammengefasst. Wie gesagt,
ich habe schnellen Speicher, der aber eben vergleichsweise teuer ist.
Demzufolge leistet man sich davon eben auch nur sehr wenig.
Ich habe langsam Speicher, der wenig kostet. Und was
man eben macht, ist, dass man dann sagt,
okay, ich habe den Prozessor,
der läuft eben mit einigen Gigastakt
Wenn ich direkt jetzt mit den Registern rechne,
die arbeiten mit voller Prozessorgeschwindigkeit, dann kann ich eben sagen,
DRAM-Speicher, also das, was Hauptspeicher ist,
im Bereich 60 bis 100, 100 Sekunden,
da bin ich schon um Faktor 100 langsamer.
Und dieses dazwischen wird dann eben letztendlich vom Cash erschlagen.
Und wenn ich sage, ich lese irgendwas von der Festplatte,
dann ist man, nicht wenn ich jetzt also sage,
Festplattenzugangszeit, einige Millisekunden-Bereich,
dann ist man also schon um Faktor Millionen langsamer
Das ist dann eben das, was ich dann dahinter noch
in der Speicherhierarchie verbürge. Und gut,
wenn ich jetzt eben sage, ich habe eine entsprechende Lokalität,
dann funktioniert das Ganze eben dadurch, dass ich sage,
mein Programm, was jetzt wirklich auf dem Prozessor läuft,
rechnet eben erstmal nur auf Registern oder auf dem Cash.
Wenn es also jetzt wirklich ein Hauptspar,
also ein Cash-Miss hat, das heißt,
irgendwas anfordert was nicht im Cash ist,
schon auf den Hauptspeicher zugreifen muss,
dann wird es in der Regel schon Ost von der CPU
runtergenommen und irgendwas anderes
Rechnet nicht. Und wenn ich also jetzt vom Programm aus sowas
wie ein Platenzuckere farbe, dann wird relativ sicher das Programm,
also quasi jetzt erst mal ausgesetzt irgendwas anderes rechnet.
Es wird dann eben dafür gesorgt,
dass die Daten übertragen werden und anschließend läuft das Ganze weiter.
So, wer sorgt jetzt dafür, dass diese Speicherhierarchie funktioniert?
Wie ich, wenn ich mir jetzt angucke,
wie sieht das aus mit der Zuordnung von Register zum Speicher?
Okay, also als Assembler-Programmierer mache ich das natürlich direkt von Hand.
In der Regel müssen wir uns damit Asia nun nicht irgendwie rumschlagen.
Das heißt, das macht der Compiler für uns.
Das, was Cash-Speicher ist, das heißt,
wie sieht jetzt diese gesamte Verwaltung von dem Cash-Speicher aus?
Das heißt, wer sorgt dafür, dass,
wenn ich jetzt eben auf eine Speicheradresse darauf zugreife,
die Sachen irgendwo im Cash landen, das macht die Hardware automatisch.
Das heißt, also Cash ist wirklich voll transparent,
darum muss sie mich als Programmierer nicht drum kümmern.
Glücklicherweise. Und so war es wie Zuordnung von Hauptspeicher auf Plattenspeicher,
mache ich entweder, indem ich jetzt also in meinem Programm mit Dateien für ein- und Ausgabe arbeite,
dann ist das also jetzt wirklich explizit natürlich gemacht.
Oder wenn ich dann eben des Konzeptes virtuellen Speichers nehme,
wo ich dann eben sage,
ich habe theoretisch mehr Speicher zur Verfügung als jetzt eigentlich Hauptspeicher und das
wird dann eben im Hintergrund irgendwie auf die Platte ausgelagert,
dann ist das eben etwas,
was das Betriebssystem beziehungsweise teilweise dann immer noch unterstützende Hardware-Einheiten machen,
was dann eben Segmentierung und Paging sind
Gut, hier, jetzt eben nochmal aus einer anderen Grafik,
aus einem anderen Buch, aber im Prinzip genau das Gleiche,
Prozessorgeschwindigkeit, Geschwindigkeit vom DRAM-Speicher nicht und man sieht also immer,
diese Lücke wird entsprechend größer und das ist eben das,
wo dann also letztendlich der Cash, der dazwischen sitzt,
dafür sorgt,
dass das geschlossen wird.
Technisch ist der Cash dann eben als Esram umgesetzt,
Transparent hatte ich eben schon erwähnt, das heißt also,
der Programmierer sieht davon nichts,
das passiert alles letztendlich durch die Hardware
Dann, was im Cash logischerweise auch noch mit drin ist,
wenn ich jetzt wieder drei Kapitel zurückgehe zum, den Sparkapitel,
Kapitel 16 war das, zum Thema Pipelining.
Nicht da ging es dann ja letztendlich darum, dass man sagt,
damit das Pipeline nicht funktioniert, brauche ich Harvard-Architektur, das heißt getrennte Speicher für Instruktionen und Daten.
Nicht genau das passiert dann eben in so einer Speicherhierarchie beim First-Level-Cash,
das heißt die CPU wirklich getrennt, Instruktionen und Daten,
was dann eben eine First-Level-Cash oder durch den First-Level-Cash realisiert wird.
Und später wird das dann eben erst wieder in Richtung auf den Hauptspeicher, was dann die Rahmen ist, zusammengeführt. Gut,
das, was eben passiert,
wenn ich jetzt also mit meinem Programm aus irgendeine Adresse referenziere,
ist, dass von der Hardware-Seite aus eben Folgendes passiert,
dass eben diese Zugriff auf die Adresse,
quasi parallel von First Levels, Second Levels,
Third Level Cash und eben vom Hauptspeicher,
also sprich von der Memory Management Unit irgendwie verarbeitet wird und wenn eben einer der Cashes dann eben schon das Ergebnis hart liefert,
der eben das entsprechende Datenwort ansonsten wird halt eben signalisiert Cashmith und dann muss eben entweder das Betriebssystem dann nochmal eingreifen,
um es eben beispielsweise zu sagen,
ein anderer Prozess soll jetzt weiter rechnen und es wird eben dann quasi der laufende Prozess unterbrochen,
bis das Datum aus dem Hauptspeicher dann eben wirklich im Cash gelandet ist oder der Prozess wird eben entsprechend angehalten.
Damit wird dann eben genau diese Wartezeit von mehreren hundert Takten signalisiert. Gut,
hier auf dieser bzw. der nächsten Grafik ist dann eben nochmal kurz an,
einfach nur die Idee, aber das ist ja eigentlich klar,
skizziert, nicht dass man sagt,
wenn ich einen gemeinsamen Cash für Instruktionen und für Daten habe,
nicht also von der Idee her, von Neumann-Rechner,
ein gemeinsamer Datenspeicher, Memory, der aber eben logisch unterteilt ist,
natürlich in Instruktionen und Daten.
Wenn ich genau das Gleiche quasi jetzt in den Cash übertrage,
habe ich dann eben einen gemeinsamen Cash oder im Englischen dann auch Unified Cash.
Wenn ich das separiert habe, in Instruktions- und Datencashes,
Würde das dann ebenentsprechend so aussehen, nicht und typischerweise,
von der Idee her ist es eben so, dass man sagt,
also First-Level-Cash ist logisch gesehen so aufgebaut, alles,
was dann kommt als Unified-Cash, also als gemeinsamer Cash.
Gut, hier ist er nochmal kurz angedeutete Position,
First Second Level Cash nicht, also alles,
je nachdem, wie nah ich in der CPU bin,
wird das dann eben entsprechend unterteilt.
Nicht, das hängt dann eben konkret noch ein bisschen davon
ab, wie dann also hier die Bussysteme aussehen
Das ist dann aber dann eigentlich wieder eine Eigenschaft der Hardware-Architektur.
Das heißt also, welche CPU, welcher Prozessor, Hersteller,
welcher Chipsatz dahinter liegt, wie das Ganze dann eben wirklich aufgebaut ist.
Gut, dann, was immer noch unterschienen würden,
was dann also auch noch wichtig ist, ist die Frage,
also ob ich einen virtuellen Cash habe oder einen physikalischen Cash.
Und zwar verbirgt sich dahinter noch die Idee,
auf die ich dann nachher noch eingehen werde,
wenn es also dann wirklich um virtuelle Adressierung geht.
Dass man sagt, ich habe jetzt mehrere Programme,
die jetzt ja irgendwie laufen sollen. Die haben letztendlich ja
irgendwie alle einen gemeinsamen Adressraum-Party. Hatte ich ja eingangs,
als ich da die Übersetzungshierarchie dann vorgestellt hatte,
also auch schon mal kurz gesagt, also der Compiler,
der den Assembler-Code erzeugt, sagt jetzt halt,
okay,
also ich adressiere von null bis N,
baue das also irgendwo in meinen Code ein
Dann kommt der Linker, der Link jetzt, also die einzelnen Objektdateien zusammen,
gegebenenfalls werden dann also noch irgendwelche Laufzeitbibliotheken statisch hinzugelingt.
Dann habe ich quasi ein ausführbares Executable.
Auch dort habe ich letztendlich von den Adressen und im Adressbereich
auch erstmal immer nur von 0 bis N irgendwas laufen.
So, und wenn ich jetzt zwei unterschiedliche Programme habe,
die also nichts miteinander zu tun haben,
dann ist in dem einen halt eben irgendwie von 0 bis irgendwas adressiert.
In dem anderen genauso. So,
zur Laufzeit muss ja jetzt Folgendes passieren, dass der Loader,
das heißt, der Teil, der vom Betriebssystem angestoßen wird,
wenn ich ein Programm jetzt wirklich per Droppel klicke,
für Eingabe in der Kommandozeile, wie auch immer, für Ausführungen bringe.
Und das Programm in den Hauptspeicher geladen wird, dafür sorgt,
dass die Adressen, die jetzt im Code drin stehen,
irgendwie mit den Hauptspeicheradressen korreliert werden. Das heißt,
da gibt es nochmal irgendeinen Mechanismus, der dafür sorgt,
dass eben irgendwelche Offsets pro laufenden Programm hinzugerechnet werden,
sodass die beiden Programme,
die eigentlich ursprünglich mal den Leichenadressraum haben,
eben irgendwie miteinander verschoben sind und sich nicht mehr
in die Quere kommen können
So diese Umsetzung passiert dann durch etwas,
was sie dann Memory Management Unit nennt,
wo man eben sagt, vor der Memory Management Unit,
das heißt also in der CPU rechne ich mit virtuellen Adressen.
Da habe ich nur einen Prozess, der läuft und er
adressiert von 0 bis 1. Wenn ich hier in den Speicher gehe,
ist dieser Adressbereich aber jetzt was, was ich vorhin verschoben.
Das ist eben das, was hier passiert.
Ein virtueller Cash arbeitet halt eben vor dieser Adressumrechnung,
was also jetzt quasi direkt aus dem binären Code aus dem Sandeler-Code rauskommt.
Im Gegensatz dazu ist es beim physikalischen Cash halt so,
dass ich dann eben wirklich mit den physikalischen, also mit den Hauptspeicheradressen rechne.
Und die Cash. Beides hat Vor- und Nachteile,
weil wenn ich einen virtuellen Cash habe,
dann muss ich hier nicht nur irgendeine Umrechnung machen.
Das heißt, das ist per se schon mal schneller.
Nachteil bei dem Ganzen ist, wenn ich einen Kontextwechsel mache,
das heißt also ein anderes Programm auf die CPU kommt,
muss der Cash komplett ungültig gemacht werden,
weil natürlich dieses andere Programm im Zahlsfall genau die gleichen virtuellen Erpressen benutzt.
Beim physikalischen Cash muss der Cash nie gelehrt werden,
weil damit, da arbeite ich ja jetzt wirklich mit dem Hauptspeicheradressen.
Da muss aber eben immer noch vorher diese Adressumrechnung passieren.
Deswegen sieht das in der Regel auch so aus,
dass man das natürlich irgendwie miteinander vermischt. Das heißt,
First Level, Cash würde sich dann anbieten,
sowas zu machen beim Second Level Cash,
kann man dann also hier mitarbeiten
Gut, typische Organisation, hier also auch nochmal kurz beschrieben,
First Level Cash, eben getrennte Instruktions- und Datencashes.
Typischerweise hat man das jetzt also bei den Prozessoren so als Second Level Cash
dann eben einen gemeinsamen Cash für Instruktionen und Daten für jeden Prozessorkern nochmal getrennt einzeln.
Und wenn ich jetzt eben CPU oder einen Chip habe,
auf dem ich dann eben ententsprechend mehrere Prozesserkerne habe,
gibt es dann eben beim Third Level Cash dann eben nochmal einen gemeinsamen Cash,
der dann eben für alle vier oder acht oder wie viele auch immer,
Prozesse, Perne quasi benutzt wird. Und gerade in dem Fall,
wenn ich jetzt eben quasi gemeinsam im Speicherbereich für mehrere Prozessoren haben,
also das, was dann eben die Symagic Multi-Processing ist,
dann ist eben diese Cash-Kohärenz wichtig,
nämlich das gemeinsam genutzte Daten, konsistent gehalten werden,
weil dann habe ich nämlich letztendlich folgendes Problem,
dass ich Sachen hier wieder finden,
dass ich nämlich Hier mit den Prozessoren jetzt ja nicht mehr auf eine gemeinsame Speicherzelle gehe,
sondern jede von diesen CPUs jetzt hier noch ihren eigenen Cash dazwischen hat.
So, und da kann es eben sein,
dass eine CPU hier schon was schreibt, ihren Cash verändert hat,
dort aber einen anderen Wert hat als das,
was also beispielsweise ursprünglich nochmal hier im Speicher starren.
So, und Cash-Kohärenz ist jetzt genau das Problem,
wenn jetzt also hier jemand anders was lesen möchte,
dann muss er natürlich den neuen Wert hier aus dem Cash
von dem Prozessor lesen und nicht das,
was im Speicher steht
Ich habe die Fragestellung, das ist dann eben das,
was man dann immer als Cashcore reins bezeichnet.
Sprich, wie kriegt man da dann eben solche gemeinsamen Datenkonsistent?
Gut, dann gibt es noch viele unterschiedliche Strategien,
jetzt hinsichtlich des Cashings, also welche Daten sollen in den Cash?
Jetzt kann ich natürlich sagen, ja, guter Wahrsager würde
mir helfen. Ich brauche im Cash eigentlich das,
was in der Zukunft von der CPU
irgendwie benötigt wird
Das ist natürlich immer schwierig vorherzusagen. In der Regel
lebt man dann eben eigentlich mit diesen Annahmen.
Temporale Lokalität, das heißt also zeitliche Lokalität,
also die Daten, die zuletzt häufig gebraucht werden.
Räumliche Lokalität, die Daten, die nahe denen zuletzt gebrauchten liegen.
Das heißt also, ähnliche Speicheradressen oder Speicheradressbereiche werden eben gecashed.
So, und dann gibt es eben auch noch unendlich viele
verschiedene Platzierungsersetzungs- und Schreibstrategien für den Cash,
wo es dann eben genau um solche Fragen geht
Wenn eine CPU jetzt also irgendwie einen Wert schreibt,
dann wird das erst mal nur in den Cash geschrieben.
Möchte ich das jetzt schon in den Hauptspeicher zurückschreiben?
Dann hat eine andere CPU, die das lesen möchte,
vielleicht den Vorteil, dass sie also gleich konsistente Daten hat.
Aber ich muss natürlich unnötig viel schreiben, wenn ich das vielleicht gleich nochmal neu überschreibe.
Da kann man jetzt eben je nach Anwendungsfall dann mit entsprechenden stochastischen Modellen versuchen,
das zu optimieren,
wann mache ich so ein komplettes Rideback oder wann arbeite ich eben
nur in einem Cash und schreibe dann irgendwie mal am Blog irgendwelche Sachen in den Hauptspeicher zurück und beim Lesen ihm genauso.
Dann, wenn der Cash voll ist,
es soll irgendwas anderes in den Cash geladen werden.
Was nehme ich raus? Ersetzungsstrategie. Wenn ich solche Sachen,
kommen da dann eben letztendlich mit rein. Gut, das,
was man beim Cash dann auch immer noch hat, als Kenngröße, ist dann sowas wie Cash Performance. Da geht es also letztendlich darum, dass ich sage,
mit einer gewissen Wahrscheinlichkeit finde ich mein Ergebnis im Cash,
das wäre dann ein Hit,
mit dem Gegenwert dazu habe ich dann eben eine Fehlerrate von Miss und interessant dann eigentlich nur,
also als mittlere Speicherzugriffszeit, wenn ich so ein System mit Cash einsetze,
kann ich dann eben sagen, gut, ist halt,
wenn ich es im Cash finde, die Zeit hiervon,
ansonsten muss ich das aber eben noch hinzuaddieren,
die Wahrscheinlichkeit für einen ist und die Zeit für einen ist,
Sodass man da dann eben, wenn man so ein Cash-System insgesamt betrachtet,
dann eben auf irgendwelche mittleren Speicherzugriffszeiten kommt.
Hier ist das Ganze dann also mal für so ein Beispiel aufgezeigt,
wo ich dann sage, okay, also die,
wenn ich mein Ergebnis im Cash finde,
habe ich das mit dem nächsten Tag gelesen oder geschrieben.
Wenn ich es nicht finde,
dann brauche ich 20 Takte, nicht bei einer,
wahrscheinlich oder einer Missrate von 5% Prozent,
kommt man dann also hier nach Rechenformel dann eben
auf eine mittlere Speicherzug aufs Zeit von zwei Takten
Wie kann man sich das vorstellen, dass man denn die 20-Stadt gibt?
Ich meine, wenn man kann, dann kann man natürlich jeder,
der ist, dann ist das einfach nur uns einfach vorstellen,
dass wir alles einmal ab oder so.
Also die Frage war jetzt, wie man sich das vorstellen kann,
dass man jetzt ja hier bei Mist 20 Takte braucht.
Ja, da ist,
da ist einfach letztendlich dahinter einfach nur folgendes Problem,
dass ich halt sage, wenn ich das also nicht im Cash finde,
dann muss ich das aus dem Hauptspeicher holen und das entsprechend langsam.
Nicht in der Prozesse läuft halt also irgendwo mit Gigahertz-Bereich und aus
dem Hauptspeicher kann ich eben Wenn ich einen Wert lese,
dann dauert das halt eben irgendwie so und so viele Mikrosekunden.
Irgendwo hatte ich hier, also da ist auch irgendwie die passenden Zahlen.
Also nee, also hier Nanosekunden, acht Nanosekunden,
da bin ich dann also irgendwie schon im Bereich von zehn Takten, die das dauert.
Also verglichen mit dem Hauptspeicher oder mit der CPU-Geschwindigkeit.
Also das sind jetzt einfach nur diese 20 Takte. Das heißt,
wenn ich jetzt sage, okay,
ich müsste es jetzt eben wirklich hier außen Hauptspeicher heraus lesen,
dann heißt das eben, die CBU muss letztendlich für 20 Takte stehen bleiben.
Ich warte, bis das dann also irgendwann einmal das Datum dann quasi da ist,
auf dem Speicherbus und dann kann das eben entsprechend übertragen werden.
Gut, dann habe ich jetzt natürlich gesagt,
cash tolle Sache und wie das alles von der Idee her funktioniert.
Jetzt wissen wir natürlich immer noch nicht,
wie man das also erstmal rein technisch oder rein praktisch umsetzt.
Dazu folgende allgemeine Idee. Also ein Cash kann man sich vorstellen
wie ein Array von Bereichen, in denen was gespeichert wird.
Das wird dann auch immer als Cash-Set bezeichnet. In jenen
dieser Bereiche stehen dann mehrere Cash-Zeilen, in denen quasi jetzt Speicherworte abgelegt sind.
Nicht in jede Zeile enthält dann also letztendlich hier als noch Verwaltungsinformationen,
eben quasi ein Datenblock,
wo jetzt also beispielsweise mehrere aufeinanderfolgende Bytes des Speichers vorhanden sind.
So, wie funktioniert jetzt die Umsetzung von Speicheradressen in den Cash?
Also hier die Grafik nur noch mal ein bisschen größer,
wenn man das sich noch mal ansehen will.
Wie funktioniert jetzt also die Umsetzung in den Cash?
Wenn ich jetzt also eine Speicheradresse habe, kann man eben
sagen, es gibt quasi einen unteren Speicherbereich von Babits.
Damit bezeichne ich so was wie den Block-off-Set.
Das heißt also, in so einer Cash-Zeile bringe ich,
also hiermit willen jetzt ja entsprechend immer bei der X86-Adressierung Bytes adressiert.
In so einer Cash-Zeile habe ich jetzt Großb weit aufeinanderfolgender Speicheradressen drin stehen. Das heißt,
hier mit den unteren Bits dieser Adresse sage ich quasi jetzt,
ob ich das nullte, erste Ente bis B-11. Byte
quasi jetzt hier aus dieser Cash-Zeile lesen möchte.
Mit den nächsten Witz, dem Set-Index,
wird jetzt quasi gesagt, für diese Speicherbereiche S,
in welchem Speicherbereich ich jetzt mein Wort finde.
Und mit den oberen Bits der Adresse Die werden dann als
Tech bezeichnet und die werden dann quasi als Verwaltungsinformation im Cash
auch mit abgelegt und gespeichert. Damit wird quasi überprüft,
ob ich jetzt überhaupt erstmal mit dieser Adresse irgendwas aus dem Cash
habe oder ob es jetzt also irgendeine andere Adresse ist,
deren Werte hier in dem Cash drin liegen.
Gut, hier, also wie gesagt,
dieses Adressierungsschema nochmal kurz
Skizziert. Hinsichtlich Cash-Organisation, geht es jetzt also darum zu sehen,
wenn ich jetzt Speicheradress habe, wie kriege ich die jetzt also irgendwo,
oder ein Datum des Hauptschweißs,
wie kriege ich das jetzt also irgendwo in den Cash rein?
Da gibt es also unterschiedliche Verfahren. Allerereinfachste ist Direct-Map-Cash oder
im Deutschland direkt abgebildet. Da wird eben jeder Speicheradresse genau
eine einzige Cash-Speicherzelle zugeordnet. Dann gibt es Bereichsassoziative, Cashes
. Da haben diese Sets jetzt eben nicht nur eine,
wie bei Direct Map, sondern mehrere von diesen Cashlines und
ein Ergebnis kann entweder hier oder hier oder hier,
aber jedenfalls in einer von diesen Cashlines diese Sets stehen.
Oder voll Assoziative, da kann jede Speicheradresse in jede
beliebige Cash Speicherzelle zugeordnet werden.
So, ich habe das jetzt versucht in Worten zu umschreiben.
Ich denke mir, dass es dem wenigsten klar geworden,
wie das Verfahren funktioniert
Deswegen gehört das Ganze hier jetzt noch mal ein bisschen anschaulicher dargestellt.
Also Cash, Direct Map. Kann man sich einfach
erst mal so vorstellen. Jede Adresse ist genau eine Speicherzelle
im Cash zugeordnet. Wenn dieses jetzt hier mein Speicherbereich ist,
und ich also hier quasi von diesem größeren Speicherbereich sage,
ich habe hier einen Cash mit acht Einträgen,
dann nehme ich beispielsweise jetzt also die unteren drei Bits meiner Speicheradresse und sage,
damit mache ich die Zuordnung auf eine Cashspeicherzelle.
Also auf ein Set
Und dann sieht man eben, dass also hier genau diese
Speicherzelle und diese und diese und hier diese letzte Graue,
das heißt alle, die eben hier in den unteren Bits 001 haben,
quasi auf den Cash-Set mit der Adresse 001 abgebildet werden.
Also sprich nichts anderes ist einfach ein entsprechendes Abschneiden der passenden Bits.
Das Abschneiden passiert dann, wenn ich das eben hiernach nehme,
quasi jetzt über diese Bits,
das,
was also
dieser Set-Index ist
Das ist Direct-Map. Da wird es eben direkt eins zu eins abgebildet.
Demzufolge hat jeder Set auch nur ein einzige Cashline.
Ich habe dann eben Großess-Sets, ist die vergleichsweise allereinfachste Cash-Art.
Damit kann man dann eben entsprechend große Cashes bauen.
Problem bei dem Ganzen kann eben sein,
wenn ich Zugriffe habe, die nach folgendem Schema arbeiten,
Zugriff auf eine Adresse A, A,
plus N-MLS und so weiter und so fort.
Dann kommt es nämlich zu einem Effekt,
der sich Cash-Trashing nennt. Sieht man relativ einfach hier.
Ich möchte beispielsweise bei einem Errätzugriff auf dieses Element zugreifen.
Es wird in den Cash geladen. Ich habe
das Ganze im Cash. Beim nächsten Speicherzugriff möchte ich auf
dieses Element zugreifen
Beim Direct Map Cash wäre das quasi die gleiche Cashline.
Da ist aber jetzt hier das andere drin. Also Cash miss,
dieses hier rausschmeißen, dieses hier neu reinladen,
die Speicheranforderung oder Speicheranforderung wird entsprechend dann erfüllt.
Es kann gelesen oder geschrieben werden, beim nächsten Speicher zu Graph 4
darauf, habe ich genau wieder das gleiche Problem.
Das heißt, mit jedem Speicherzugriff erzeuge ich so hundertprozentig sicher
ein Cash miss. Das ist also das,
was die Cash-Frashing ist
Gut, hier ist dann noch mal im Einzelnen aufgezeigt,
wie dann eben letztendlich der Zugriff auf solche direkt abgegebildeten Cashes funktioniert.
Das heißt, ich habe hier meine Adresse mit dem Set-Index
beispielsweise hier 5 Bit und der 1 würde ich dann eben
auf den Set 1 indizieren.
Anschließend würde dann in einem Cash geguckt,
da gibt es dann immer noch so etwas wie so ein Valid Bitch.
Ist das Gesetz, sprich sind die Cash-Daten
überhaupt gültig
Weil es muss ja immer noch unterschieden werden, nach dem Einschalten des Computers.
Es wurde noch nichts in den Cash geladen. Sich da stehen,
aber natürlich auch irgendwelche Werte, Nullen oder Einfen drin,
um eben zu unterscheiden, ist das überhaupt ein gültiges Datenwort?
Dann kommt eben der Mechanismus, der sich Line-Matching nennt.
Das heißt, da würden jetzt die verbleibenden Bits der Adresse,
die nämlich das Tech bilden, mit dem im Cash gespeicherten Tech verglichen.
Und nur wenn dieses Tech übereinstimmt,
ich also quasi hier die gleiche Adresse habe,
habe ich mit meiner gesuchten Adresse hiermit den Set ausgewählt,
den richtigen Tag und kann dann über den Block-off-Set quasi in
dieser Cashline dann eben ein entsprechendes Wort heraus adressieren.
Das ist also im Prinzip die Art und Weise, wie dann so ein Cash-Zugriff funktioniert.
So rein technisch kann man das also vergleichsweise einfach machen,
indem ich dann eben sage, ich habe hier ein entsprechend großes Esram,
wo ich dann also hier quasi ganz normal über die Adresse,
dekodiere und sage, ich habe hier meine Datenworte.
Diese untere Teil, der Block-off-Set macht nichts anderes als über einen Multiplexer,
dann eben hier die entsprechenden Datenbereiche nur auszuwählen. Mit dem Set-Index,
das ist eben genau meine Adresse,
mit der ich den Set auswähle und mit dem oberen Tal,
der Tag, wird dann eben genommen und mit dem gespeicherten Tag verglichen und nur,
wenn diese Texte gleich sind, habe ich dann eben ein Cash-Shit,
das heißt eben das richtige Wort aus Location gelesen, beziehungsweise angesprochen.
Gut, das ist also die Art und Weise,
wie ein direkt abgebildeter Cash funktioniert. Hier ist das Ganze
jetzt nochmal für so ein bisschen Assembler-Code als Beispiel beschrieben.
So, ich jetzt irgendwas völlig Falsches vorlese. Also,
Ich habe hier einen Cash, der ist ursprünglich leer.
Ich habe hier jetzt also irgendwie eine Adresse, 32 Bitbreit.
Hier, meinetwegen jetzt 8 CPU-Register, Programmzähler,
Instruktionscounter und hier irgendwas im Speicher. Hier als Instruktionsspeicher,
jetzt also irgendwelche Assembler-Befehle hier im Datenspeicher, jetzt eben irgendwelche Werte.
So, Programmcounter ist A000. In demzufolge möchte ich also hier
diesen Buffet letztendlich lesen
Nicht, was passiert. Es wird quasi versucht zu lesen. Ein Fletch-Miss passiert,
weil, und er dieser Adresse ist, hier also nichts abgelegt.
Von der Behandlung her wird dann also quasi das Wort außen
oder der entsprechende Bereich dann eben aus dem Speicher geladen.
Hier in einem Cash, abgelegt,
was man dann eben hier auch schon sieht, ist natürlich,
dass ich jetzt hier nicht einzelne Worte lese,
sondern eben diese Cashline dann eben auch entsprechend groß ist,
sodass dann eben auch gleich ein ganzer Speicherbereich dort übertragen wurde
So, anschließend habe ich jetzt eben jede den richtigen Wert
und kann dann eben das Ganze in ein Instruktionsregister einladen.
Gut, da steht jetzt ein Befehl. Lot. Und zwar
von der Adresse R1 mit Offset 8 in Register 2 Laden.
Nicht, jetzt sind wir in der Execute-Phase dieses Befehls.
Auch hier ist jetzt eben ja wieder ein Speicherzugriff.
Ich habe ein Cashmith
Auch da wird dann also quasi hier die entsprechende Adresse berechnet,
was dann also die hier ist.
Der Bereich in die Cashline übertragen und anschließend dann eben wirklich,
wenn das also in der Cashline drin ist,
dann eben der entsprechende Wert hier mit reingelesen.
Damit ist dann also hier dieser erste Befehl dann das Execute letztendlich abgearbeitet.
Gut, anschließend würde dann Der Programmzähler inkrementiert werden,
der nächste Befehl geladen werden. So,
jetzt hat man hier glücklicherweise endlich mal einen Cash-Hit.
Beim Fetch, der Befehl, steht hier jetzt schon,
also quasi unter eins dann in der Adressline.
Wird dann quasi jetzt hier reingeladen in das Instruktionsregister und entsprechend abgearbeitet.
Hab dann hier in der Abarbeitung jetzt also hier bei der Adressierung,
die dann stattfindet,
an der Stelle dann eben auch schon ein
Eine Ausführung, ein Hit, Cash it, das Ganze wird abgearbeitet.
Der nächste Befehl läuft problemlos durch, wird abgearbeitet,
wo jetzt also hier was berechnet wird und so weiter und so fort.
Und dann erst beim fünften Befehl,
der jetzt also hier nicht mehr in dieser Cashline drin ist,
habe ich dann eben wieder
einen Mist
Hier wird dann eben wieder entsprechend die Daten in die Cashline
geladen und dann entsprechend weiter ausgeführt. Das heißt also,
hier ist jetzt einfach mal so von der Berechnung her dargestellt,
wie jetzt im Prinzip erstmal so ein einfacher Direct Map Cash funktioniert,
vorausgesetzt, also was ja auch schon wieder der Fall ist,
ich habe gemeinsam Instruktions- und Datenspeicher und eben auch einen gemeinsamen Cash dafür.
Also die Adressen, hier sind auch alle passend so gewählt,
dass sich das also erstmal nicht in die Quere kommt.
Aber da kann man das dann eben wirklich am Beispiel nochmal nachvollziehen.
Wenn ich jetzt natürlich eine gesamte Cash-Hierarchie habe mit mehreren Ebenen
Cashes und dann eben auch noch getrennt Instruktions- und Daten-Cash.
Letztendlich ist es immer die gleiche Situation,
bloß das Beispiel wird dann also derartig unübersichtlich,
deswegen muss ich sagen, nicht. Also dies hier ist etwas,
was man als Veranschaulichung dann nochmal ganz gut vorstellen kann,
rein praktisch würde es aber eben auf aktuellen Rechnen oder auf aktuellen CPUs dann eben auch schon anders laufen.
Gut, aber hier ist dann eben wirklich nochmal so ein bisschen grafisch dargestellt,
wie eigentlich jetzt dieser Cash-Mechanismus wirklich in der Abarbeitung von Programmen,
Instruktionen holen, Instruktionen dekodieren, ausführen, letztendlich funktioniert.
Gut, das war jetzt als erstes einfachste Art Direct-Map-Cash,
wenn ich jetzt sage, ich habe im Bereich Assoziative Cashes,
also Set Associative Cashes, unterscheidet sich dadurch,
dass ich jetzt eben sagen kann, ich habe in jedem Dieser Sets,
jetzt nicht nur eine, sondern mehrere Cashlines, typischerweise zwei oder vier,
demzufolge heißen die im Englischen dann auch immer Two-Way-Set, Associtive oder Four-Way-Set-Associtive Cashes.
Gut, inzwischen taucht das nicht mehr so auf,
also Ende der 90er Jahre haben sich Intel und AMD dann immer quasi in den Datenblättern,
dass dann immer hervorgehoben,
dass jeweils ihre Art und Weise des Cashes, Also,
AMD hatte, glaube ich, immer zweifache Assoziative,
aber dafür größere Cashes, Intel HT4-fache Assoziative,
aber dafür kleinere Cashes.
Den und jeder hat dann also quasi immer mit irgendwelchen Beispielen vorgerechnet,
dass die eigene Strategie dann also die deutlich bessere und effizientere wäre.
Und man dem zufolge dann auch den Prozessor von ihm kaufen sollte.
Gut, wie sieht ein Zugriff auf solche Endfach-assoziativen Cashes aus?
Im Prinzip eigentlich genauso. Mit dem Set-Endex berechne ich
den Set. Was jetzt hier aber,
dann wird eben geguckt, mit diesem Value-Bit sind
die Daten gültig
Was jetzt aber hier eben sein kann, ist,
dass ich jetzt eben hier nicht nur eine, sondern mehrere Zahlen habe.
Und da sieht man jetzt eben genau,
wofür man jetzt also diese Tech-Bits braucht,
weil also quasi jetzt von dieser Adresse verglichen wird,
entsprechend diese Tech-Bits, den in dieser Cash-Line.
Wenn ich hier keine Erleihübereinstimmung habe, dann habe ich einen Cash-Mith,
wenn entweder der oder der übereinstimmt, weiß ich eben,
diese Adresse ist entweder in dieser oder wie hier in dem Beispiel in dieser unteren Cash-Line.
Und dann kann man eben auch wieder mit diesem Block auf Setups
entsprechende Spannungen gleicher Wort heraus adressieren. Ich das also,
die Art und Weise, wie das funktioniert,
also wie gesagt, von der Idee her genauso,
bloß ich habe jetzt eben hier gleich mehrere mögliche Ablageorte.
Führt dann dazu, wenn man das in Hardware umsetzen würde,
spare ich ja letztendlich genauso aufgebaut,
aber ich brauche dann eher sie natürlich dann hier mehr Hardwareaufwand,
weil ich dann eben beispielsweise dann parallel für alle Texte
das natürlich vergleichen möchte und man dann eben entsprechend viele
parallele Vergleiche machen muss
So,
und da ganz allgemeine Fall,
ein voll assoziativer Cash,
da kann ich jetzt eben sagen,
ich habe nur noch einen einzigen Set und jede Speicheradresse kann hier irgendwo beliebig drin liegen,
den zufolge brauche ich dann natürlich entsprechend viele Vergleiche und das Ganze gilt eben nur für extrem kleine Cashes,
typischerweise für bestimmte Sachen,
die man also dann betriebssystemseitig bzw. generell
für die Speicherverwaltung dann noch braucht
Gut, dann stellt sich jetzt noch so ein bisschen die Frage nach der Cash-Dimensionierung,
sprich, wenn ich jetzt eine Adresse habe,
wie viele Bits spendiere ich hierfür,
wie viele Bits spendiere ich hierfür und so weiter.
Nicht dazu, kann man ja immer sagen, im Cash wären ja,
also quasi haben wir diese kompletten Cash-Lines gespeichert, das heißt also größere Speicherblöcke.
Jetzt kann ich natürlich sagen, wie groß oder wie kleinwählig die.
Und zwar, wenn ich sage, ich habe Eine große Blockgröße.
Das heißt also, ich habe in einer Cashline sehr viele aufeinanderfolgende Bytes.
Ist das natürlich ganz gut, wenn ich jetzt das gefunden habe?
Also meine räumliche Lokalität habe, dass ich dann mit einer
entsprechend großen Wahrscheinlichkeit auch beim nächsten Zugriff wieder was in dem Cash finde.
Nachteil bei dem Ganzen ist dann aber,
dass wenn ich ein Misse habe, also ein Cashmith,
ich natürlich dann jetzt nicht nur Wenig Daten,
sondern dann eben entsprechend viel Daten aus dem Hauptspeicher erstmal in die Cash-Line übertragen muss.
Demzufolge dann eben auch mit der entsprechend großen Blockgröße diese Miss-Penalty anwächst. Nicht,
das heißt, insgesamt ergibt sich dann abhängig von der Blockgröße etwas,
wo man sagen kann,
es gibt eben Effekte hinsichtlich der räumlichen und der zeitlichen Lokalität,
wo ich dann eben für einen Cash sowas für so
eine Art lokales Minimum habe,
wo quasi bei dieser Dimensionierung,
dass also letztendlich
am besten funktioniert
Typischerweise kann man dann eben sagen, mich,
also das ist dann hier so per Simulation,
beziehungsweise dann eben entsprechende Programme dann einfach mal ausprobiert, sagen,
also die Blockgröße in den Cashes ist ebenso im Bereich von 32 bis 128 byte.
Und die Größe der Cashes dann eben im First-Level-Cash bis 256
Milobat im Second Level Cash dann eben schon bis vier Mediabyte und so weiter und so fort.
Das Ganze ist dann auch immer noch so ein bisschen davon abhängig,
also ob ich das jetzt also für einen Direct Map zweifach assoziativen oder voll assoziativen Cash mache,
wo ich dann eben auch unterschiedliche Abstufungen hinsichtlich dieser Performance-Werte habe.
Gut, all das kann man letztendlich über entsprechende Simulationen,
wo ich dann eben quasi durchspiele und berechne, mit welchen Adressen rechne ich,
mit welchen Cashgrößen rechne ich, was würde passieren,
wenn ich eben Cashmith habe und das Ganze dann eben jetzt wirklich für irgendwelche Anwendungs-Benchmarks dann eben mal durchspiele,
durchrechnen, optimieren und dann eben gucken,
wie kriege ich da jetzt das Ganze jetzt eben entsprechend optimal ausgerichtet,
bzw. optimal dimensioniert.
Gut, hier auch noch mal aufgelistet bei den Cashmiths,
wird dann auch noch unterschienen zwischen drei unterschiedlichen Arten.
Einmal der Cash ist noch leer, nennt sie dann Coldmith
Dann sowas wie Konfliktmiss. Wenn ich nämlich diese Verdrängung habe,
das heißt also, es wird irgendwas in den,
aus dem Cash gelesen,
was eben genau unter dem gleichen Set wieder eine Verdrängung hervorrufen würde.
Nicht, also das Beispiel hier hatte ich ja vorhin schon genannt,
also mit der Größe 8. Und wenn ich eben Zugriff habe
auf null 8,
08 abwechseln würde,
eben jedes Mal
ein Miss passieren
Und dann gibt es eben noch so etwas wie Capacity-Teams,
wenn der Cash insgesamt einfach zu klein dimensioniert ist,
wo man dann eben auch sagen kann,
wie groß soll man die Cashes machen?
Ich kann natürlich sagen, je größer insgesamt, umso besser.
Andererseits, Cash ist teuer und ein Prozessorhersteller will natürlich
sein Produkt zwar teuer verkaufen, aber billig produzieren.
Also wird er schon zusehen, dass er die Cashes so wählt,
dass sie zwar vernünftig arbeiten,
dem benutzt er also die entsprechende Performance-Steigerung bringen
Die andererseits aber natürlich nicht größer gemacht werden als das,
was letztendlich, also irgendwie sinnvoll ist. Andererseits,
wenn sie zu klein sind und ich eben jetzt quasi als typischen
Working Set in meinem Programm halt eben irgendwo einen Adressbereich habe,
der deutlich größer ist als das,
was ich in einem Cash unterbringen kann,
habe ich natürlich eine relativ größere Wahrscheinlichkeit,
dass ich in dem Programm Cash Mrs.
erzeuge und eben das entsprechend langsamer abläuft.
Deswegen sollte der Cash dann eben eine gewisse Mindestgröße haben,
aber eben natürlich einfach aus diesen wirtschaftlichen Überlegungen heraus dann eben auch wieder nicht zu groß sein.
Gut, hier nur nochmal aufgezählten mit dieser Ersetzungsstrategie beim Direct Map Cash,
muss man sich da keine Gedanken machen,
weil da wird das einfach direkt über die Adresse gemacht.
Da gibt es keine Ersetzungsstrategie. Wenn ich ein mehrfach assoziativen Cash habe,
Da kann ich ja sagen, gut,
da kann ich ja unter in einem Cash-Set, oder jetzt unter einer Adresse,
bin ich also ein Cash-Set 1 beispielsweise adressiere, das Wert,
den Wert entweder hier oder hier oder eben in irgendeiner anderen Cashline speichern.
Frage ist jetzt, in welcher, beziehungsweise gerade wenn in
der Cashline schon was steht, welche soll wieder rausfliegen?
Nicht, und da kann man dann eben sagen,
typischerweise entweder Leasterys sind die used, das heißt,
der am längsten nicht benutzte oder er liest Frequent Lyused,
der am selben benutzt wurde.
Nicht, da gibt es unterschiedliche Strategien,
mal funktioniert die eine, mal funktioniert die andere besser.
Nicht jeweils durch entsprechende Hardware-Unterstützung, also Warteschlangen oder irgendwelche Zähler
kann man das dann eben letztendlich in der Hardware machen.
Wie gesagt, für uns als Programmierer ist das transparent,
weil das dann eben durch entsprechende Hardware-Einheiten und Zusatzinformationen in den Cashlines realisiert wird.
Aber eben, wenn ich jetzt also wirklich als Architekt von Computerhardware rangehen würde,
um jetzt eben irgendwo in Prozesse zu entwerfen,
dann würde man sich an dieser Stelle an eben entsprechende Gedanken machen.
Schreibstrategie hatte ich ja auch schon angekündigt, nicht,
also waren werden modifizierte Daten des Cashes zurückgeschrieben.
Entweder als Ride through, nicht, das heißt,
die werden direkt und sofort in den Hauptspeicher zurückgeschrieben.
Nachteil kann aber eben sein, dass dann unnötig oft geschrieben wird.
Fright Back die Cashline oder dieses Update im Hauptspeicher passiert,
erst wenn die Cashline quasi jetzt aus dem Cash verdrängt werden würde.
Nicht das ist da effizienzmäßig natürlich besser,
dann habe ich eben genau diese Probleme mit der Cash-Kohärenz,
beziehungsweise das, was es dann eben auch teilweise noch gibt,
also Betriebssystemseitig, dass man eben oder prozesseseitig,
dass man eben sagt, es gibt spezielle Befehle,
mit denen ich dann da so ein Cash-Flash erreichen kann,
beziehungsweise es gibt dann eben auch von Betriebssysteme bestimmte Speicherbereiche,
die dann eben nicht Cashing gekennzeichnet werden.
Gut, Cash-Kohärenz hatte ich ja schon kurz angesprochen.
Da geht es jetzt eben wirklich darum,
wie kriege ich das Ganze letztendlich einheitlich, nicht, also sprich,
ich habe mehrere Prozessoren, die auf einen Speicherbereich darauf zugreifen.
Jetzt liegt aber noch der Cash dazwischen.
Und ich habe jetzt also beispielsweise einen Prozessor,
der also auf Daten zugreift, die im Cash von P1 fliegen.
Dann müsste man halt eben sagen, beim Schreibzugriff muss P1
letztendlich entweder seinen Cash aktualisieren oder den Cash ungültig machen.
Beim Lesezugriff darf dieser Zugriff dann eben nicht auf den Hauptspeicher erfolgen,
sondern es muss irgendeinen Mechanismus gefunden werden, dass der Cash des Prozesses die Daten liefert.
Das passiert dann eben durch das, was man Cash-Kohärenz-Protokoll nennt,
beziehungsweise was dann auch immer als Snooping bezeichnet wird. Das heißt,
die Cashes überwachen quasi Speicherzugriffe generell und stellen dann eben fest,
Wenn jetzt also quasi auf einem globalen Adressbus ein anderer Prozess,
irgendeinen Speicherzugriff auf einen Speicherbereich macht, betrifft das jetzt irgendwelche Werte,
die ich lokal in meinem Cash drin habe und von mir verwaltet werden.
Und dann kann man da eben entsprechende Mechanismen überhaupt erst mal einleiten.
Nicht das Ganze wird dann eben immer im Englischen als Snoobing,
im Deutschen Schnüffeln, mithören, mitlauschen,
wie auch immer man das jetzt übersetzen möchte, bezeichnet.
So, für diese Cash-Strategien gibt es dann sehr viele unterschiedliche Protokolle,
werde ich jetzt also gar nicht weiter vorstellen, sondern auch gleich so ein bisschen vorspringen.
Also die sind hier entsprechend aufgelöstet, das,
was man meistens in Little Little Literatur oder in Lehrbüchern immer findet,
ist ein Mesi-Protokoll, setzt sich zusammen aus Modified,
Exclusive Shared und Invallet, wo es dann darum geht,
für Busmaster beziehungsweise für jetzt eben irgendeine andere CPU,
also ein Client, wie für jedes Cash-Element,
welcher Status gilt dort.
Und das Ganze wird dann typischerweise immer in Form irgendwie solcher Automatendiagramme beschrieben,
also hier auch noch mal so eine Anwendung für endliche Automaten und Hardwareseitig,
also sprich von den Herstellern der Cashes, wird das dann eben genauso,
dann eben auch irgendwie als ähnliche Automat letztendlich implementiert.
Gut, das eigentlich soweit zu den Cash-Zugriffen. Hier noch
mal kurz zusammengefasst, Optimierung der Cash-Zugriffe. Ich hätte diese mittlere Speicherzugriffszeit,
hatte ich ja schon kurz erklärt, wie kann man Cash-Zugriffe optimieren?
Gut, indem ich jetzt natürlich hier die einzelnen Faktoren,
beziehungsweise Therme, entsprechend kleiner mache. Das heißt also entweder mit einer kleineren Mist-Time erreiche,
indem ich, was ja nun eben auch passiert,
entsprechend viele Cash-Ebenen reinbringe, hier irgendwelche anderen Strategien fahre,
Critical World First, also im Prinzip das Speicherwort, was also genau adressiert wird,
wird als erstes gelesen und dann erst der Rest des Cash-Beichers aufgefüllt und noch diverse andere Verfahren.
Dann kann ich sagen, Missrate kleiner machen,
das kann man mit größeren Cashes machen. Nachteil ist natürlich,
es kostet mehr Hardware, eine höhere Assoziativität. Also sprich,
nicht nur Direct Map, sondern zweifach, vierfach,
achtfach assoziative Cashes, aber auch das kostet mehr Hardware
und macht die Cashes letztendlich wieder langsamer.
Oder es gibt dann eben noch diverse Optimierungstechniken,
die dann eben dort auch noch
mit reinspielen können
Gut, Cash-Effekte, nicht klassisch, sind dann eben solche Cash-Effekte über Matrix-Zugriffen.
Also die Folie hatte ich ganz am Anfang ja noch,
also auch schon mal,
nicht wo ich dann eben bei irgendwelchen Erem zugriffen,
entweder zahlenweise oder spaltenweise arbeite und dann eben unterschiedliche Laufzeiten und unterschiedliche Ergebnisse gelegt gegebenenfalls auch bekomme.
Nicht das sind eben, zumindest in Bezug auf die Laufzeiten,
dann eben typische Cash-Effekte, weil also gerade bei direkt abgebildeten Cashes
kann ich also durch entsprechende Zugriffsmuster eben genau so ein Cash-Slashing erzeugen oder auch nicht.
Und dadurch also drastische Änderungen im Laufzeitverhalten provozieren. Gut,
das ist dann hier nochmal im Einzelnen jetzt, dass es für unterschiedliche Beispiele genauer aufgeschlüsselt.
Also auch hier möchte ich jetzt noch kurz rübergehen.
Hier dann nur noch ein paar Fotos,
Chip-Layout von eingebetteten Prozessoren beziehungsweise hier von aktuellen Prozessoren,
nur um mal auch vom Vergleich her zu zeigen,
womit also das Elizium, was man teuer gewitzt halt hat,
also eigentlich gefüllt ist.
Also hier beim Armprozessor. Also hier sind die eigentlichen Recheneinheiten.
Hier habe ich Memory Management Unit, das ist Instruktionscash,
das ist Datencash. Das heißt also,
hier sieht man schon mal einen Großteil des Siliziums,
das ist eigentlich mit Cashes Fall, beim AM10 genau das Gleiche.
Hier den, ja inzwischen also fünf Jahre alten Intel,
also die erste I7-Generation ist das,
also wenn eine Hail im Core vier CPUs Innen drinnen,
also im Prinzip First-Level-Cash, Second-Level-Cash, sind dann diese Bereiche,
Third-Level-Cash ist dann dieses hier.
Das Gleiche dann eben bei AMD-Prozessor, hier die CPUs und
dann also hier entsprechend First-Level-Cash ist hier mit drin,
Second-Level-Cash und alles DCS, Third-Level-Cash nicht.
Also auch hier kann man sagen,
also Pi mal Daumen, die Hälfte des Siliziums ist also
auch hier mit Cashes gefüllt
Gut, hier nochmal für die Programmierung, generelle Empfehlung,
nicht also was ist letztendlich gut für die Ausnutzung von Cash,
zeitliche und räumliche Lokalität, kleiner Working Set und kleine sogenannte Strides, also Adressfortschaltung. Gut,
da muss man jetzt natürlich sagen, das ist vom Algorithmus abhängig,
wenn ich einen Algorithmus oder ein Problem habe,
wo ich viel Speicher brauche, dann kann ich nicht sagen,
ich habe einen kleinen Working Set,
ich habe aber generell sollte man einfach als Programmierer schon mal sagen,
also ich versuche Nicht unendlich viel Speicher zu verbraten,
sondern gucke schon, dass sie das so ein bisschen kleiner halte,
weil das wirkt sich dann eben auch entsprechend drastisch beim Cashing aus.
So, da das Ganze eigentlich nochmal zusammengefasst. Gut,
jetzt möchte ich nur nochmal, wobei wir jetzt also zeitlich
hier schon relativ knapp werden und nochmal ganz kurz erwähnen, was ist virtueller Speicher?
Da geht es jetzt eben nochmal darum, das,
was ich jetzt quasi als zwischen CPU Und Hauptspeicher gesetzt habe,
noch mal weiter zu erweitern, in Richtung Festplattenspeicher,
weil als Programmierer sage ich, ich habe einen linearen Adressraum,
der ist möglichst groß, 32 Bit, ja gut,
das ist inzwischen veraltet, inzwischen sage ich, okay,
64 Bit-Prozessoren,
die möchte ich eigentlich ansprechen können.
Linear adressierbar. Das Betriebssystem sagt,
ich habe jetzt nicht nur ein Programm, sondern ich habe mehrere Programme,
Klaas, Prozesse, wie auch immer ich das nenne.
Ich habe aber nur einen begrenzten Speicher zur Verfügung
und der ist in der Regel keine 2 hoch 64,
bald groß, sondern deutlich kleiner.
Das heißt also, ich habe hier meinetwegen jetzt also
irgendwie 8 Gigabyte Hauptspeicher. Es kann jetzt aber sein,
dass ein einzelnes Programm schon mehr verbraten hat oder es kann eben sein,
dass also die Summe aller Programme, die laufen, mehr benötigen.
Dann möchte das Betriebssystem natürlich sagen, parallel laufende Prozesse sollen speichermäßig voneinander getrennt werden. Das heißt,
ich möchte an ihm noch irgendwelche Sicherheitsmechanismen Zugriffsrechte haben und ich möchte eben auch gleich mit reinbringen,
dass ich sage, alles, was Kot ist, ist ried only,
alles, was Daten ist, darf ried right sein.
Dazu gibt es dann eben zwei Stichworte,
virtueller Speicher und dann eben Paging bzw. Segmentierung als Verwaltungstechniken davon.
Virtueller Speicher ist grob gesagt eben einfach erstmal nichts anderes,
als dass ich sage, von dem gesamten Adressraum,
den jetzt alle Programme oder alle Tasks belegen können,
ist eben wirklich nur ein kleiner Teil im Hauptspeicher und nicht benötigter Teil,
ist auf die Platte ausgelagert.
So, dadurch, dass inzwischen seine Hauptspeicher vergleichsweise günstig ist,
tritt das jetzt also nicht mehr ganz so häufig auf,
wie jetzt also vielleicht noch vor zehn Jahren,
nicht aber im Prinzip kann es eben schon sein,
dass man sagt, ich habe nicht alles,
was ich als Programm habe,
im Hauptspeicher,
sondern Teil
davon auf die Platte ausgelagert
Und das ist eben quasi die Erweiterung von Speicher auf die Platte etwas,
was man dann eben als virtuellen Speicher bezeichnet. Das heißt,
für ein einzelnes Programm oder eben auch für die Menge aller Programme,
also sprich das, was das Betriebssystem verwaltet, kann der Speicher größer sein, als der physikalische Hauptspeicher. Wenn der Speicher größer ist,
das, was dann passieren wird, ist,
dass der Rechner natürlich sehr langsam wird,
wenn jetzt also andauernd irgendwas auf die Platte geschrieben wird oder zurückgelesen wird,
weil die Platte eben verglichen, mit, nicht CPU-Geschwindigkeit,
300 Pico-Sekunden, Cash-Speicher, eine Nano-Sekunde,
das heißt, da bin ich schon so mit drei,
ich hatte vorhin zehn gesagt, bis zehn Tagen dabei,
Hauptspeicher, acht Nano-Sekunden, so und wie gesagt,
bei der Festplatte ist man im Millisekunden-Bereich,
demzufolge brauche ich da dann also wirklich jetzt als Miss-Penalty entsprechend viele Zyklen.
Das heißt, da sollte ein recht guter Mechanismus da sein,
der dann quasi diese Abbildung von Speicher in die Festplatte letztendlich überwahren.
Das ist aber das, was dann Virtual Memory im Prinzip
ist und was dann also die Speicherhierarchie dann entsprechend nach unten hin ergänzt und erweitert.
Gut, das Ganze wird verwaltet, dann eben durch diese
Memory Management Unit. Das ist dann eben die Einheit,
die dafür sorgt, dass ich eben aus virtuellen Adressen der CPU
physikalische Adresse im Hauptspeicher bekomme
Letztendlich passiert das nichts anderes als über Tabellen,
in denen hinterlegt ist für ein laufendes Programm,
mit welchen Offsets quasi aus den Adressen hier Hauptspeicheradressen gemacht werden.
Um solchen virtuellen Speicher umzusetzen,
gibt es dann zwei verschiedene Konzepte, Segmentierung und Paging,
rein praktisch hat man inzwischen eigentlich beides gemeinsam mit Segmentierung,
wird von der Idee her bezeichnet, dass ich das,
wie hier angedeutet, quasi nach Programmunterteile.
Also ich habe hier einen Prozess 1,
habe hier mein Textsegment, mein Datensegment mit irgendwelchen Adressen.
Ein Prozess 2. Hier sieht man eben auch die überlappenden Adressbereiche.
Und das, was die Memory Management Unit zur Laufzeit macht,
ist, dass sie eben sagt,
dieser Teil hier wird irgendwo hier in den Speicherbereich eingeblendet.
Dieser Teil wird irgendwo hier in den Speicherbereich eingeblendet und so
weiter und so fort. Und dann gibt es eben Abfragemöglichkeiten,
wo ich dann eben überprüfen kann, dass ein Programm 2,
wenn es jetzt also quasi läuft, nicht irgendeine Adresse anspricht,
die jetzt also gar nicht zu seinen eigenen Programmen gehört.
Was also zum Beispiel ein Virus vollsuchen würde,
um jetzt also hier aus irgendeinem anderen Bereich Speicherbereich was auszulesen.
Nicht das würde dann eben durch entsprechende Abfragen hier hinsichtlich der
Speicherbereiche passieren. Gleichzeitig können dann hier eben auch solche Mechanismen
wie Read Only und Read Ride
entsprechend einfach implementiert werden
Nicht, das ist also im Prinzip das, was sich Segmentierung nennt.
Paging ist quasi, dass man jetzt sagt,
ich habe Blöcke einer festen Größe, die nennen sich Seiten,
die wir dann auf Hauptspeicherblöcke zugeordnet, es ist dann quasi Kacheln.
Und es gibt eine Page-Table, eine Tabelle,
in der drinsteht, wenn eine Adresse kommt,
ist das im Hauptspeicher oder ist das auf die Platte ausgelagert.
Damit kann man also dann entsprechend effizient seinen virtuellen Speicher realisieren
Und das Ganze kam man dann eben von der Idee her,
mit der Segmentierung verheiraten und dafür sorgen,
dass letztendlich quasi über so eine tabellenartige Zuordnung, also einmal geguckt werden kann,
gehört dieser Adresse des Hauptspeichers dann eben wirklich zu dem passenden Programm,
darf das darauf zugreifen.
Und es passiert dann eben auch gleichautomatisch die Zuordnung von irgendeiner Adresse
in den Hauptspeicherbereich oder wenn das dann eben entsprechend ausgelagert ist auf die Festplatte. Gut,
also das war jetzt im extrem Schnelldurchgang,
weil ich jetzt so die Begriffe nochmal kurz erläutert haben wollte,
virtueller Speicher, Segmentierung und Paging auf den Folien,
wenn man sich das also einzeln anguckt,
ist das also nochmal ein bisschen genauer beschrieben,
beziehungsweise hier also auf diesen hinteren Folien dann also nochmal am Beispiel der Adresskodierung bei X86-Prozessoren ein bisschen weiter beschrieben.
Aber wie gesagt, das ist dann eigentlich ja schon immer ein bisschen spezieller,
gerade in Bezug, also auf die Art und Weise,
wie das also ein Betriebssystem beziehungsweise eine Prozessorarchitektur letztendlich umsetzt.
Also wie gesagt, das, was man eigentlich immer nur wissen müsste,
ist virtueller Speicher, Auslagerung von Daten,
Realisierung von Schutzmechanismen und dass das dann eben durch Hardware-Mechanismen,
aber eben auch durch Eigenschaften des Betriebssystems unterstützt wird.
Gut, ich hoffe, ich habe damit zumindest ein bisschen motiviert,
also nochmal in diesen Teil reinzugucken, wenn einen das genauer interessieren sollte.
Ansonsten soll das jetzt der Vorlesungsstoff der diesjährigen Vorlesung und Rechnerstrukturen
gewesen sein. Die Folien in Komplettausgabe sind seit Dienstag
auf der Webseite bzw. über Stine zugreifbar und Ja,
übermorgen werden wir uns dann bei im Audimax 2 dann zur Probeklausur einfinden.
Da werde ich noch ein bisschen was zur Klausur beziehungsweise zu den Sachen sagen.
Nicht dann wird im Prinzip dann ähnlich wie in der Klausur
entsprechendes Teil einmal geschrieben und Anfang nächster Woche Dienstag beziehungsweise am Mittwoch
ist ja dann nochmal Tutorium beziehungsweise die Besprechung auf der Probeklausur.
Ich hoffe, dass wir das dann auch so weit hinkriegen.
Das soll dann also auch als Lecture-to-go aufgenommen werden,
beziehungsweise dann auch um eine entsprechend kurzfristigen Zugriff hinzukriegen,
dann also auch live gestreamt werden
Gut, ansonsten dann Schluss für heute,
Ende der Vorlesung und nächsten Termin
dann eben nochmal
die Probeklausur